mirror of
				https://github.com/KevinMidboe/python-gpiozero.git
				synced 2025-10-29 17:50:37 +00:00 
			
		
		
		
	Merge-clean update of PR #126
This is an updated cherry-pick of Martin O'Hanlon's LEDBarGraph class.
This commit is contained in:
		| @@ -22,6 +22,13 @@ LED Board | |||||||
|     :inherited-members: |     :inherited-members: | ||||||
|     :members: |     :members: | ||||||
|  |  | ||||||
|  | LED Bar Graph | ||||||
|  | ============= | ||||||
|  |  | ||||||
|  | .. autoclass:: LEDBarGraph(\*pins, initial_value=0) | ||||||
|  |     :inherited-members: | ||||||
|  |     :members: | ||||||
|  |  | ||||||
| Traffic Lights | Traffic Lights | ||||||
| ============== | ============== | ||||||
|  |  | ||||||
| @@ -36,6 +43,13 @@ PiLITEr | |||||||
|     :inherited-members: |     :inherited-members: | ||||||
|     :members: |     :members: | ||||||
|  |  | ||||||
|  | PiLITEr Bar Graph | ||||||
|  | ================= | ||||||
|  |  | ||||||
|  | .. autoclass:: PiLiterBarGraph | ||||||
|  |     :inherited-members: | ||||||
|  |     :members: | ||||||
|  |  | ||||||
| PI-TRAFFIC | PI-TRAFFIC | ||||||
| ========== | ========== | ||||||
|  |  | ||||||
|   | |||||||
| @@ -48,7 +48,9 @@ from .output_devices import ( | |||||||
| ) | ) | ||||||
| from .boards import ( | from .boards import ( | ||||||
|     LEDBoard, |     LEDBoard, | ||||||
|  |     LEDBarGraph, | ||||||
|     PiLiter, |     PiLiter, | ||||||
|  |     PiLiterBarGraph, | ||||||
|     TrafficLights, |     TrafficLights, | ||||||
|     PiTraffic, |     PiTraffic, | ||||||
|     TrafficLightsBuzzer, |     TrafficLightsBuzzer, | ||||||
|   | |||||||
| @@ -19,7 +19,59 @@ from .output_devices import LED, PWMLED, Buzzer, Motor | |||||||
| from .devices import GPIOThread, CompositeDevice, SourceMixin | from .devices import GPIOThread, CompositeDevice, SourceMixin | ||||||
|  |  | ||||||
|  |  | ||||||
| class LEDBoard(SourceMixin, CompositeDevice): | class LEDCollection(SourceMixin, CompositeDevice): | ||||||
|  |     """ | ||||||
|  |     Abstract base class for :class:`LEDBoard` and :class:`LEDBarGraph`. | ||||||
|  |     """ | ||||||
|  |  | ||||||
|  |     def __init__(self, *pins, **kwargs): | ||||||
|  |         self._blink_thread = None | ||||||
|  |         super(LEDCollection, self).__init__() | ||||||
|  |         pwm = kwargs.get('pwm', False) | ||||||
|  |         LEDClass = PWMLED if pwm else LED | ||||||
|  |         self._leds = tuple(LEDClass(pin) for pin in pins) | ||||||
|  |  | ||||||
|  |     def close(self): | ||||||
|  |         for led in self.leds: | ||||||
|  |             led.close() | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def closed(self): | ||||||
|  |         return all(led.closed for led in self.leds) | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def leds(self): | ||||||
|  |         """ | ||||||
|  |         A tuple of all the :class:`LED` or :class:`PWMLED` objects contained by | ||||||
|  |         the instance. | ||||||
|  |         """ | ||||||
|  |         return self._leds | ||||||
|  |  | ||||||
|  |     def on(self): | ||||||
|  |         """ | ||||||
|  |         Turn all the LEDs on. | ||||||
|  |         """ | ||||||
|  |         for led in self.leds: | ||||||
|  |             led.on() | ||||||
|  |  | ||||||
|  |     def off(self): | ||||||
|  |         """ | ||||||
|  |         Turn all the LEDs off. | ||||||
|  |         """ | ||||||
|  |         for led in self.leds: | ||||||
|  |             led.off() | ||||||
|  |  | ||||||
|  |     def toggle(self): | ||||||
|  |         """ | ||||||
|  |         Toggle all the LEDs. For each LED, if it's on, turn it off; if it's | ||||||
|  |         off, turn it on. | ||||||
|  |         """ | ||||||
|  |         for led in self.leds: | ||||||
|  |             led.toggle() | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class LEDBoard(LEDCollection): | ||||||
|     """ |     """ | ||||||
|     Extends :class:`CompositeDevice` and represents a generic LED board or |     Extends :class:`CompositeDevice` and represents a generic LED board or | ||||||
|     collection of LEDs. |     collection of LEDs. | ||||||
| @@ -41,29 +93,10 @@ class LEDBoard(SourceMixin, CompositeDevice): | |||||||
|         ``False`` (the default), construct regular :class:`LED` instances. This |         ``False`` (the default), construct regular :class:`LED` instances. This | ||||||
|         parameter can only be specified as a keyword parameter. |         parameter can only be specified as a keyword parameter. | ||||||
|     """ |     """ | ||||||
|     def __init__(self, *pins, **kwargs): |  | ||||||
|         self._blink_thread = None |  | ||||||
|         super(LEDBoard, self).__init__() |  | ||||||
|         pwm = kwargs.get('pwm', False) |  | ||||||
|         LEDClass = PWMLED if pwm else LED |  | ||||||
|         self._leds = tuple(LEDClass(pin) for pin in pins) |  | ||||||
|  |  | ||||||
|     def close(self): |     def close(self): | ||||||
|         self._stop_blink() |         self._stop_blink() | ||||||
|         for led in self.leds: |         super(LEDBoard, self).close() | ||||||
|             led.close() |  | ||||||
|  |  | ||||||
|     @property |  | ||||||
|     def closed(self): |  | ||||||
|         return all(led.closed for led in self.leds) |  | ||||||
|  |  | ||||||
|     @property |  | ||||||
|     def leds(self): |  | ||||||
|         """ |  | ||||||
|         A tuple of all the :class:`LED` or :class:`PWMLED` objects contained by |  | ||||||
|         the instance. |  | ||||||
|         """ |  | ||||||
|         return self._leds |  | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def value(self): |     def value(self): | ||||||
| @@ -75,32 +108,21 @@ class LEDBoard(SourceMixin, CompositeDevice): | |||||||
|  |  | ||||||
|     @value.setter |     @value.setter | ||||||
|     def value(self, value): |     def value(self, value): | ||||||
|  |         self._stop_blink() | ||||||
|         for l, v in zip(self.leds, value): |         for l, v in zip(self.leds, value): | ||||||
|             l.value = v |             l.value = v | ||||||
|  |  | ||||||
|     def on(self): |     def on(self): | ||||||
|         """ |  | ||||||
|         Turn all the LEDs on. |  | ||||||
|         """ |  | ||||||
|         self._stop_blink() |         self._stop_blink() | ||||||
|         for led in self.leds: |         super(LEDBoard, self).on() | ||||||
|             led.on() |  | ||||||
|  |  | ||||||
|     def off(self): |     def off(self): | ||||||
|         """ |  | ||||||
|         Turn all the LEDs off. |  | ||||||
|         """ |  | ||||||
|         self._stop_blink() |         self._stop_blink() | ||||||
|         for led in self.leds: |         super(LEDBoard, self).off() | ||||||
|             led.off() |  | ||||||
|  |  | ||||||
|     def toggle(self): |     def toggle(self): | ||||||
|         """ |         self._stop_blink() | ||||||
|         Toggle all the LEDs. For each LED, if it's on, turn it off; if it's |         super(LEDBoard, self).toggle() | ||||||
|         off, turn it on. |  | ||||||
|         """ |  | ||||||
|         for led in self.leds: |  | ||||||
|             led.toggle() |  | ||||||
|  |  | ||||||
|     def blink( |     def blink( | ||||||
|             self, on_time=1, off_time=1, fade_in_time=0, fade_out_time=0, |             self, on_time=1, off_time=1, fade_in_time=0, fade_out_time=0, | ||||||
| @@ -178,9 +200,96 @@ class LEDBoard(SourceMixin, CompositeDevice): | |||||||
|                 break |                 break | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class LEDBarGraph(LEDCollection): | ||||||
|  |     """ | ||||||
|  |     Extends :class:`CompositeDevice` to control a line of LEDs representing a | ||||||
|  |     bar graph. Positive values (0 to 1) light the LEDs from first to last. | ||||||
|  |     Negative values (-1 to 0) light the LEDs from last to first. | ||||||
|  |  | ||||||
|  |     The following example turns on all the LEDs on a board containing 5 LEDs | ||||||
|  |     attached to GPIO pins 2 through 6:: | ||||||
|  |  | ||||||
|  |         from gpiozero import LEDBarGraph | ||||||
|  |  | ||||||
|  |         graph = LEDBarGraph(2, 3, 4, 5, 6) | ||||||
|  |         graph.value = 2/5  # Light the first two LEDs only | ||||||
|  |         graph.value = -2/5 # Light the last two LEDs only | ||||||
|  |         graph.off() | ||||||
|  |  | ||||||
|  |     As with other output devices, :attr:`source` and :attr:`values` are | ||||||
|  |     supported:: | ||||||
|  |  | ||||||
|  |         from gpiozero import LEDBarGraph, MCP3008 | ||||||
|  |         from signal import pause | ||||||
|  |  | ||||||
|  |         graph = LEDBarGraph(2, 3, 4, 5, 6) | ||||||
|  |         pot = MCP3008(channel=0) | ||||||
|  |         graph.source = pot.values | ||||||
|  |         pause() | ||||||
|  |  | ||||||
|  |     :param int \*pins: | ||||||
|  |         Specify the GPIO pins that the LEDs of the bar graph are attached to. | ||||||
|  |         You can designate as many pins as necessary. | ||||||
|  |  | ||||||
|  |     :param float initial_value: | ||||||
|  |         The initial :attr:`value` of the graph given as a float between -1 and | ||||||
|  |         +1.  Defaults to 0.0. | ||||||
|  |     """ | ||||||
|  |  | ||||||
|  |     def __init__(self, *pins, **kwargs): | ||||||
|  |         super(LEDBarGraph, self).__init__(*pins, pwm=False) | ||||||
|  |         initial_value = kwargs.get('initial_value', 0) | ||||||
|  |         self.value = initial_value | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def value(self): | ||||||
|  |         """ | ||||||
|  |         The value of the LED bar graph. When no LEDs are lit, the value is 0. | ||||||
|  |         When all LEDs are lit, the value is 1. Values between 0 and 1 | ||||||
|  |         light LEDs linearly from first to last. Values between 0 and -1 | ||||||
|  |         light LEDs linearly from last to first. | ||||||
|  |  | ||||||
|  |         To light a particular number of LEDs, simply divide that number by | ||||||
|  |         the number of LEDs. For example, if your graph contains 3 LEDs, the | ||||||
|  |         following will light the first:: | ||||||
|  |  | ||||||
|  |             from gpiozero import LEDBarGraph | ||||||
|  |  | ||||||
|  |             graph = LEDBarGraph(12, 16, 19) | ||||||
|  |             graph.value = 1/3 | ||||||
|  |  | ||||||
|  |         .. note:: | ||||||
|  |  | ||||||
|  |             Setting value to -1 will light all LEDs. However, querying it | ||||||
|  |             subsequently will return 1 as both representations are the same in | ||||||
|  |             hardware. | ||||||
|  |         """ | ||||||
|  |         for index, led in enumerate(self.leds): | ||||||
|  |             if not led.is_lit: | ||||||
|  |                 break | ||||||
|  |         else: | ||||||
|  |             index = len(self.leds) | ||||||
|  |         if not index: | ||||||
|  |             for index, led in enumerate(reversed(self.leds)): | ||||||
|  |                 if not led.is_lit: | ||||||
|  |                     break | ||||||
|  |             index = -index | ||||||
|  |         return index / len(self.leds) | ||||||
|  |  | ||||||
|  |     @value.setter | ||||||
|  |     def value(self, value): | ||||||
|  |         count = len(self.leds) | ||||||
|  |         if value >= 0: | ||||||
|  |             for index, led in enumerate(self.leds, start=1): | ||||||
|  |                 led.value = value >= (index / count) | ||||||
|  |         else: | ||||||
|  |             for index, led in enumerate(reversed(self.leds), start=1): | ||||||
|  |                 led.value = value <= -(index / count) | ||||||
|  |  | ||||||
|  |  | ||||||
| class PiLiter(LEDBoard): | class PiLiter(LEDBoard): | ||||||
|     """ |     """ | ||||||
|     Extends :class:`LEDBoard` for the Ciseco Pi-LITEr: a strip of 8 very bright |     Extends :class:`LEDBoard` for the `Ciseco Pi-LITEr`_: a strip of 8 very bright | ||||||
|     LEDs. |     LEDs. | ||||||
|  |  | ||||||
|     The Pi-LITEr pins are fixed and therefore there's no need to specify them |     The Pi-LITEr pins are fixed and therefore there's no need to specify them | ||||||
| @@ -196,11 +305,38 @@ class PiLiter(LEDBoard): | |||||||
|         If ``True``, construct :class:`PWMLED` instances for each pin. If |         If ``True``, construct :class:`PWMLED` instances for each pin. If | ||||||
|         ``False`` (the default), construct regular :class:`LED` instances. This |         ``False`` (the default), construct regular :class:`LED` instances. This | ||||||
|         parameter can only be specified as a keyword parameter. |         parameter can only be specified as a keyword parameter. | ||||||
|  |  | ||||||
|  |     .. _Ciseco Pi-LITEr: http://shop.ciseco.co.uk/pi-liter-8-led-strip-for-the-raspberry-pi/ | ||||||
|     """ |     """ | ||||||
|     def __init__(self, pwm=False): |     def __init__(self, pwm=False): | ||||||
|         super(PiLiter, self).__init__(4, 17, 27, 18, 22, 23, 24, 25, pwm=pwm) |         super(PiLiter, self).__init__(4, 17, 27, 18, 22, 23, 24, 25, pwm=pwm) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class PiLiterBarGraph(LEDBarGraph): | ||||||
|  |     """ | ||||||
|  |     Extends :class:`LEDBarGraph` to treat the `Ciseco Pi-LITEr`_ as an | ||||||
|  |     8-segment bar graph. | ||||||
|  |  | ||||||
|  |     The Pi-LITEr pins are fixed and therefore there's no need to specify them | ||||||
|  |     when constructing this class. The following example sets the graph value | ||||||
|  |     to 0.5:: | ||||||
|  |  | ||||||
|  |         from gpiozero import PiLiterBarGraph | ||||||
|  |  | ||||||
|  |         graph = PiLiterBarGraph() | ||||||
|  |         graph.value = 0.5 | ||||||
|  |  | ||||||
|  |     :param bool initial_value: | ||||||
|  |         The initial value of the graph given as a float between -1 and +1. | ||||||
|  |         Defaults to 0.0. | ||||||
|  |  | ||||||
|  |     .. _Ciseco Pi-LITEr: http://shop.ciseco.co.uk/pi-liter-8-led-strip-for-the-raspberry-pi/ | ||||||
|  |     """ | ||||||
|  |     def __init__(self, initial_value=0): | ||||||
|  |         super(PiLiterBarGraph, self).__init__( | ||||||
|  |                 4, 17, 27, 18, 22, 23, 24, 25, initial_value=initial_value) | ||||||
|  |  | ||||||
|  |  | ||||||
| TrafficLightTuple = namedtuple('TrafficLightTuple', ('red', 'amber', 'green')) | TrafficLightTuple = namedtuple('TrafficLightTuple', ('red', 'amber', 'green')) | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user