7. Source/Values¶
GPIO Zero provides a method of using the declarative programming paradigm to connect devices together: feeding the values of one device into another, for example the values of a button into an LED:
from gpiozero import LED, Button
from signal import pause
led = LED(17)
button = Button(2)
led.source = button.values
pause()
which is equivalent to:
from gpiozero import LED, Button
from time import sleep
led = LED(17)
button = Button(2)
while True:
led.value = button.value
sleep(0.01)
Every device has a value
property (the device’s current value).
Input devices can only have their values read, but output devices can also have
their value set to alter the state of the device:
>>> led = PWMLED(17)
>>> led.value # LED is initially off
0.0
>>> led.on() # LED is now on
>>> led.value
1.0
>>> led.value = 0 # LED is now off
Every device also has a values
property (a generator
continuously yielding the device’s current value). All output devices have a
source
property which can be set to any iterator. The
device will iterate over the values provided, setting the device’s value to
each element at a rate specified in the source_delay
property.
The most common use case for this is to set the source of an output device to the values of an input device, like the example above. A more interesting example would be a potentiometer controlling the brightness of an LED:
from gpiozero import PWMLED, MCP3008
from signal import pause
led = PWMLED(17)
pot = MCP3008()
led.source = pot.values
pause()
It is also possible to set an output device’s source
to
the values
of another output device, to keep them
matching:
from gpiozero import LED, Button
from signal import pause
red = LED(14)
green = LED(15)
button = Button(17)
red.source = button.values
green.source = red.values
pause()
The device’s values can also be processed before they are passed to the
source
:
For example:
from gpiozero import Button, LED
from signal import pause
def opposite(values):
for value in values:
yield not value
led = LED(4)
btn = Button(17)
led.source = opposite(btn.values)
pause()
Alternatively, a custom generator can be used to provide values from an artificial source:
For example:
from gpiozero import LED
from random import randint
from signal import pause
def rand():
while True:
yield randint(0, 1)
led = LED(17)
led.source = rand()
pause()
If the iterator is infinite (i.e. an infinite generator), the elements will be
processed until the source
is changed or set to None
.
If the iterator is finite (e.g. a list), this will terminate once all elements are processed (leaving the device’s value at the final element):
from gpiozero import LED
from signal import pause
led = LED(17)
led.source = [1, 0, 1, 1, 1, 0, 0, 1, 0, 1]
pause()
7.1. Composite devices¶
Most devices have a value
range between 0 and 1. Some have a
range between -1 and 1 (e.g. Motor
). The value
of a
composite device is a namedtuple of such values. For example, the
Robot
class:
>>> from gpiozero import Robot
>>> robot = Robot(left=(14, 15), right=(17, 18))
>>> robot.value
RobotValue(left_motor=0.0, right_motor=0.0)
>>> tuple(robot.value)
(0.0, 0.0)
>>> robot.forward()
>>> tuple(robot.value)
(1.0, 1.0)
>>> robot.backward()
>>> tuple(robot.value)
(-1.0, -1.0)
>>> robot.value = (1, 1) # robot is now driven forwards
7.2. Source Tools¶
GPIO Zero provides a set of ready-made functions for dealing with
source/values, called source tools. These are available by importing from
gpiozero.tools
.
Some of these source tools are artificial sources which require no input:
In this example, random values between 0 and 1 are passed to the LED, giving it a flickering candle effect:
from gpiozero import PWMLED
from gpiozero.tools import random_values
from signal import pause
led = PWMLED(4)
led.source = random_values()
led.source_delay = 0.1
pause()
Some tools take a single source and process its values:
In this example, the LED is lit only when the button is not pressed:
from gpiozero import Button, LED
from gpiozero.tools import negated
from signal import pause
led = LED(4)
btn = Button(17)
led.source = negated(btn.values)
pause()
Some tools combine the values of multiple sources:
In this example, the LED is lit only if both buttons are pressed (like an AND gate):
from gpiozero import Button, LED
from gpiozero.tools import all_values
from signal import pause
button_a = Button(2)
button_b = Button(3)
led = LED(17)
led.source = all_values(button_a.values, button_b.values)
pause()