Controlling Positional Servos with Python

In our first installment of this series we discussed the theory of operation for continuous rotation servos that spin continuously in either direction.  Positional servos are slightly different.  They operate under the assumption that we only want the servo to turn to a certain position and then stop.  In fact, the positional servo will prevent us from turning beyond certain limits.  Generally they have a 90-180 degree range of motion, but there are many different varieties that can turn to different limits.  However, the theory of operation is going to be identical for nearly all positional servos.

Check out the video demo here: https://youtu.be/wAPUyItqpRs

The connection details and basic code will be the same as for continuous rotation servos, so see the previous blog post for that information.

These servos are driven by a stream of pulses, just like the continuous rotation servos we discussed previously. But now the pulse duration is used to control the position of the servo arm, rather than the direction/speed of rotation.

Positional servos operate with the following rules, based on the duration of the pulses sent every 20 ms:

  1. If the pulse is high or “ON” for 1.0 ms during those 20 ms then the Servo will position itself to its standard clockwise position
  2. If the pulse is high or “ON” for 1.5 ms during those 20 ms then the Servo will position itself to its center position (halfway in between standard clockwise and standard counterclockwise)
  3. If the pulse is high or “ON” for 2.0 ms during those 20 ms then the Servo will position itself to its standard counterclockwise position

You can also set anything in between to get an intermediate position.  For example: setting the pulse high for 1.2 ms will position the servo at 60% from center in the clockwise direction.  See the table below for more values.

Pulse High Time

Percent Clockwise from Center

Degree Turn from Center (typical)

1.0 ms



1.1 ms



1.2 ms



1.3 ms



1.4 ms



1.5 ms



1.6 ms



1.7 ms



1.8 ms



1.9 ms



2.0 ms




Note: Many servos will respond to pulse durations outside the limits stated above! Experiment with your servo to see what its full range of motion really is. Try shorter and longer pulses, for example 0.5 ms and 2.5 ms pulse widths. The true p_min and p_max values can become constants in your Python code!


Servo Position Feedback and Jitter

A positional servo is different from a continuous rotation servo in that there is no default OFF position.  If you set the continuous servo to 1.5 ms, it will stop rotating and the motor will generally stop completely.  The positional servo is different.  If you set it to 1.5 ms, it will continuously attempt to move the servo to the zero-degree position. Try as you might to turn the servo-arm after it is set, it will always try to get back to its set position.  One example use is setting the position of a ship’s sail.  You don’t want the wind to push the sail to a new position once it has been set!  You always want it to stay in position regardless of outside forces. 

Python with Robots - Control loop

Servos hold their position by using a control loop. If you want to learn more about how that works, check out our Python with Robots curriculum where you build one from scratch in Python!

With low-cost servos the feedback is provided by a small potentiometer, which can sometimes produce a "noisy" signal - making the control circuit think the servo arm has moved a bit and needs to be repositioned... even when it is sitting still. That can cause "jitter" - you'll hear the motor buzzing a bit, and maybe see the servo arm shake back and forth like its had a bit too much coffee!