Skip to content

Commit a32d2d2

Browse files
committed
WIP: servo works.
1 parent c2c5e41 commit a32d2d2

File tree

4 files changed

+87
-12
lines changed

4 files changed

+87
-12
lines changed

README.rst

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,15 @@ Introduction
33
============
44

55
.. image:: https://readthedocs.org/projects/adafruit-circuitpython-motor/badge/?version=latest
6-
76
:target: https://circuitpython.readthedocs.io/projects/motor/en/latest/
8-
97
:alt: Documentation Status
108

119
.. image :: https://img.shields.io/discord/327254708534116352.svg
1210
:target: https://discord.gg/nBQh6qu
1311
:alt: Discord
1412
15-
TODO
13+
This helper library provides higher level objects to control motors and servos based on one or more
14+
PWM outputs.
1615

1716
Dependencies
1817
=============

adafruit_motor/servo.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,14 @@ class _BaseServo:
4343
:param int max_pulse: The maximum pulse length of the servo in microseconds.
4444
:param int range: The physical range of the servo corresponding to the signal's duty in
4545
degrees."""
46-
def __init__(self, pwm_out, *, min_pulse=1000, max_pulse=2000, trim=0):
47-
self._min_duty = (min_pulse * 0xffff * pwm_out.frequency) / 1000000
48-
max_duty = (max_pulse * 0xffff * pwm_out.frequency) / 1000000
49-
self._duty_range = max_duty - self._min_duty
46+
def __init__(self, pwm_out, *, min_pulse=1000, max_pulse=2000):
47+
self._min_duty = int((min_pulse * pwm_out.frequency) / 1000000 * 0xffff)
48+
max_duty = (max_pulse * pwm_out.frequency) / 1000000 * 0xffff
49+
self._duty_range = int(max_duty - self._min_duty)
50+
print(self._min_duty, self._duty_range)
5051
self._pwm_out = pwm_out
52+
self._min_pulse = min_pulse
53+
self._pulse_range = max_pulse - min_pulse
5154

5255
@property
5356
def _fraction(self):
@@ -56,7 +59,9 @@ def _fraction(self):
5659
@_fraction.setter
5760
def _fraction(self, value):
5861
"""The fraction of pulse high."""
59-
self._pwm_out.duty_cycle = self.min_duty + value * self._duty_range
62+
duty_cycle = self._min_duty + int(value * self._duty_range)
63+
print(self._min_pulse + int(value * self._pulse_range))
64+
self._pwm_out.duty_cycle = duty_cycle
6065

6166
class Servo(_BaseServo):
6267
"""Control the position of a servo.
@@ -66,7 +71,8 @@ class Servo(_BaseServo):
6671
:param int min_pulse: The minimum pulse length of the servo in microseconds.
6772
:param int max_pulse: The maximum pulse length of the servo in microseconds.
6873
:param int trim: Slight shift of values to calibrate stopped value in microseconds."""
69-
def __init__(self, pwm_out, *, actuation_range=180, min_pulse=1000, max_pulse=2000, trim=0):
74+
def __init__(self, pwm_out, *, actuation_range=180, min_pulse=1000, max_pulse=2000):
75+
super().__init__(pwm_out, min_pulse=min_pulse, max_pulse=max_pulse)
7076
self._actuation_range = actuation_range
7177
self._pwm = pwm_out
7278

@@ -75,10 +81,11 @@ def angle(self):
7581
return self._actuation_range * self._fraction
7682

7783
@angle.setter
78-
def angle(self, value):
84+
def angle(self, new_angle):
7985
"""The servo angle in degrees."""
80-
if value < 0 or value > self._actuation_range:
86+
if new_angle < 0 or new_angle > self._actuation_range:
8187
raise ValueError("Angle out of range")
88+
self._fraction = new_angle / self._actuation_range
8289

8390
class ContinuousServo(_BaseServo):
8491
"""Control a continuous rotation servo.
@@ -99,7 +106,7 @@ def throttle(self, value):
99106
raise ValueError("Throttle must be between -1.0 and 1.0")
100107
if value is None:
101108
raise ValueError("Continuous servos cannot spin freely")
102-
self._fraction = int((value + 1) / 2)
109+
self._fraction = (value + 1) / 2
103110

104111
def __enter__(self):
105112
return self

examples/continuous_servo.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import time
2+
3+
from board import *
4+
import busio
5+
6+
# Import the PCA9685 module.
7+
from adafruit_pca9685 import PCA9685
8+
9+
# This example also relies on the Adafruit motor library available here:
10+
# https://github.com/adafruit/Adafruit_CircuitPython_Motor
11+
from adafruit_motor import servo
12+
13+
i2c = busio.I2C(SCL, SDA)
14+
15+
# Create a simple PCA9685 class instance.
16+
pca = PCA9685(i2c)
17+
pca.frequency = 50
18+
19+
# The pulse range is 1000 - 2000 by default.
20+
servo7 = servo.ContinuousServo(pca.channels[7], min_pulse=600, max_pulse=2500)
21+
22+
print("Forwards")
23+
servo7.throttle = 1
24+
time.sleep(1)
25+
26+
print("Backwards")
27+
servo7.throttle = -1
28+
time.sleep(1)
29+
30+
print("Stop")
31+
servo7.throttle = 0
32+
33+
pca.deinit()

examples/servo_sweep.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import time
2+
3+
from board import *
4+
import busio
5+
6+
# Import the PCA9685 module.
7+
from adafruit_pca9685 import PCA9685
8+
from adafruit_motor import servo
9+
10+
i2c = busio.I2C(SCL, SDA)
11+
12+
# Create a simple PCA9685 class instance.
13+
pca = PCA9685(i2c)
14+
pca.frequency = 50
15+
16+
# To get the full range of the servo you will likely need to adjust the min_pulse and max_pulse to
17+
# match the stall points of the servo.
18+
# This is an example for the Sub-micro servo: https://www.adafruit.com/product/2201
19+
# servo7 = servo.Servo(pca.channels[7], min_pulse=580, max_pulse=2480)
20+
# This is an example for the Micro Servo - High Powered, High Torque Metal Gear:
21+
# https://www.adafruit.com/product/2307
22+
# servo7 = servo.Servo(pca.channels[7], min_pulse=600, max_pulse=2400)
23+
# This is an example for the Standard servo - TowerPro SG-5010 - 5010:
24+
# https://www.adafruit.com/product/155
25+
# servo7 = servo.Servo(pca.channels[7], min_pulse=600, max_pulse=2500)
26+
# This is an example for the Analog Feedback Servo: https://www.adafruit.com/product/1404
27+
# servo7 = servo.Servo(pca.channels[7], min_pulse=600, max_pulse=2600)
28+
29+
# The pulse range is 1000 - 2000 by default.
30+
servo7 = servo.Servo(pca.channels[7])
31+
32+
for i in range(180):
33+
servo7.angle = i
34+
for i in range(180):
35+
servo7.angle = 180 - i
36+
pca.deinit()

0 commit comments

Comments
 (0)