I just updated my code to use pigpio instead of RPi.GPIO, the later is working but my robot is trembling like a chihuahua, so I gave pigpio a try.

In this piece of code I'm moving my servo, so to move it 90 degrees I was sending 7.07 , based on this calculation (my servo goes up to 270 degrees):

def AngleCalculation(angle):
     return float(angle) / 27 + 2

and the result would be applied here:

def ExecuteRotationOnServo(angle):

now after update to pigio the same angle doesn't move the servo at all, but I did notice that with big numbers like 100 or 150 it does move (not in the correct angle), with 200 or 10 it doesn't (I couldn't understand why, the documentation says that 0-255 should work):

def ExecuteRotationOnServo(angle):

After reading the documentation I'm even more confused, I can't see any units or formula to get angles to work with it (I'm new to this so maybe it is just my ignorance), googling didn't help at all, just found this link with a formula but in it the answer assumes that I know the pulse width of an specific angle (and I have no clue, my previous code were happy with simple numbers)

How can I convert angles into something that pigpio can understand?

Why aren't angles the basic unit for this kind of things? (I'm assuming that angles is way less accurate or something like that?)

  • Yes, I usually start with duty cycles, then write a function to convert angles to duty cycles, I also define even higher level abstractions/functions, eg, concert "Middle" to 90 degrees "Far left" to zero degrees. You can find a demo program in my answer below: raspberrypi.stackexchange.com/questions/98467/….
    – tlfong01
    Commented Apr 29, 2020 at 2:51
  • PS - Of course you can do even higher level things, such as "North" converted to "90 degrees", North West West fo 45 degrees etc.
    – tlfong01
    Commented Apr 29, 2020 at 2:53
  • 1
    This is how servos work! There is no absolute angle/duty cycle relationship. You might want to try gpiozero.Servo which is probably easier to use. AngularServo might be more relevant.
    – Milliways
    Commented Apr 29, 2020 at 7:05

2 Answers 2


You probably ought to be using the set_servo_pulsewidth method.

Servos are not controlled by PWM dutycycle, that is a misunderstanding of how servos work. It just so happens that for one particular frequency you need a particular dutycycle to send a particular pulse width. Forget PWM and dutycycles.

For most hobby servos the following applies.

A pulse width of 1500 µs moves the horn to the centre position.

An increase in pulse width of 10 µs moves the horn 1 degree clockwise.

An decrease in pulse width of 10 µs moves the horn 1 degree counterclockwise.

E.g. to centre the horn use 1500 µs. To move the horn to 45 degrees use 1500+450 so 1950. To move the horn to -45 degrees use 1500-450 so 1050.

Each servo is slightly different so check your servos.

Generally servos expect pulses in the range 1000 to 2000 for about 100 degrees of travel.

The small 9g servos can generally cope with pulses in the range 500 to 2500 for 200 degrees of travel.

WARNING: check your servos. Sending pulses outside the range they expect can destroy them.

  • thanks, that calculation did the trick to transform my angles and have it working as it was before.
    – pau Fer
    Commented Apr 30, 2020 at 19:54

the answer that joan gave does give an approximation of where the angles are, but the more you go from centre the less accurate it is, at the end to get a perfect relation between the exact angle and the exact equivalent in pulse width I used a simple rule of 3:

I basically put my motor in the exact centre (in my case 1435), then I kept manually adding pulse width until the motor was at 1.5708 radians (90 degrees), in my case that is 2125 pw, so now we know that 2125 - 1435 (690) is exactly 1.5708 radians (90 degrees), which means that

1 Radian is 439.267642 (690 / 1.5708).

now I can easily give any angle and get exactly how many radians that is

enter image description here

 def ConvertRadsInPulseWidth(angle):
    everyRadianInPulseWidth = 439.267642
    rounded = "{:.10f}".format(float(angle))
    pulseWithFromRadians = (everyRadianInPulseWidth * float(rounded))

    moveFromCentre= 1435 + pulseWithFromRadians

    return moveFromCentre

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.