I changed my servos for a more powerful one and cannot get it to work, I believe it is because I can't get the right duty cycle calculation in the code


I have a robotic arm that I started programming for fun, got everything working but the servos that came with the arm where way too weak, someone recommended this one which sure look more robust, today it arrived so I thought it would be just about replace it, for my surprise it doesn't work at all.

after investigating I think it'S because I didn't set the right duty cycle, I never heard about it before but I tried to calculate it with information I found on internet, but after hours I still couldn't get it to work properly.

sometimes it moves but definitely not to the right angle and it is not consistent, but because I'm new in all of this I don't even know if that is the reason.

I'm unsure if I only need to update the SERVO_MIN_DUTY or if I must change the hertz when I set up the GPIO PWM, too.


This is the old servo:

  • Operating Speed : 0.17sec / 60 degrees (4.8V no load)
  • Operating Speed : 0.13sec / 60 degrees (6.0V no load).
  • Stall Torque : 13 kg-cm (180.5 oz-in) at 4.8V;
  • Stall Torque : 15 kg-cm (208.3 oz-in) at 6V.

this is the new servo:

  • Item: DS3218 20KG Large Torque Digital Servo
  • Stall Torque (5V): 19 kg/cm (263.8oz/in)
  • Stall Torque (6.8V): 21.5 kg/cm (298.5 oz/in)
  • Speed : 0.16 sec/60°(5V) / 0.14 sec/60°(6.8V)
  • Operating Voltage: 4.8 ~ 6.8 DC Volts
  • Dead brand: 3μs
  • Weight: 60 g
  • Motor Type: DC Motor Gear
  • Type: Copper & Aluminum
  • Working frequence: 1520μs / 333Hz
  • Size: 40 x 20 x 40.5 mm
  • Features:
    • High performance digital standard servo
    • High-precision metal gears with hard anodizing
    • CNC aluminium middle Shell
    • Dual ball bearings

The original code (I tried to update it using the data I found around without success,mostly from this guide)

import RPi.GPIO as GPIO
import time
OFFSE_DUTY = 0.5        #define pulse offset of servo
SERVO_MIN_DUTY = 2.5+OFFSE_DUTY     #define pulse duty cycle for minimum angle of servo
SERVO_MAX_DUTY = 12.5+OFFSE_DUTY    #define pulse duty cycle for maximum angle of servo
servoPin = 12

def map( value, fromLow, fromHigh, toLow, toHigh):  # map a value from one range to another range
    return (toHigh-toLow)*(value-fromLow) / (fromHigh-fromLow) + toLow

def setup():
    global p
    GPIO.setmode(GPIO.BOARD)         # use PHYSICAL GPIO Numbering
    GPIO.setup(servoPin, GPIO.OUT)   # Set servoPin to OUTPUT mode
    GPIO.output(servoPin, GPIO.LOW)  # Make servoPin output LOW level

    p = GPIO.PWM(servoPin, 50)     # set Frequece to 50Hz
    p.start(0)                     # Set initial Duty Cycle to 0
def servoWrite(angle):      # make the servo rotate to specific angle, 0-180 
        angle = 0
    elif(angle > 180):
        angle = 180
    p.ChangeDutyCycle(map(angle,0,180,SERVO_MIN_DUTY,SERVO_MAX_DUTY)) # map the angle to duty cycle and output it
def loop():
    while True:
        for dc in range(0, 181, 1):   # make servo rotate from 0 to 180 deg
            servoWrite(dc)     # Write dc value to servo
        for dc in range(180, -1, -1): # make servo rotate from 180 to 0 deg

def destroy():

if __name__ == '__main__':     # Program entrance
    print ('Program is starting...')
    except KeyboardInterrupt:  # Press ctrl-c to end the program.

So what exactly do I need from there to know exactly how to update the code for any servo?

The item description says 0.16 for 60° so I expected to be able to get it with a rule of 3 (for 180° I could do a 0.16 x 180 / 60 = 0.48s, but that result seems to high for my little understanding).

  • \$\begingroup\$ you have to use a power supply, otherwise the servo will not move \$\endgroup\$
    – jsotola
    Apr 5, 2020 at 22:49
  • 1
    \$\begingroup\$ Possible help here arduino.stackexchange.com/questions/58232/cant-drive-servo \$\endgroup\$
    – elchambro
    Apr 6, 2020 at 0:54
  • 1
    \$\begingroup\$ How is the power supply holding up under the bigger load of these new servos? \$\endgroup\$
    – user16324
    Apr 6, 2020 at 10:11
  • \$\begingroup\$ this is correct! After updating the servo I also put the voltage up to the recommended by the servo description, but it looks like it is not enough, if I put it up to 9v (more than it is supposed to be, but I assume my power supply also give less amp) the servo comes back to live, I assumed it was the code because I had the recommended voltage and changes in the code would make the servo move sometimes (still do not understand why) How do I manage this situation in terms of accepted answer in a comment? \$\endgroup\$
    – pau Fer
    Apr 6, 2020 at 10:19
  • \$\begingroup\$ If you increased the PSU to 9V you may have damaged the servos. You probably need a PSU with higher rated current, not voltage. \$\endgroup\$
    – user16324
    Apr 6, 2020 at 15:50

2 Answers 2


You should not have needed to change any code if both servos have the same angle limits.

The digital servo does not need a pulse 333 times per second.

0.16sec/60° is the shaft speed, not the HI pulse required. The pulse should still be 1500us for center, 1000us for one extreme and 2000us for the other extreme.

  • \$\begingroup\$ @ChrisStratton What makes his inputs oddball? They look standard as far as I can tell. The servos are fairly standard too. \$\endgroup\$
    – DKNguyen
    Apr 7, 2020 at 14:01

5 volt at 3 amps and the servo works 100%, the problem is that even with the correct voltage I didn't have enough amp to push the servo.

I also found this guide that helped a lot in terms of calculating and understanding the limits of my servos as it explains every single step and the whole maths behind it in a very simple way (I read quite a few and was always confuse about the whole thing)

  • 1
    \$\begingroup\$ You should not need to power your servo from 9V, and you should not do it. Get a power supply that can deliver the needed current at the specified voltage. I have a couple of DS3218 servos just like yours. They run just fine on the specified voltage. \$\endgroup\$
    – JRE
    Apr 6, 2020 at 14:26
  • \$\begingroup\$ Hi JRE, thanks for answering once more, I can see in the servo description that a recommended voltage is between 4.8 ~ 6.8, with 9 it is 100% working as I expected, played with it for hours yesterday, but I understand it is not ideal, I assume that the problem is that my power supply do not give enough amp at 6 volts but I cannot see any amp indication in the servo description, only volts, is there something I should be looking for to know it before hand? (I'm still learning and would like to know those things) \$\endgroup\$
    – pau Fer
    Apr 7, 2020 at 8:58
  • \$\begingroup\$ I put it in a 5v with 3 amp and it works perfectly fine too,edited the answer, thank you for the advice JRE (still unsure if that is too much amp though!) \$\endgroup\$
    – pau Fer
    Apr 7, 2020 at 9:28
  • 1
    \$\begingroup\$ The servo will only take the current it needs. Your power supply can deliver up to 3A, but won't force the servo to take all 3A. \$\endgroup\$
    – JRE
    Apr 7, 2020 at 9:29
  • \$\begingroup\$ I see, I didn't know that, when I was studying about this I basically put in my head that every device received W , which is basically V x A, so I assumed there were no difference in which one is bigger as long as the W is about right, I will investigate, thank you again for your time \$\endgroup\$
    – pau Fer
    Apr 7, 2020 at 9:32

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.