mirror of
https://github.com/KevinMidboe/python-gpiozero.git
synced 2025-12-08 20:39:01 +00:00
This PR implements SnowPi, adds the ability for LEDBoard's to own other LEDBoards as well as LEDs, and enhances blink so that manually controlling a LED automatically stops it from blinking (no matter whether it's blinking itself or a LEDBoard is blinking it). It also fixes up RGBLED and Motor which I managed to break with the last PR ...
This commit is contained in:
@@ -11,7 +11,7 @@ from threading import Lock
|
||||
from itertools import repeat, cycle, chain
|
||||
|
||||
from .exc import OutputDeviceBadValue, GPIOPinMissing
|
||||
from .devices import GPIODevice, CompositeDevice, SourceMixin
|
||||
from .devices import GPIODevice, Device, CompositeDevice, SourceMixin
|
||||
from .threads import GPIOThread
|
||||
|
||||
|
||||
@@ -121,6 +121,16 @@ class DigitalOutputDevice(OutputDevice):
|
||||
self._blink_thread = None
|
||||
super(DigitalOutputDevice, self).__init__(pin, active_high, initial_value)
|
||||
self._lock = Lock()
|
||||
self._controller = None
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
return self._read()
|
||||
|
||||
@value.setter
|
||||
def value(self, value):
|
||||
self._stop_blink()
|
||||
self._write(value)
|
||||
|
||||
def close(self):
|
||||
self._stop_blink()
|
||||
@@ -174,6 +184,9 @@ class DigitalOutputDevice(OutputDevice):
|
||||
self._blink_thread = None
|
||||
|
||||
def _stop_blink(self):
|
||||
if self._controller:
|
||||
self._controller._stop_blink(self)
|
||||
self._controller = None
|
||||
if self._blink_thread:
|
||||
self._blink_thread.stop()
|
||||
self._blink_thread = None
|
||||
@@ -286,6 +299,7 @@ class PWMOutputDevice(OutputDevice):
|
||||
"""
|
||||
def __init__(self, pin=None, active_high=True, initial_value=0, frequency=100):
|
||||
self._blink_thread = None
|
||||
self._controller = None
|
||||
if not 0 <= initial_value <= 1:
|
||||
raise OutputDeviceBadValue("initial_value must be between 0 and 1")
|
||||
super(PWMOutputDevice, self).__init__(pin, active_high)
|
||||
@@ -437,6 +451,9 @@ class PWMOutputDevice(OutputDevice):
|
||||
)
|
||||
|
||||
def _stop_blink(self):
|
||||
if self._controller:
|
||||
self._controller._stop_blink(self)
|
||||
self._controller = None
|
||||
if self._blink_thread:
|
||||
self._blink_thread.stop()
|
||||
self._blink_thread = None
|
||||
@@ -508,10 +525,10 @@ def _led_property(index, doc=None):
|
||||
return property(getter, setter, doc=doc)
|
||||
|
||||
|
||||
class RGBLED(SourceMixin, CompositeDevice):
|
||||
class RGBLED(SourceMixin, Device):
|
||||
"""
|
||||
Extends :class:`CompositeDevice` and represents a full color LED component
|
||||
(composed of red, green, and blue LEDs).
|
||||
Extends :class:`Device` and represents a full color LED component (composed
|
||||
of red, green, and blue LEDs).
|
||||
|
||||
Connect the common cathode (longest leg) to a ground pin; connect each of
|
||||
the other legs (representing the red, green, and blue anodes) to any GPIO
|
||||
@@ -556,6 +573,18 @@ class RGBLED(SourceMixin, CompositeDevice):
|
||||
green = _led_property(1)
|
||||
blue = _led_property(2)
|
||||
|
||||
def close(self):
|
||||
if self._leds:
|
||||
self._stop_blink()
|
||||
for led in self._leds:
|
||||
led.close()
|
||||
self._leds = ()
|
||||
super(RGBLED, self).close()
|
||||
|
||||
@property
|
||||
def closed(self):
|
||||
return bool(self._leds)
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
"""
|
||||
@@ -569,6 +598,7 @@ class RGBLED(SourceMixin, CompositeDevice):
|
||||
|
||||
@value.setter
|
||||
def value(self, value):
|
||||
self._stop_blink()
|
||||
self.red, self.green, self.blue = value
|
||||
|
||||
@property
|
||||
@@ -606,11 +636,6 @@ class RGBLED(SourceMixin, CompositeDevice):
|
||||
r, g, b = self.value
|
||||
self.value = (1 - r, 1 - g, 1 - b)
|
||||
|
||||
def close(self):
|
||||
self._stop_blink()
|
||||
for led in self._leds:
|
||||
led.close()
|
||||
|
||||
def blink(
|
||||
self, on_time=1, off_time=1, fade_in_time=0, fade_out_time=0,
|
||||
on_color=(1, 1, 1), off_color=(0, 0, 0), n=None, background=True):
|
||||
@@ -654,7 +679,8 @@ class RGBLED(SourceMixin, CompositeDevice):
|
||||
self._blink_thread.join()
|
||||
self._blink_thread = None
|
||||
|
||||
def _stop_blink(self):
|
||||
def _stop_blink(self, led=None):
|
||||
# If this is called with a single led, we stop all blinking anyway
|
||||
if self._blink_thread:
|
||||
self._blink_thread.stop()
|
||||
self._blink_thread = None
|
||||
@@ -687,16 +713,19 @@ class RGBLED(SourceMixin, CompositeDevice):
|
||||
cycle(sequence) if n is None else
|
||||
chain.from_iterable(repeat(sequence, n))
|
||||
)
|
||||
for l in self._leds:
|
||||
l._controller = self
|
||||
for value, delay in sequence:
|
||||
self._leds[0].value, self._leds[1].value, self._leds[2].value = value
|
||||
for l, v in zip(self._leds, value):
|
||||
l._write(v)
|
||||
if self._blink_thread.stopping.wait(delay):
|
||||
break
|
||||
|
||||
|
||||
class Motor(SourceMixin, CompositeDevice):
|
||||
"""
|
||||
Extends :class:`CompositeDevice` and represents a generic motor connected
|
||||
to a bi-directional motor driver circuit (i.e. an `H-bridge`_).
|
||||
Extends :class:`CompositeDevice` and represents a generic motor
|
||||
connected to a bi-directional motor driver circuit (i.e. an `H-bridge`_).
|
||||
|
||||
Attach an `H-bridge`_ motor controller to your Pi; connect a power source
|
||||
(e.g. a battery pack or the 5V pin) to the controller; connect the outputs
|
||||
@@ -725,33 +754,9 @@ class Motor(SourceMixin, CompositeDevice):
|
||||
raise GPIOPinMissing(
|
||||
'forward and backward pins must be provided'
|
||||
)
|
||||
super(Motor, self).__init__()
|
||||
self._forward = PWMOutputDevice(forward)
|
||||
self._backward = PWMOutputDevice(backward)
|
||||
|
||||
def close(self):
|
||||
self._forward.close()
|
||||
self._backward.close()
|
||||
|
||||
@property
|
||||
def closed(self):
|
||||
return self._forward.closed and self._backward.closed
|
||||
|
||||
@property
|
||||
def forward_device(self):
|
||||
"""
|
||||
Returns the `PWMOutputDevice` representing the forward pin of the motor
|
||||
controller.
|
||||
"""
|
||||
return self._forward
|
||||
|
||||
@property
|
||||
def backward_device(self):
|
||||
"""
|
||||
Returns the `PWMOutputDevice` representing the backward pin of the
|
||||
motor controller.
|
||||
"""
|
||||
return self._backward
|
||||
super(Motor, self).__init__(
|
||||
forward_device=PWMOutputDevice(forward),
|
||||
backward_device=PWMOutputDevice(backward))
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
@@ -759,7 +764,7 @@ class Motor(SourceMixin, CompositeDevice):
|
||||
Represents the speed of the motor as a floating point value between -1
|
||||
(full speed backward) and 1 (full speed forward).
|
||||
"""
|
||||
return self._forward.value - self._backward.value
|
||||
return self.forward_device.value - self.backward_device.value
|
||||
|
||||
@value.setter
|
||||
def value(self, value):
|
||||
@@ -788,8 +793,8 @@ class Motor(SourceMixin, CompositeDevice):
|
||||
The speed at which the motor should turn. Can be any value between
|
||||
0 (stopped) and the default 1 (maximum speed).
|
||||
"""
|
||||
self._backward.off()
|
||||
self._forward.value = speed
|
||||
self.backward_device.off()
|
||||
self.forward_device.value = speed
|
||||
|
||||
def backward(self, speed=1):
|
||||
"""
|
||||
@@ -799,8 +804,8 @@ class Motor(SourceMixin, CompositeDevice):
|
||||
The speed at which the motor should turn. Can be any value between
|
||||
0 (stopped) and the default 1 (maximum speed).
|
||||
"""
|
||||
self._forward.off()
|
||||
self._backward.value = speed
|
||||
self.forward_device.off()
|
||||
self.backward_device.value = speed
|
||||
|
||||
def reverse(self):
|
||||
"""
|
||||
@@ -814,5 +819,5 @@ class Motor(SourceMixin, CompositeDevice):
|
||||
"""
|
||||
Stop the motor.
|
||||
"""
|
||||
self._forward.off()
|
||||
self._backward.off()
|
||||
self.forward_device.off()
|
||||
self.backward_device.off()
|
||||
|
||||
Reference in New Issue
Block a user