Pi IoT In Python Using GPIO Zero - Compound Devices
Written by Harry Fairhead & Mike James   
Monday, 07 February 2022
Article Index
Pi IoT In Python Using GPIO Zero - Compound Devices
An Example
LEDBarGraph

This is easier to understand after an example. The TriLED class can be implemented using CompositeDevice inheritance as:

 class TriLED(CompositeDevice):
    def __init__(self, pin1=None,pin2=None,pin3=None):
         super(TriLED, self).
__init__(LED(pin1),LED(pin2),LED(pin3)) def AllOn(self): self[0].on() self[1].on() self[2].on() def AllOff(self): self[0].off() self[1].off() self[2].off()

Notice that now it is the instance of TriLED that behaves as a container for the LEDs:

leds=TriLED(4,17,27)
while True:
    leds[0].on()
    sleep(0.001)
    leds[0].off()
    sleep(0.001)

You can see that there is access to the component LEDs, the LED on pin 4 in this case, and, in general, this is to be discouraged – you should provide methods that do the things the user wants to do without them having to access the component parts. This is an ideal and in some situations direct access to the components might be the only way of getting the job done.

If you do want to encourage access from the outside world then use named parameters:

class TriLED(CompositeDevice):
    def __init__(self, pin1=None,pin2=None,pin3=None):
         super(TriLED, self).__init__(left=LED(pin1),
middle=LED(pin2),right=LED(pin3))

Now you can write the more meaningful:

leds=TriLED(4,17,27)
while True:
    leds.left.on()
    sleep(0.001)
    ledsleft.off()
    sleep(0.001)

The CompositeDevice class also brings some extras of its own. The main one is value, which returns a named tuple with the current value of each device. For example:

leds=TriLED(4,17,27)
print(leds.value)

displays:

TriLEDValue(device_0=0, device_1=0, device_2=0)

For unnamed devices the class assigns a name, while for named devices the name given is used. You can adjust the order in which the devices are listed in the tuple using the _order parameter - the underscore at the start of the name is a sure sign that you are not expected to need it. For example, changing the call to the constructor to:

super(TriLED, self).__init__(left=LED(pin1),
middle=LED(pin2), right=LED(pin3),_order=["right","left","middle"])

results in printing:

TriLEDValue(right=0, left=0, middle=0)

If you need to create an identical type, the namedtuple attribute provides the class of the named tuple used to report the value. This is helpful if you are using the CompositeOutputDevice class.

CompositeOutputDevice

Usually a composite device has both input and output devices, but if it only has output the CompositeOutputDevice adds a few extra methods to CompositeDevice that are useful. In particular:

  • on() turns all devices on

  • off() turns all devices off

  • toggle() turns any on device off and any off device on.

Also the value attribute is modified to allow you to set the state of all of the output devices.

The CompositeOutputDevice makes implementing TriLED much easier:

from gpiozero import LED, CompositeOutputDevice
from time import sleep
class TriLED(CompositeOutputDevice):
    def __init__(self, pin1=None,pin2=None,pin3=None):
         super(TriLED, self).__init__(left=LED(pin1),
                        middle=LED(pin2),right=LED(pin3))

Notice that now you don’t have to define an allOn or allOff as they are inherited as on and off.

In addition you can now set the state of all of the output devices in one operation:

leds=TriLED(4,17,27)
while True:
    leds.value=leds.namedtuple(0,1,1)
    sleep(0.001)
    leds.value=leds.namedtuple(1,0,0)
    sleep(0.001)

This sets the LED on pin1 low and the other two high and then sets pin 1 high and the other two low.

LEDCollection

Devices with sets of LEDs are so common and so easy to make that there is a special LEDCollection version of CompositeOutputDevice which creates a tuple of LED or PWMLED objects. The default is to create LED objects, but you can change this using pwm=True in the constructor. It inherits the on, off and toggle methods from CompositeOutputDevice and has an leds attribute which gets or sets the LED tuple.

Using this we can implement TriLED as:

class TriLED(LEDCollection):
    def __init__(self, pin1=None,pin2=None,pin3=None):
         super(TriLED, self).__init__(left=pin1,
                              middle=pin2,right=pin3)

Notice that now we don’t need to specify that we are creating LED objects, just the pins used. Once you have an instance of this new class you can use it as before.

The LEDCollection class is used to implement many of the LED classes listed below.

  • LEDBoard

LEDBoard(*pins, pwm=False, active_high=True,
     initial_value=False, pin_factory=None, **named_pins)

This is the simplest of the composite LED devices and is just a collection of LEDs wired to specified GPIO pins, for example:

board=LEDBoard(4,17,27)

In addition to turning all of the LEDs on or off, and setting them to toggle, blink and pulse, you can control individual LEDs by specifying the device number. For example:

board.on(1)

turns on just the first specified LED, i.e. the one connected to GPIO4. You can use this in on, off and toggle, but not in pulse or blink.



Last Updated ( Monday, 07 February 2022 )