Hobby Servo Examples - Adafruit Circuit Playground Bluefruit

The following short Python programs demonstrate operation of hobby circuit actuators using the Adafruit Circuit Playground Bluefruit (CPB) board. These assume the board has an external hobby servo and power battery circuit attached.

Each can be run by copying the program into code.py on the CIRCUITPY drive offered by the board. The text can be pasted directly from this page, or each file can be downloaded from the CircuitPython sample code folder on this site.

Related Pages

Essential Documentation

Hobby Servo Summary

  • A hobby servo is a closed-loop actuator: it uses a position sensor to control the output shaft to a commanded angle.

  • The output has limited travel. The LKY62 has a nominal range of 180 degrees but the travel limits are actually somewhat more.

  • Internally it includes a DC motor, gear train, position sensing potentiometer, and a control circuit.

  • The output shaft is splined (i.e. grooved) and supplied with matching molded plastic servo horns. The horns are the only practical way to connect to the output.

  • The horns are used with tendon lines (tension-only) or pushrods (push or pull) to connect the movement to a mechanism.

  • The LKY62 servos typically operate on 5 to 6 Volts and can draw upwards of 1000 mA (much more than the CPB output).

  • The command signal is a pulse train emitted at 50 Hz (every 20 msec). Each pulse is about 1 to 2 msec long and the pulse length encodes the target angle.

Hobby Servo Power Circuit

The CPB VOUT power output is intended only for small external sensors and it not sufficient to run even a medium-size hobby servo. The following diagrams illustrate how to use an external 4-AA battery pack to power a hobby servo driven by the CPB.

../_images/CPB-Servo-circuit.png

Schematic diagram showing the connections between a 4-AA battery pack, hobby servo, and CPB board. The small solderless breadboard is one possible approach for setting up the wiring; each row of five sockets connect together, so in this configuration it is joining the wires of like colors. On the CPB, any of the three GND pads may be used.

../_images/CPB-Servo-full.jpg

Photo of a physical realization the circuit. The clip jumper wires loop out of the photo from the CPB and down to the boardboard. The servo leads loop out of the photo and back to short male-male jumper wires which connect to the breadboard. The battery pack has breadboard-compatible leads; the red lead is positive and connects to the red wire (center) on the servo. The batteries are rechargeable NiMH AA, although alkaline also work.

../_images/CPB-Servo-detail.jpg

Detail photo centered on the breadboard.

Servo Sweep

This minimal sketch demonstrates the basic configuration for setting up a servo output and issuing motion commands. The resulting movement is shown in the following video.

Direct download: cpb_servo_sweep.py.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# cpb_servo_sweep.py

# Demonstrate oscillating movement of a hobby servo.  Note that only a tiny
# micro-servo (e.g. "SG90 9g") is safe to drive directly off the board; in
# general, hobby servos require a separate battery supply.  The wiring for this
# is as follows:
#
#  1. The servo control line (typ. orange) connects to SDA A5  
#  2. The servo ground line  (typ. brown)  connects to GND     
#  3. The servo power line   (typ. red)    connects to 6V battery

# Related documentation:
# https://circuitpython.readthedocs.io/en/latest/shared-bindings/pwmio/index.html#module-pwmio
# https://circuitpython.readthedocs.io/projects/motor/en/latest/api.html#module-adafruit_motor.servo

# ----------------------------------------------------------------
# Import the standard Python time functions.
import time

# Import the low-level hardware libraries.
import board
import pwmio

# Import the Adafruit helper library.
from adafruit_motor import servo

# ----------------------------------------------------------------
# Initialize hardware.

# Create a PWMOut object on pad SDA A5 to generate control signals.
pwm = pwmio.PWMOut(board.A5, duty_cycle=0, frequency=50)

# Create a Servo object which controls a hobby servo using the PWMOut.
actuator = servo.Servo(pwm, min_pulse=1000, max_pulse=2000)

# ----------------------------------------------------------------
# Begin the main processing loop.
while True:
    print("Starting cycle.")
    for angle in range(0, 180, 5):
        actuator.angle = angle
        time.sleep(0.02)

    print("Reversing cycle.")
    for angle in range(180, 0, -5):
        actuator.angle = angle
        time.sleep(0.02)

    print("Pausing.")
    time.sleep(0.5)
    

Sine Servo

This sketch moves the servo back and forth in a smooth motion. It is constructed as a non-blocking event loop, so this is a more practical starting point for combining with with additional sensor and actuator code. The resulting movement is shown in the following video.

Direct download: cpb_sine_servo.py.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# cpb_sine_servo.py

# Demonstrate oscillating movement of a hobby servo using a non-blocking event
# loop structure.  This program style supports operating multiple devices for
# input and output.

# Note that only a tiny micro-servo (e.g. "SG90 9g") is safe to drive directly
# off the board; in general, hobby servos require a separate battery supply.
# The wiring for this is as follows:
#
#  1. The servo control line (typ. orange) connects to SDA A5  
#  2. The servo ground line  (typ. brown)  connects to GND     
#  3. The servo power line   (typ. red)    connects to 6V battery

# Related documentation:
# https://circuitpython.readthedocs.io/en/latest/shared-bindings/pwmio/index.html#module-pwmio
# https://circuitpython.readthedocs.io/projects/motor/en/latest/api.html#module-adafruit_motor.servo

# ----------------------------------------------------------------
# Import standard Python modules.
import time, math

# Import the low-level hardware libraries.
import board
import pwmio

# Import the Adafruit helper library.
from adafruit_motor import servo

# ----------------------------------------------------------------
# Initialize hardware.

# Create a PWMOut object on pad SDA A5 to generate control signals.
pwm = pwmio.PWMOut(board.A5, duty_cycle=0, frequency=50)

# Create a Servo object which controls a hobby servo using the PWMOut.
actuator = servo.Servo(pwm, min_pulse=1000, max_pulse=2000)

# ----------------------------------------------------------------
# Initialize global variables for the main loop.

phase_angle = 0.0
phase_rate  = 2*math.pi / 6.0  # one cycle per six seconds, in radians/second
next_servo_update = time.monotonic_ns()
next_status_update = time.monotonic_ns()

# ----------------------------------------------------------------
# Enter the main event loop.
while True:
    # Read the current integer clock.
    now = time.monotonic_ns()

    # If the time has arrived to update the servo command signal:
    if now >= next_servo_update:
        next_servo_update += 20000000  # 20 msec in nanoseconds (50 Hz update)
        actuator.angle = 90 + 90 * math.sin(phase_angle)
        phase_angle += phase_rate * 0.020

    # If the time has arrived to display the status:
    if now >= next_status_update:
        next_status_update += 500000000  # 0.5 sec in nanoseconds (2 Hz update)
        print(actuator.angle)