mirror of
https://github.com/KevinMidboe/python-gpiozero.git
synced 2025-10-29 17:50:37 +00:00
Fix #135
This commit is contained in:
@@ -35,7 +35,7 @@ RGBLED
|
|||||||
======
|
======
|
||||||
|
|
||||||
.. autoclass:: RGBLED(red, green, blue, active_high=True)
|
.. autoclass:: RGBLED(red, green, blue, active_high=True)
|
||||||
:members: on, off, red, green, blue, value
|
:members: on, off, blink, red, green, blue, value
|
||||||
|
|
||||||
Motor
|
Motor
|
||||||
=====
|
=====
|
||||||
|
|||||||
@@ -302,6 +302,7 @@ class PWMOutputDevice(OutputDevice):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
|
self._stop_blink()
|
||||||
if self._pwm:
|
if self._pwm:
|
||||||
# Ensure we wipe out the PWM object so that re-runs don't attempt
|
# Ensure we wipe out the PWM object so that re-runs don't attempt
|
||||||
# to re-stop the PWM thread (otherwise, the fact that close is
|
# to re-stop the PWM thread (otherwise, the fact that close is
|
||||||
@@ -484,11 +485,12 @@ PWMLED.is_lit = PWMLED.is_active
|
|||||||
|
|
||||||
|
|
||||||
def _led_property(index, doc=None):
|
def _led_property(index, doc=None):
|
||||||
return property(
|
def getter(self):
|
||||||
lambda self: getattr(self._leds[index], 'value'),
|
return self._leds[index].value
|
||||||
lambda self, value: setattr(self._leds[index], 'value', value),
|
def setter(self, value):
|
||||||
doc
|
self._stop_blink()
|
||||||
)
|
self._leds[index].value = value
|
||||||
|
return property(getter, setter, doc=doc)
|
||||||
|
|
||||||
|
|
||||||
class RGBLED(SourceMixin, CompositeDevice):
|
class RGBLED(SourceMixin, CompositeDevice):
|
||||||
@@ -523,6 +525,8 @@ class RGBLED(SourceMixin, CompositeDevice):
|
|||||||
(the :meth:`off` method always does the opposite).
|
(the :meth:`off` method always does the opposite).
|
||||||
"""
|
"""
|
||||||
def __init__(self, red=None, green=None, blue=None, active_high=True):
|
def __init__(self, red=None, green=None, blue=None, active_high=True):
|
||||||
|
self._leds = ()
|
||||||
|
self._blink_thread = None
|
||||||
if not all([red, green, blue]):
|
if not all([red, green, blue]):
|
||||||
raise OutputDeviceError('red, green, and blue pins must be provided')
|
raise OutputDeviceError('red, green, and blue pins must be provided')
|
||||||
super(RGBLED, self).__init__()
|
super(RGBLED, self).__init__()
|
||||||
@@ -572,9 +576,91 @@ class RGBLED(SourceMixin, CompositeDevice):
|
|||||||
self.value = (0, 0, 0)
|
self.value = (0, 0, 0)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
|
self._stop_blink()
|
||||||
for led in self._leds:
|
for led in self._leds:
|
||||||
led.close()
|
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):
|
||||||
|
"""
|
||||||
|
Make the device turn on and off repeatedly.
|
||||||
|
|
||||||
|
:param float on_time:
|
||||||
|
Number of seconds on. Defaults to 1 second.
|
||||||
|
|
||||||
|
:param float off_time:
|
||||||
|
Number of seconds off. Defaults to 1 second.
|
||||||
|
|
||||||
|
:param float fade_in_time:
|
||||||
|
Number of seconds to spend fading in. Defaults to 0.
|
||||||
|
|
||||||
|
:param float fade_out_time:
|
||||||
|
Number of seconds to spend fading out. Defaults to 0.
|
||||||
|
|
||||||
|
:param tuple on_color:
|
||||||
|
The color to use when the LED is "on". Defaults to white.
|
||||||
|
|
||||||
|
:param tuple off_color:
|
||||||
|
The color to use when the LED is "off". Defaults to black.
|
||||||
|
|
||||||
|
:param int n:
|
||||||
|
Number of times to blink; ``None`` (the default) means forever.
|
||||||
|
|
||||||
|
:param bool background:
|
||||||
|
If ``True`` (the default), start a background thread to continue
|
||||||
|
blinking and return immediately. If ``False``, only return when the
|
||||||
|
blink is finished (warning: the default value of *n* will result in
|
||||||
|
this method never returning).
|
||||||
|
"""
|
||||||
|
self._stop_blink()
|
||||||
|
self._blink_thread = GPIOThread(
|
||||||
|
target=self._blink_device,
|
||||||
|
args=(on_time, off_time, fade_in_time, fade_out_time, on_color, off_color, n)
|
||||||
|
)
|
||||||
|
self._blink_thread.start()
|
||||||
|
if not background:
|
||||||
|
self._blink_thread.join()
|
||||||
|
self._blink_thread = None
|
||||||
|
|
||||||
|
def _stop_blink(self):
|
||||||
|
if self._blink_thread:
|
||||||
|
self._blink_thread.stop()
|
||||||
|
self._blink_thread = None
|
||||||
|
|
||||||
|
def _blink_device(
|
||||||
|
self, on_time, off_time, fade_in_time, fade_out_time, on_color,
|
||||||
|
off_color, n, fps=50):
|
||||||
|
# Define some simple lambdas to perform linear interpolation between
|
||||||
|
# off_color and on_color
|
||||||
|
lerp = lambda t, fade_in: tuple(
|
||||||
|
(1 - t) * off + t * on
|
||||||
|
if fade_in else
|
||||||
|
(1 - t) * on + t * off
|
||||||
|
for off, on in zip(off_color, on_color)
|
||||||
|
)
|
||||||
|
sequence = []
|
||||||
|
if fade_in_time > 0:
|
||||||
|
sequence += [
|
||||||
|
(lerp(i * (1 / fps) / fade_in_time, True), 1 / fps)
|
||||||
|
for i in range(int(fps * fade_in_time))
|
||||||
|
]
|
||||||
|
sequence.append((on_color, on_time))
|
||||||
|
if fade_out_time > 0:
|
||||||
|
sequence += [
|
||||||
|
(lerp(i * (1 / fps) / fade_out_time, False), 1 / fps)
|
||||||
|
for i in range(int(fps * fade_out_time))
|
||||||
|
]
|
||||||
|
sequence.append((off_color, off_time))
|
||||||
|
sequence = (
|
||||||
|
cycle(sequence) if n is None else
|
||||||
|
chain.from_iterable(repeat(sequence, n))
|
||||||
|
)
|
||||||
|
for value, delay in sequence:
|
||||||
|
self._leds[0].value, self._leds[1].value, self._leds[2].value = value
|
||||||
|
if self._blink_thread.stopping.wait(delay):
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
class Motor(SourceMixin, CompositeDevice):
|
class Motor(SourceMixin, CompositeDevice):
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user