Skip to content

Commit f0a1b0a

Browse files
committed
Add the ability to disable servo motor by setting angle or fraction to None, also renamed examples to pca9685 to separate them from plain-GPIO examples
1 parent 117e146 commit f0a1b0a

File tree

6 files changed

+96
-33
lines changed

6 files changed

+96
-33
lines changed

adafruit_motor/servo.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,17 @@ def set_pulse_width_range(self, min_pulse=750, max_pulse=2250):
5454
def fraction(self):
5555
"""Pulse width expressed as fraction between 0.0 (`min_pulse`) and 1.0 (`max_pulse`).
5656
For conventional servos, corresponds to the servo position as a fraction
57-
of the actuation range.
57+
of the actuation range. Is None when servo is diabled (pulsewidth of 0ms).
5858
"""
59+
if self._pwm_out.duty_cycle == 0: # Special case for disabled servos
60+
return None
5961
return (self._pwm_out.duty_cycle - self._min_duty) / self._duty_range
6062

6163
@fraction.setter
6264
def fraction(self, value):
65+
if value is None:
66+
self._pwm_out.duty_cycle = 0 # disable the motor
67+
return
6368
if not 0.0 <= value <= 1.0:
6469
raise ValueError("Must be 0.0 to 1.0")
6570
duty_cycle = self._min_duty + int(value * self._duty_range)
@@ -102,11 +107,17 @@ def __init__(self, pwm_out, *, actuation_range=180, min_pulse=750, max_pulse=225
102107

103108
@property
104109
def angle(self):
105-
"""The servo angle in degrees. Must be in the range ``0`` to ``actuation_range``."""
110+
"""The servo angle in degrees. Must be in the range ``0`` to ``actuation_range``.
111+
Is None when servo is disabled."""
112+
if self.fraction is None: # special case for disabled servos
113+
return None
106114
return self.actuation_range * self.fraction
107115

108116
@angle.setter
109117
def angle(self, new_angle):
118+
if new_angle is None: # disable the servo by sending 0 signal
119+
self.fraction = None
120+
return
110121
if new_angle < 0 or new_angle > self.actuation_range:
111122
raise ValueError("Angle out of range")
112123
self.fraction = new_angle / self.actuation_range
File renamed without changes.

examples/motor_pca9685_servo_sweep.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import time
2+
3+
from board import SCL, SDA
4+
import busio
5+
6+
# Import the PCA9685 module. Available in the bundle and here:
7+
# https://github.com/adafruit/Adafruit_CircuitPython_PCA9685
8+
from adafruit_pca9685 import PCA9685
9+
from adafruit_motor import servo
10+
11+
i2c = busio.I2C(SCL, SDA)
12+
13+
# Create a simple PCA9685 class instance.
14+
pca = PCA9685(i2c)
15+
# You can optionally provide a finer tuned reference clock speed to improve the accuracy of the
16+
# timing pulses. This calibration will be specific to each board and its environment. See the
17+
# calibration.py example in the PCA9685 driver.
18+
# pca = PCA9685(i2c, reference_clock_speed=25630710)
19+
pca.frequency = 50
20+
21+
# To get the full range of the servo you will likely need to adjust the min_pulse and max_pulse to
22+
# match the stall points of the servo.
23+
# This is an example for the Sub-micro servo: https://www.adafruit.com/product/2201
24+
# servo7 = servo.Servo(pca.channels[7], min_pulse=580, max_pulse=2350)
25+
# This is an example for the Micro Servo - High Powered, High Torque Metal Gear:
26+
# https://www.adafruit.com/product/2307
27+
# servo7 = servo.Servo(pca.channels[7], min_pulse=500, max_pulse=2600)
28+
# This is an example for the Standard servo - TowerPro SG-5010 - 5010:
29+
# https://www.adafruit.com/product/155
30+
# servo7 = servo.Servo(pca.channels[7], min_pulse=400, max_pulse=2400)
31+
# This is an example for the Analog Feedback Servo: https://www.adafruit.com/product/1404
32+
# servo7 = servo.Servo(pca.channels[7], min_pulse=600, max_pulse=2500)
33+
# This is an example for the Micro servo - TowerPro SG-92R: https://www.adafruit.com/product/169
34+
# servo7 = servo.Servo(pca.channels[7], min_pulse=500, max_pulse=2400)
35+
36+
# The pulse range is 750 - 2250 by default. This range typically gives 135 degrees of
37+
# range, but the default is to use 180 degrees. You can specify the expected range if you wish:
38+
# servo7 = servo.Servo(pca.channels[7], actuation_range=135)
39+
servo7 = servo.Servo(pca.channels[7])
40+
41+
# We sleep in the loops to give the servo time to move into position.
42+
for i in range(180):
43+
servo7.angle = i
44+
time.sleep(0.03)
45+
for i in range(180):
46+
servo7.angle = 180 - i
47+
time.sleep(0.03)
48+
49+
# You can also specify the movement fractionally.
50+
fraction = 0.0
51+
while fraction < 1.0:
52+
servo7.fraction = fraction
53+
fraction += 0.01
54+
time.sleep(0.03)
55+
56+
pca.deinit()

examples/motor_servo_sweep.py

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,52 @@
11
import time
2-
3-
from board import SCL, SDA
4-
import busio
5-
6-
# Import the PCA9685 module. Available in the bundle and here:
7-
# https://github.com/adafruit/Adafruit_CircuitPython_PCA9685
8-
from adafruit_pca9685 import PCA9685
2+
import board
3+
import pulseio
94
from adafruit_motor import servo
105

11-
i2c = busio.I2C(SCL, SDA)
12-
13-
# Create a simple PCA9685 class instance.
14-
pca = PCA9685(i2c)
15-
# You can optionally provide a finer tuned reference clock speed to improve the accuracy of the
16-
# timing pulses. This calibration will be specific to each board and its environment. See the
17-
# calibration.py example in the PCA9685 driver.
18-
# pca = PCA9685(i2c, reference_clock_speed=25630710)
19-
pca.frequency = 50
6+
# create a PWMOut object on the control pin.
7+
pwm = pulseio.PWMOut(board.D5, duty_cycle=0, frequency=50)
208

219
# To get the full range of the servo you will likely need to adjust the min_pulse and max_pulse to
2210
# match the stall points of the servo.
2311
# This is an example for the Sub-micro servo: https://www.adafruit.com/product/2201
24-
# servo7 = servo.Servo(pca.channels[7], min_pulse=580, max_pulse=2350)
12+
# servo = servo.Servo(pwm, min_pulse=580, max_pulse=2350)
2513
# This is an example for the Micro Servo - High Powered, High Torque Metal Gear:
2614
# https://www.adafruit.com/product/2307
27-
# servo7 = servo.Servo(pca.channels[7], min_pulse=500, max_pulse=2600)
15+
# servo = servo.Servo(pwm, min_pulse=500, max_pulse=2600)
2816
# This is an example for the Standard servo - TowerPro SG-5010 - 5010:
2917
# https://www.adafruit.com/product/155
30-
# servo7 = servo.Servo(pca.channels[7], min_pulse=400, max_pulse=2400)
18+
# servo = servo.Servo(pwm, min_pulse=400, max_pulse=2400)
3119
# This is an example for the Analog Feedback Servo: https://www.adafruit.com/product/1404
32-
# servo7 = servo.Servo(pca.channels[7], min_pulse=600, max_pulse=2500)
20+
# servo = servo.Servo(pwm, min_pulse=600, max_pulse=2500)
3321
# This is an example for the Micro servo - TowerPro SG-92R: https://www.adafruit.com/product/169
34-
# servo7 = servo.Servo(pca.channels[7], min_pulse=500, max_pulse=2400)
22+
# servo = servo.Servo(pwm, min_pulse=500, max_pulse=2400)
3523

3624
# The pulse range is 750 - 2250 by default. This range typically gives 135 degrees of
3725
# range, but the default is to use 180 degrees. You can specify the expected range if you wish:
38-
# servo7 = servo.Servo(pca.channels[7], actuation_range=135)
39-
servo7 = servo.Servo(pca.channels[7])
26+
# servo = servo.Servo(board.D5, actuation_range=135)
27+
servo = servo.Servo(pwm)
4028

4129
# We sleep in the loops to give the servo time to move into position.
30+
print("Sweep from 0 to 180")
4231
for i in range(180):
43-
servo7.angle = i
44-
time.sleep(0.03)
32+
servo.angle = i
33+
time.sleep(0.01)
34+
print("Sweep from 180 to 0")
4535
for i in range(180):
46-
servo7.angle = 180 - i
47-
time.sleep(0.03)
36+
servo.angle = 180 - i
37+
time.sleep(0.01)
38+
39+
print("Move to 90 degrees")
40+
servo.angle = 90
41+
time.sleep(1)
42+
print("Release servo motor for 10 seconds")
43+
servo.fraction = None
44+
time.sleep(10)
4845

4946
# You can also specify the movement fractionally.
47+
print("Sweep from 0 to 1.0 fractionally")
5048
fraction = 0.0
5149
while fraction < 1.0:
52-
servo7.fraction = fraction
50+
servo.fraction = fraction
5351
fraction += 0.01
54-
time.sleep(0.03)
55-
56-
pca.deinit()
52+
time.sleep(0.01)

0 commit comments

Comments
 (0)