Let's look at the most basic example from the Servo guide:
import time
import board
import pulseio
from adafruit_motor import servo
# create a PWMOut object on Pin A2.
pwm = pwmio.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)
This works fine for us if we only have one servo, and we don't have anything else that we want to happen at the same time. But once we add in another thing, we'd have the same trouble as before — time.sleep() delaying our other actions unintentionally.
In the next version we adopt the "is it time yet" approach in order to avoid the use of time.sleep():
# SPDX-FileCopyrightText: 2020 FoamyGuy for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
This example script shows how to sweep servo(s) without using
time.sleep().
"""
import time
import board
import pwmio
from adafruit_motor import servo
SERVO_LIST = [
{
"MAX_ANGLE": 180,
"MIN_ANGLE": 0,
"PREV_TIME": -1,
"PIN": board.A1,
"DELAY_BETWEEN": 0.05,
"SERVO": None,
"MOVE_BY": 5
}
]
for cur_servo in SERVO_LIST:
pwm = pwmio.PWMOut(cur_servo["PIN"], duty_cycle=2 ** 15, frequency=50)
# Create a servo object.
cur_servo["SERVO"] = servo.Servo(pwm)
while True:
# Store the current time to refer to later.
now = time.monotonic()
for servo in SERVO_LIST:
if now >= servo["PREV_TIME"] + servo["DELAY_BETWEEN"]:
try:
servo["SERVO"].angle += servo["MOVE_BY"]
except ValueError as e:
if servo["MOVE_BY"] > 0:
servo["SERVO"].angle = servo["MAX_ANGLE"]
else:
servo["SERVO"].angle = servo["MIN_ANGLE"]
if servo["SERVO"].angle >= servo["MAX_ANGLE"] or \
servo["SERVO"].angle <= servo["MIN_ANGLE"]:
servo["MOVE_BY"] = -servo["MOVE_BY"]
servo["PREV_TIME"] = now
This version also moves the configuration for the servo sweeping into a list of dictionaries so that additional servos with different sweeping effects can be added easily.
To add an additional servo, you would make a copy of the dictionary that is in SERVO_LIST and change any of the fields that we want to the new desired parameters:
{
"MAX_ANGLE": 90,
"MIN_ANGLE": 45,
"PREV_TIME": -1,
"PIN": board.A2,
"DELAY_BETWEEN": 0.03,
"SERVO": None,
"MOVE_BY": 5
}
SERVO and PREV_TIME should be left as their default values. The rest of the code will fill them in when needed. MAX_ANGLE and MIN_ANGLE are the degrees at which the servo will turn around to move the opposite direction.
PIN is the IO pin that the servo is connected to.
DELAY_BETWEEN is how long it will wait between each servo step. This is in seconds, and you likely want to keep it pretty small in most situations.
MOVE_BY is how many steps the servo will take each time it moves.
Here is an example of a list with two servos in it. You could continue adding more if you wanted.
SERVO_LIST = [
{
"MAX_ANGLE": 180,
"MIN_ANGLE": 0,
"PREV_TIME": -1,
"PIN": board.A1,
"DELAY_BETWEEN": 0.05,
"SERVO": None,
"MOVE_BY": 5
},
{
"MAX_ANGLE": 90,
"MIN_ANGLE": 45,
"PREV_TIME": -1,
"PIN": board.A2,
"DELAY_BETWEEN": 0.03,
"SERVO": None,
"MOVE_BY": 5
}
]
Page last edited January 22, 2025
Text editor powered by tinymce.