2

I'm a new entry in the world of Raspberry Pi and Python language. My problem is as follows: I would like to control an micro Servo SG90 (datasheet here) with my Raspberry Pi 3 model B. Looking online I realized that I can control the servo with GPIO.PWM and changing the DutyCycle I can set the servo in a specific degree. In my case DC = 2 is 0º DC = 6.15 is 90º and DC = 10.3 is 180º but this isn't important because at any point the Servo is and I don't run pwm.stop(), it doesn't stand still but continues to shake and sway around that point. How can I fix this?

This is the a example the code:

import RPi.GPIO as GPIO
from time import sleep

GPIO.setmode(GPIO.BOARD)
GPIO.setup(13, GPIO.OUT)
sh = GPIO.PWM(13,50)

sh.start(2)
sleep(3)
sh.ChangeDutyCycle(6.15)
sleep(3)
sh.ChangeDutyCycle(10.3)
sleep(3)

sh.stop()
GPIO.cleanup()

1 Answer 1

4

You are using the wrong tool for the job.

Servos require accurately timed pulses. The RPi.GPIO module uses software timing which leads to all sorts of timing jitter, which leads to a twitching servo, which shortens the life of the servo.

Use something like my pigpio which uses hardware timed pulses.

Try

sudo pigpiod # start daemon
./servo_demo.py 27 # send pulses to GPIO27 (pin 13)
#!/usr/bin/env python

# servo_demo.py
# 2016-10-07
# Public Domain

# servo_demo.py          # Send servo pulses to GPIO 4.
# servo_demo.py 23 24 25 # Send servo pulses to GPIO 23, 24, 25.

import sys
import time
import random
import pigpio

NUM_GPIO=32

MIN_WIDTH=1000
MAX_WIDTH=2000

step = [0]*NUM_GPIO
width = [0]*NUM_GPIO
used = [False]*NUM_GPIO

pi = pigpio.pi()

if not pi.connected:
   exit()

if len(sys.argv) == 1:
   G = [4]
else:
   G = []
   for a in sys.argv[1:]:
      G.append(int(a))

for g in G:
   used[g] = True
   step[g] = random.randrange(5, 25)
   if step[g] % 2 == 0:
      step[g] = -step[g]
   width[g] = random.randrange(MIN_WIDTH, MAX_WIDTH+1)

print("Sending servos pulses to GPIO {}, control C to stop.".
   format(' '.join(str(g) for g in G)))

while True:

   try:

      for g in G:

         pi.set_servo_pulsewidth(g, width[g])
         actual = pi.get_servo_pulsewidth(g)

         #print(g, width[g], actual)

         width[g] += step[g]

         if width[g]<MIN_WIDTH or width[g]>MAX_WIDTH:
            step[g] = -step[g]
            width[g] += step[g]

      time.sleep(0.1)

   except KeyboardInterrupt:
      break

print("\nTidying up")

for g in G:
   pi.set_servo_pulsewidth(g, 0)

pi.stop()
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.