From c960f26ed50650fa0fb289fe369bf79d9e269dc4 Mon Sep 17 00:00:00 2001 From: Martin O'Hanlon Date: Wed, 12 Oct 2022 16:54:03 +0100 Subject: [PATCH 1/6] added servo --- picozero/__init__.py | 1 + picozero/picozero.py | 68 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/picozero/__init__.py b/picozero/__init__.py index 97630ee..6c6b963 100644 --- a/picozero/__init__.py +++ b/picozero/__init__.py @@ -21,6 +21,7 @@ RGBLED, Motor, Robot, + Servo, DigitalInputDevice, Switch, diff --git a/picozero/picozero.py b/picozero/picozero.py index 3e58d24..69c04d1 100644 --- a/picozero/picozero.py +++ b/picozero/picozero.py @@ -16,6 +16,8 @@ class EventFailedScheduleQueueFull(Exception): # SUPPORTING CLASSES ############################################################################### +def clamp(n, low, high): return max(low, min(n, high)) + class PinMixin: """ Mixin used by devices that have a single pin number. @@ -365,8 +367,8 @@ class PWMOutputDevice(OutputDevice, PinMixin): LOW (the :meth:`off` method always does the opposite). :param bool initial_value: - If :data:`False` (the default), the LED will be off initially. If - :data:`True`, the LED will be switched on initially. + If :data:`0` (the default), the device will be off initially. If + :data:`1`, the device will be switched on initially. """ 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 +1402,68 @@ def close(self): Rover = Robot +class Servo(PWMOutputDevice): + """ + Represents a PWM-controlled servo motor. + + Setting the `value` to 0 will move the servo to its minimum position, + 1 will move the servo to its maximum position. Setting the `value` to + :data:`None` will turn the servo "off" (i.e. no signal is sent). + + :type pin: int + :param pin: + The pin the servo motor is connected to. + + :param bool initial_value: + If :data:`0`, the servo will be set to its minimum position. If + :data:`1`, the servo will set to its maximum position. If :data:`None` + (the default), the position of the servo will not change. + + :param float min_pulse_width: + The pulse width corresponding to the servo's minimum position. This + defaults to 1ms. + + :param float max_pulse_width: + The pulse width corresponding to the servo's maximum position. This + defaults to 2ms. + + :param float frame_width: + The length of time between servo control pulses measured in seconds. + This defaults to 20ms which is a common value for servos. + + :param int duty_factor: + The duty factor of the PWM signal. This is a value between 0 and 65535. + Defaults to 65535. + """ + def __init__(self, pin, initial_value=None, min_pulse_width=1/1000, max_pulse_width=2/1000, frame_width=20/1000, duty_factor=65535): + self._min_duty = int((min_pulse_width / frame_width) * duty_factor) + self._max_duty = int((max_pulse_width / frame_width) * duty_factor) + + super().__init__(pin, freq=int(1 / frame_width), duty_factor=duty_factor, initial_value=initial_value) + + def _state_to_value(self, state): + return None if state == 0 else clamp((state - self._min_duty) / (self._max_duty - self._min_duty), 0, 1) + + def _value_to_state(self, value): + return 0 if value is None else int(self._min_duty + ((self._max_duty - self._min_duty) * value)) + + def min(self): + """ + Set the servo to its minimum position. + """ + self.value = 0 + + def mid(self): + """ + Set the servo to its mid-point position. + """ + self.value = 0.5 + + def max(self): + """ + Set the servo to its maximum position. + """ + self.value = 1 ############################################################################### # INPUT DEVICES From 14c5a395d68a743222b655bdc93d21a4910f9235 Mon Sep 17 00:00:00 2001 From: Martin O'Hanlon Date: Sun, 16 Oct 2022 14:57:16 +0100 Subject: [PATCH 2/6] tests --- tests/test_picozero.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/test_picozero.py b/tests/test_picozero.py index 9b216f1..e7db8dd 100644 --- a/tests/test_picozero.py +++ b/tests/test_picozero.py @@ -317,10 +317,6 @@ def test_pico_led(self): pico_led.off() self.assertEqual(pico_led.value, 0) - ########################################################################### - # INPUT DEVICES - ########################################################################### - def test_rgb_led_default_values(self): d = RGBLED(1,2,3) @@ -366,6 +362,15 @@ def test_rgb_led_alt_values(self): self.assertEqual(d.value, (0,1,1)) d.close() + + def test_servo_default_value(self): + d = Servo(1) + self.assertEqual(d.value, 0) + d.close() + + ########################################################################### + # INPUT DEVICES + ########################################################################### def test_digital_input_device_default_values(self): d = DigitalInputDevice(1) From 3bd31344ffe35269c8f7598cea79c9d1a595df3a Mon Sep 17 00:00:00 2001 From: Martin O'Hanlon Date: Sun, 16 Oct 2022 21:19:39 +0100 Subject: [PATCH 3/6] servo tests --- tests/test_picozero.py | 48 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/tests/test_picozero.py b/tests/test_picozero.py index e7db8dd..00124e2 100644 --- a/tests/test_picozero.py +++ b/tests/test_picozero.py @@ -62,7 +62,12 @@ def reset(self): self._is_set = False class Testpicozero(unittest.TestCase): - + + def assertInRange(self, value, lower, upper): + msg = "Expected %r to be in range {} to {}".format(lower, upper) + self.assertTrue(value <= upper, msg) + self.assertTrue(value >= lower, msg) + ########################################################################### # OUTPUT DEVICES ########################################################################### @@ -365,7 +370,46 @@ def test_rgb_led_alt_values(self): def test_servo_default_value(self): d = Servo(1) - self.assertEqual(d.value, 0) + + self.assertEqual(d.value, None) + + d.value = 0 + self.assertAlmostEqual(d.value, 0, 2) + self.assertInRange(d._pwm.duty_u16(), int((0.001 / 0.02) * 65535) - 1, int((0.001 / 0.02) * 65535) + 1) + + d.value = 1 + self.assertAlmostEqual(d.value, 1, 2) + self.assertInRange(d._pwm.duty_u16(), int((0.002 / 0.02) * 65535) - 1, int((0.002 / 0.02) * 65535) + 1) + + d.value = None + self.assertEqual(d.value, None) + self.assertEqual(d._pwm.duty_u16(), 0) + + d.min() + self.assertAlmostEqual(d.value, 0, 2) + + d.mid() + self.assertAlmostEqual(d.value, 0.5, 2) + + d.max() + self.assertAlmostEqual(d.value, 1, 2) + + d.close() + + def test_servo_alt_values(self): + d = Servo(1, initial_value=1, min_pulse_width=0.9/1000, max_pulse_width=2.1/1000, frame_width=19/1000) + + self.assertAlmostEqual(d.value, 1, 2) + + d.value = 0 + self.assertInRange(d._pwm.duty_u16(), int((0.0009 / 0.019) * 65535) - 1, int((0.0009 / 0.019) * 65535) + 1) + + d.value = 1 + self.assertInRange(d._pwm.duty_u16(), int((0.0021 / 0.019) * 65535) - 1, int((0.0021 / 0.019) * 65535) + 1) + + d.value = None + self.assertEqual(d._pwm.duty_u16(), 0) + d.close() ########################################################################### From 46e69769ee59a4c0c1b1eff7db058d619e337668 Mon Sep 17 00:00:00 2001 From: Martin O'Hanlon Date: Mon, 17 Oct 2022 12:30:44 +0100 Subject: [PATCH 4/6] added servo off method --- picozero/picozero.py | 6 ++++++ tests/test_picozero.py | 3 +++ 2 files changed, 9 insertions(+) diff --git a/picozero/picozero.py b/picozero/picozero.py index 69c04d1..fd90ac5 100644 --- a/picozero/picozero.py +++ b/picozero/picozero.py @@ -1465,6 +1465,12 @@ def max(self): """ self.value = 1 + def off(self): + """ + Turn the servo "off" by setting the value to `None`. + """ + self.value = None + ############################################################################### # INPUT DEVICES ############################################################################### diff --git a/tests/test_picozero.py b/tests/test_picozero.py index 00124e2..bbd4afa 100644 --- a/tests/test_picozero.py +++ b/tests/test_picozero.py @@ -394,6 +394,9 @@ def test_servo_default_value(self): d.max() self.assertAlmostEqual(d.value, 1, 2) + d.off() + self.assertEqual(d._pwm.duty_u16(), 0) + d.close() def test_servo_alt_values(self): From a7795180d4b5f0ef2a6ac116891751cd4408f57c Mon Sep 17 00:00:00 2001 From: Martin O'Hanlon Date: Mon, 17 Oct 2022 13:12:55 +0100 Subject: [PATCH 5/6] servo docs --- docs/api.rst | 7 + docs/examples/servo_move.py | 15 + docs/examples/servo_pulse.py | 5 + docs/examples/servo_sweep.py | 10 + docs/images/servo.svg | 648 +++++++++++++++++++++++++++++++++++ docs/recipes.rst | 20 ++ docs/sketches/servo.fzz | Bin 0 -> 25581 bytes 7 files changed, 705 insertions(+) create mode 100644 docs/examples/servo_move.py create mode 100644 docs/examples/servo_pulse.py create mode 100644 docs/examples/servo_sweep.py create mode 100644 docs/images/servo.svg create mode 100644 docs/sketches/servo.fzz diff --git a/docs/api.rst b/docs/api.rst index 214a6dc..7a461b9 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -56,6 +56,13 @@ Speaker :inherited-members: :members: +Servo +----- +.. autoclass:: Servo + :show-inheritance: + :inherited-members: + :members: + Motor ----- diff --git a/docs/examples/servo_move.py b/docs/examples/servo_move.py new file mode 100644 index 0000000..9e1c4e5 --- /dev/null +++ b/docs/examples/servo_move.py @@ -0,0 +1,15 @@ +from picozero import Servo +from time import sleep + +servo = Servo(1) + +servo.min() +sleep(1) + +servo.mid() +sleep(1) + +servo.max() +sleep(1) + +servo.off() \ No newline at end of file diff --git a/docs/examples/servo_pulse.py b/docs/examples/servo_pulse.py new file mode 100644 index 0000000..40ffa56 --- /dev/null +++ b/docs/examples/servo_pulse.py @@ -0,0 +1,5 @@ +from picozero import Servo + +servo = Servo(1) + +servo.pulse() \ No newline at end of file diff --git a/docs/examples/servo_sweep.py b/docs/examples/servo_sweep.py new file mode 100644 index 0000000..36640db --- /dev/null +++ b/docs/examples/servo_sweep.py @@ -0,0 +1,10 @@ +from picozero import Servo +from time import sleep + +servo = Servo(1) + +for i in range(0, 100): + servo.value = i / 100 + sleep(0.1) + +servo.off() diff --git a/docs/images/servo.svg b/docs/images/servo.svg new file mode 100644 index 0000000..42dbf43 --- /dev/null +++ b/docs/images/servo.svg @@ -0,0 +1,648 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D + + + E + + + B + + + U + + + G + + + B + + + O + + + O + + + T + + + S + + + E + + + L + + + L + + + E + + + D + + + 1 + + + 2 + + + 3 + + + 9 + + + U + + + S + + + B + + + + R + + + a + + + s + + + p + + + b + + + e + + + r + + + r + + + y + + + + + + P + + + i + + + + + + P + + + i + + + c + + + o + + + + + + © + + + 2 + + + 0 + + + 2 + + + 0 + + + R + + + P + + + 2 + + + - + + + 8 + + + 0 + + + + + + + + + + + + + + + 2 + + + 0 + + + / + + + 2 + + + 1 + + + P + + + 6 + + + 4 + + + M + + + 1 + + + 5 + + + . + + + 0 + + + 0 + + + + + + T + + + T + + + T + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/recipes.rst b/docs/recipes.rst index bd6c2a3..87438d1 100644 --- a/docs/recipes.rst +++ b/docs/recipes.rst @@ -182,6 +182,26 @@ Play individual notes and control the timing or perform another action: .. literalinclude:: examples/speaker_notes.py +Servo +----- + +A servo motor connected to a single pin, 3.3v and ground. + +.. image:: images/servo.svg + :alt: A diagram of the Raspberry Pi Pico connected to a servo motor + +Move the servo to its minimum, mid and maximum positions. + +.. literalinclude:: examples/servo_move.py + +Pulse the servo between its minumum and maximum position. + +.. literalinclude:: examples/servo_pulse.py + +Move the servo gradually from its minimum to maximum position in 100 increments. + +.. literalinclude:: examples/servo_sweep.py + Motor ----- diff --git a/docs/sketches/servo.fzz b/docs/sketches/servo.fzz new file mode 100644 index 0000000000000000000000000000000000000000..e053fbaebb0cffecc4298dede4a8584f766ed3be GIT binary patch literal 25581 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 NZm)x*Z~WKS{{it4Q7-@h literal 0 HcmV?d00001 From f76da5da15e9fe5132078d0fdb3a93fc7c21c0b2 Mon Sep 17 00:00:00 2001 From: Martin O'Hanlon Date: Wed, 19 Oct 2022 15:54:45 +0100 Subject: [PATCH 6/6] doc fixes --- docs/examples/potentiometer.py | 6 +++--- picozero/picozero.py | 7 ------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/docs/examples/potentiometer.py b/docs/examples/potentiometer.py index 61ca01d..92a51ac 100644 --- a/docs/examples/potentiometer.py +++ b/docs/examples/potentiometer.py @@ -1,11 +1,11 @@ -# Potentiometer connected to ADC0, GND and 3V +# Potentiometer connected to GP26 (ADC0), GND and 3V from time import sleep from pico import Pot -pot = Pot(0) +pot = Pot(26) while True: - print(pot.value, pot.voltage, pot.percent) + print(pot.value, pot.voltage) sleep(0.1) diff --git a/picozero/picozero.py b/picozero/picozero.py index 3e58d24..a94c05e 100644 --- a/picozero/picozero.py +++ b/picozero/picozero.py @@ -264,13 +264,6 @@ class DigitalOutputDevice(OutputDevice, PinMixin): :param int pin: The pin that the device is connected to. - :param int freq: - The frequency of the PWM signal in Hertz. Defaults to 100. - - :param int duty_factor: - The duty factor of the PWM signal. This is a value between 0 and 65535. - Defaults to 65535. - :param bool active_high: If :data:`True` (the default), the :meth:`on` method will set the Pin to HIGH. If :data:`False`, the :meth:`on` method will set the Pin to