Skip to content

Commit 887eba9

Browse files
author
Martin O'Hanlon
authored
Merge pull request #84 from RaspberryPiFoundation/dev
v 0.4.0
2 parents 762096f + 531be66 commit 887eba9

11 files changed

Lines changed: 838 additions & 17 deletions

File tree

docs/api.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ Speaker
5656
:inherited-members:
5757
:members:
5858

59+
Servo
60+
-----
61+
.. autoclass:: Servo
62+
:show-inheritance:
63+
:inherited-members:
64+
:members:
65+
5966
Motor
6067
-----
6168

docs/examples/potentiometer.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
# Potentiometer connected to ADC0, GND and 3V
1+
# Potentiometer connected to GP26 (ADC0), GND and 3V
22

33
from time import sleep
44
from pico import Pot
55

6-
pot = Pot(0)
6+
pot = Pot(26)
77

88
while True:
9-
print(pot.value, pot.voltage, pot.percent)
9+
print(pot.value, pot.voltage)
1010
sleep(0.1)
1111

docs/examples/servo_move.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from picozero import Servo
2+
from time import sleep
3+
4+
servo = Servo(1)
5+
6+
servo.min()
7+
sleep(1)
8+
9+
servo.mid()
10+
sleep(1)
11+
12+
servo.max()
13+
sleep(1)
14+
15+
servo.off()

docs/examples/servo_pulse.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from picozero import Servo
2+
3+
servo = Servo(1)
4+
5+
servo.pulse()

docs/examples/servo_sweep.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from picozero import Servo
2+
from time import sleep
3+
4+
servo = Servo(1)
5+
6+
for i in range(0, 100):
7+
servo.value = i / 100
8+
sleep(0.1)
9+
10+
servo.off()

docs/images/servo.svg

Lines changed: 648 additions & 0 deletions
Loading

docs/recipes.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,26 @@ Play individual notes and control the timing or perform another action:
182182

183183
.. literalinclude:: examples/speaker_notes.py
184184

185+
Servo
186+
-----
187+
188+
A servo motor connected to a single pin, 3.3v and ground.
189+
190+
.. image:: images/servo.svg
191+
:alt: A diagram of the Raspberry Pi Pico connected to a servo motor
192+
193+
Move the servo to its minimum, mid and maximum positions.
194+
195+
.. literalinclude:: examples/servo_move.py
196+
197+
Pulse the servo between its minumum and maximum position.
198+
199+
.. literalinclude:: examples/servo_pulse.py
200+
201+
Move the servo gradually from its minimum to maximum position in 100 increments.
202+
203+
.. literalinclude:: examples/servo_sweep.py
204+
185205
Motor
186206
-----
187207

docs/sketches/servo.fzz

25 KB
Binary file not shown.

picozero/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
RGBLED,
2222
Motor,
2323
Robot,
24+
Servo,
2425

2526
DigitalInputDevice,
2627
Switch,

picozero/picozero.py

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ class EventFailedScheduleQueueFull(Exception):
1616
# SUPPORTING CLASSES
1717
###############################################################################
1818

19+
def clamp(n, low, high): return max(low, min(n, high))
20+
1921
class PinMixin:
2022
"""
2123
Mixin used by devices that have a single pin number.
@@ -264,13 +266,6 @@ class DigitalOutputDevice(OutputDevice, PinMixin):
264266
:param int pin:
265267
The pin that the device is connected to.
266268
267-
:param int freq:
268-
The frequency of the PWM signal in Hertz. Defaults to 100.
269-
270-
:param int duty_factor:
271-
The duty factor of the PWM signal. This is a value between 0 and 65535.
272-
Defaults to 65535.
273-
274269
:param bool active_high:
275270
If :data:`True` (the default), the :meth:`on` method will set the Pin
276271
to HIGH. If :data:`False`, the :meth:`on` method will set the Pin to
@@ -365,8 +360,8 @@ class PWMOutputDevice(OutputDevice, PinMixin):
365360
LOW (the :meth:`off` method always does the opposite).
366361
367362
:param bool initial_value:
368-
If :data:`False` (the default), the LED will be off initially. If
369-
:data:`True`, the LED will be switched on initially.
363+
If :data:`0` (the default), the device will be off initially. If
364+
:data:`1`, the device will be switched on initially.
370365
"""
371366

372367
PIN_TO_PWM_CHANNEL = ["0A","0B","1A","1B","2A","2B","3A","3B","4A","4B","5A","5B","6A","6B","7A","7B","0A","0B","1A","1B","2A","2B","3A","3B","4A","4B","5A","5B","6A","6B"]
@@ -1400,6 +1395,74 @@ def close(self):
14001395

14011396
Rover = Robot
14021397

1398+
class Servo(PWMOutputDevice):
1399+
"""
1400+
Represents a PWM-controlled servo motor.
1401+
1402+
Setting the `value` to 0 will move the servo to its minimum position,
1403+
1 will move the servo to its maximum position. Setting the `value` to
1404+
:data:`None` will turn the servo "off" (i.e. no signal is sent).
1405+
1406+
:type pin: int
1407+
:param pin:
1408+
The pin the servo motor is connected to.
1409+
1410+
:param bool initial_value:
1411+
If :data:`0`, the servo will be set to its minimum position. If
1412+
:data:`1`, the servo will set to its maximum position. If :data:`None`
1413+
(the default), the position of the servo will not change.
1414+
1415+
:param float min_pulse_width:
1416+
The pulse width corresponding to the servo's minimum position. This
1417+
defaults to 1ms.
1418+
1419+
:param float max_pulse_width:
1420+
The pulse width corresponding to the servo's maximum position. This
1421+
defaults to 2ms.
1422+
1423+
:param float frame_width:
1424+
The length of time between servo control pulses measured in seconds.
1425+
This defaults to 20ms which is a common value for servos.
1426+
1427+
:param int duty_factor:
1428+
The duty factor of the PWM signal. This is a value between 0 and 65535.
1429+
Defaults to 65535.
1430+
"""
1431+
def __init__(self, pin, initial_value=None, min_pulse_width=1/1000, max_pulse_width=2/1000, frame_width=20/1000, duty_factor=65535):
1432+
self._min_duty = int((min_pulse_width / frame_width) * duty_factor)
1433+
self._max_duty = int((max_pulse_width / frame_width) * duty_factor)
1434+
1435+
super().__init__(pin, freq=int(1 / frame_width), duty_factor=duty_factor, initial_value=initial_value)
1436+
1437+
def _state_to_value(self, state):
1438+
return None if state == 0 else clamp((state - self._min_duty) / (self._max_duty - self._min_duty), 0, 1)
1439+
1440+
def _value_to_state(self, value):
1441+
return 0 if value is None else int(self._min_duty + ((self._max_duty - self._min_duty) * value))
1442+
1443+
def min(self):
1444+
"""
1445+
Set the servo to its minimum position.
1446+
"""
1447+
self.value = 0
1448+
1449+
def mid(self):
1450+
"""
1451+
Set the servo to its mid-point position.
1452+
"""
1453+
self.value = 0.5
1454+
1455+
def max(self):
1456+
"""
1457+
Set the servo to its maximum position.
1458+
"""
1459+
self.value = 1
1460+
1461+
def off(self):
1462+
"""
1463+
Turn the servo "off" by setting the value to `None`.
1464+
"""
1465+
self.value = None
14031466

14041467
###############################################################################
14051468
# INPUT DEVICES

0 commit comments

Comments
 (0)