High Level Servo Control

Position Control with Motor Library

The best way to control servos is with a handy Adafruit CircuitPython Motor module which simplifies setting the duty cycle to control servos (and even allows controlling servos from different PWM hardware like the PCA9685 board).

To follow this approach you'll need to install the Adafruit CircuitPython Motor library on your CircuitPython board.  

First make sure you are running the latest version of Adafruit CircuitPython for your board.

Next you'll need to install the necessary libraries to use the hardware--carefully follow the steps to find and install these libraries from Adafruit's CircuitPython library bundle.  Our introduction guide has a great page on how to install the library bundle for both express and non-express boards.

Remember for non-express boards like the, you'll need to manually install the necessary libraries from the bundle:

  • adafruit_motor

You can also download the adafruit_motor folder from its releases page on Github.

Before continuing make sure your board's lib folder has the adafruit_motor folder copied over.

Now connect to the board's serial REPL so you are at the CircuitPython >>> prompt.  Then import the board and pulseio modules as before.  We'll create a PWM output just like as shown in the first section--the motor library will take this PWM output and add an extra level of simple control on top of it:

Download: file
import board
import pulseio
pwm = pulseio.PWMOut(board.D5, frequency=50)

Now let's import the servo submodule from the adafruit_motor module and create an instance of the Servo class from it:

Download: file
import adafruit_motor.servo
servo = adafruit_motor.servo.Servo(pwm, min_pulse=750, max_pulse=2250)

Notice the servo class needs to be told what PWM output the servo is connected to for your board.  If you're following the wiring and this guide it will be a PWM output on board pin 5 (be sure to create this with a 50 hz frequency as shown!).

There are a few optional keyword parameters that you might specify in the initializer too.  These aren't shown and are useful for using very specialized or custom servos with different ranges or pulse width values--for simple servos you don't typically need to set these values:

  • actuation_range - The range in degrees of the servo movement.  The default is 180 degrees.
  • min_pulse - The minimum position pulse length in microseconds (default 1000 us).
  • max_pulse - The maximum position pulse length in microseconds (default 2000 us).

Here we've change the minimum pulse from the default 1000 microseconds to 750, and the default maximum pulse from 2000 microseconds to 2250 to ensure we get the full sweep as some servos differ. Some experimentation may be required!

Controlling the servo is simple once you have the class created, just set the angle property to a value from 0 to 180 degrees!

Download: file
servo.angle = 0
servo.angle = 90
servo.angle = 180

Notice each time you set angle the servo springs to life and moves!

If you don't see the servo moving be sure you have it wired and powered exactly as shown.  Also make sure you've created the PWM output exactly as shown above too (note the 50 hz frequency!).

There's another type of servo class in the module that you might find useful too, the ContinuousServo class.  This is for controlling continuous rotation servos that move completely around like a small motor instead of point at specific angles.  For these servos you control their speed (or throttle).  Create an instance just like with the Servo class above:

Download: file
continuous = adafruit_motor.servo.ContinuousServo(pwm, min_pulse=750, max_pulse=2250)

With these servos you set the throttle property to a value from -1 to 1 (or anything in between, including fractional values).  Where -1 is fully speed 'backwards' and 1 is full speed 'forwards'.  A value of 0 should stop the motor (but your servo might need to be trimmed a bit and have a small value set that stops its movement instead of zero, experiment with values yourself to see).

Download: file
continuous.throttle = -1   # Full backwards
continuous.throttle = 0    # Stop
continuous.throttle = 1    # Full forwards
continuous.throttle = 0.5  # Half speed forwards

Examples

Standard Servo

Here's the complete standard servo sweep example written for the adafruit_motor library.  Remember save this as code.py on your board to have it run:

import time
import board
import pulseio
from adafruit_motor import servo

# create a PWMOut object on Pin A2.
pwm = pulseio.PWMOut(board.A2, duty_cycle=2 ** 15, frequency=50)

# Create a servo object, my_servo.
my_servo = servo.Servo(pwm)

while True:
    for angle in range(0, 180, 5):  # 0 - 180 degrees, 5 degrees at a time.
        my_servo.angle = angle
        time.sleep(0.05)
    for angle in range(180, 0, -5): # 180 - 0 degrees, 5 degrees at a time.
        my_servo.angle = angle
        time.sleep(0.05)

Continuous Servo

Here is an example for a continuous servo:

# Continuous Servo Test Program for CircuitPython
import time
import board
import pulseio
from adafruit_motor import servo

# create a PWMOut object on Pin A2.
pwm = pulseio.PWMOut(board.A2, frequency=50)

# Create a servo object, my_servo.
my_servo = servo.ContinuousServo(pwm)

while True:
    print("forward")
    my_servo.throttle = 1.0
    time.sleep(2.0)
    print("stop")
    my_servo.throttle = 0.0
    time.sleep(2.0)
    print("reverse")
    my_servo.throttle = -1.0
    time.sleep(2.0)
    print("stop")
    my_servo.throttle = 0.0
    time.sleep(4.0)
This guide was first published on Jan 15, 2018. It was last updated on Jan 15, 2018. This page (High Level Servo Control) was last updated on Aug 18, 2019.