0

I am having the problem, that I am not able to control any of my servos I have. I have two servos, one is a normal servo used in model planes and the second one is a micro sized servo.

I wired both of them separately (The signal cable to a GPIO pin and the other two cables first directly to the board and after to a external power source). When I try to run them via the similar python code

...
GPIO.setmode(GPIO.BCM)
GPIO.setup(11, GPIO.OUT)
pwm = GPIO.PWM(11, 50)
pwm.start(2)
timelib.sleep(2)
pwm.ChangeDutyCycle(3)
timelib.sleep(2)
...

the servos sometimes just turn for a bit but then stop on one side. After that you can still hear the servo making noises like it is trying to run further. After it turned to the end I can not make it work or make it turn in any way. It will just stay there whatever input I will make. It will just turn to the same end again if I am manually turn them back to the start position. I can not figure it out what I am doing wrong or where I need to change my way of doing it.

Does anyone have any tips or had a similar problem? I'm thankful for every further tip and further step I will make.

Thanks in advance!

pythoniosIV
  • 237
  • 5
  • 18
  • 1
    This really sounds like a power issue. You're really supposed to drive servos from a separate power supply. However, you can sometimes get away with it if there's only one or two low powered servos connected AND the Pi (or Arduino, etc.) has a high enough wattage power supply connected (>= 2 Amps would likely do it). – Merkle Groot Dec 28 '19 at 20:56
  • @MerkleGroot We did indeed fix it with using a seperate servo controller "hat" by adafruit on the raspberry pi and this was powered by an external power supply. The project was successfully finished and the raspberry was controlling 10+ servos plus 2 motors via a web app "hosted" on the raspberry too. Success! – pythoniosIV Jan 07 '20 at 12:58

2 Answers2

0

The servos position is controlled by the pulsewidth of a 50 Hz PWM signal. Hence, we need to turn the PWM sequence on at 50 Hz. Note that for a 50 Hz signal, the Period of the signal is 1/50=.02 seconds, or 20 milliseconds. Keep this Period in mind as we will come back to it later. We start by creating a PWM object on Pin 11 with a 50 Hz signal with the command:

pwm=GPIO.PWM(11,50)

We can now start the pwm sequence by giving a command to specify the DutyCycle of the signal. Before we do this, we need to talk a little bit about how servos work. A typical servo wants to see a frequency of 50 Hz on the control line. The position it moves to depends on the pulse width of the signal. Most servos behave roughly as such, but you will need to tweak these numbers for your particular servo. Typically, the servo will go to the full left position when it sees a pulse width of 1 millisecond, it will go the middle position when it sees a pulse width of 1.5 millisecond, and it will go to the full right position when it sees a pulse width of 2 millisecond. Note however, that on the Raspberry Pi we do not specify a pulse width, but we specify a DutyCycle. So, we can use the following relationship:

DutyCycle =PulseWidth/Period

Remember that Period = 1/frequency, so:

DutyCycle = PulseWidth/(1/frequency) = PulseWidth * frequency

The PulseWidth that will give us a full left position is 1 milllisecond. We now calculate the applied DutyCycle to give us the desired position:

DutyCycle = PulseWidth*frequency=.001 *50 = .05 = 5%

So, for a 50 Hz signal, if we set the DutyCycle to 5, then we should see the servo move to the full left position. Similarly, if we set DutyCycle to 7.5, we should get the middle position, and if we set it to 10 we should be in the full right position. You can get all the intermediate positions by linearly scaling between 5 and 10. Note that these values will vary between brands, and between individual servos, so play around with your servo to get it calibrated. We are now ready to apply a command to position the servo. If we want the servo in the full left position, we should set the DutyCycle to 5%. We do that with the command:

pwm.start(5)

This will start the PWM signal, and will set it at 5%. Remember, we already specified the 50 Hz signal when we created the pwm object in our earlier commands. Now if we want to change the position, we can change the DutyCycle. For example, if we want to go to the middle position, we want a DutyCycle of 7.5, which we can get with the command:

pwm.ChangeDutyCycle(7.5)

Now if we want the full right position, we want a duty cycle of 10, which we would get with the command:

pwm.ChangeDutyCycle(10)

Remember, it is not DutyCycle that actually controls servo position, it is PulseWidth. We are creating DutyCycles to give us the desired PulseWidth.

Now, play around with your particular servo and then find the specific DutyCycles that lead to full left and full right positions. For my servo, I find that full left is at DutyCycle=2, and full right is at DutyCycle=12. With these values, I can create a linear equation that will give me any angle I want between 0 and 180. This will make the Raspberry Pi behave much more like the simple and intuitive operation of the Arduino.

To do the linear equation I need two points. Well, I know that for a desired angle of 0, I should apply a DutyCycle of 2. This would be the point (0,2). Now I also know that for a desired angle of 180, I should apply a DutyCycle of 12. This would be the point (180,12). We now have two points and can calculate the equation of the line. (Remember, play with your servo . . . your numbers might be slightly different than mine, but the methodology below will work if you use your two points)

Remember slope of a line will be:

m=(y2-y1)/(x2-x1)=(12-2)/180-0)=10/180 = 1/18

We can now get the equation of the line using the point slope formula.

y-y1=m(x-x1)

y-2=1/18*(x-0)

y = 1/18*x + 2

Putting in our actual variables, we get

DutyCycle = 1/18* (DesiredAngle) + 2

Now to change to that position, we simply use the command:

pwm.ChangeDutyCycle(DutyCycle)

See more at: http://www.toptechboy.com/raspberry-pi/raspberry-pi-lesson-28-controlling-a-servo-on-raspberry-pi-with-python/#sthash.LRmf7708.dpuf

Community
  • 1
  • 1
Swastik Padhi
  • 1,849
  • 15
  • 27
  • thanks for your answer. Is it possible that my servos or raspberry got damaged, altough I am able to atleast turn them via the pwm.start() signal? (After I turned them back manually) – pythoniosIV Oct 27 '15 at 06:46
  • @nthommen if you are able to turn the servos both ways then everything is fine. Is that what you are asking? – Swastik Padhi Oct 27 '15 at 09:07
  • right now I am just able to turn them one way and only with the pwm.start() signal and then it will stay at that position and will not turn back somehow. If I will not turn the servo manually back to the position before the pwm.start() signal I am not able to do anything else. – pythoniosIV Oct 27 '15 at 09:29
  • @nthommen Didn't you read my answer completely? Your servo stays at one position quite possibly because `pwm.start(2)` refers to one of the extremes. Executing `pwm.ChangeDutyCycle(3)` after that would only force the servo in the same direction and since the extreme has been reached, it stays there. Try `pwm.ChangeDutyCycle(1)` or `pwm.ChangeDutyCycle(1.5)` to rotate it to the other extreme or to the middle respectively. – Swastik Padhi Oct 27 '15 at 09:43
  • whatever value I will put in pwm.start() it will just turn to the full end and make strange noises. pwm.changeDutyCycles() wont turn anything even if I play completely with these values. It will stop making noises if I call pwm.stop(). If I dont turn the servo back manually and call again pwm.start() with a value it will not do anything at all beside making noises. – pythoniosIV Oct 27 '15 at 17:13
  • @nthommen Consider replacing the servo then. Also, avoid rotating the servo manually. That might harm its gears. – Swastik Padhi Oct 27 '15 at 21:01
0

Alternately, you can use my library which hides most of the pwm and GPIO board complexity. Sample code:

from RaspberryMotors.motors import servos
s1 = servos.servo(11)  #create the servo objects , connected to GPIO board pin #11 
s1.setAngleAndWait(45) # move S1 position of 45 degrees
s1.shutdown()  #will clean up the GPIO board as well`

You can view download the code or the library via any of the two links: https://github.com/vikramdayal/RaspberryMotors or https://pypi.org/project/RaspberryMotors/#description