diff --git a/docs/examples/combining_sources.py b/docs/examples/combining_sources.py new file mode 100644 index 0000000..136314c --- /dev/null +++ b/docs/examples/combining_sources.py @@ -0,0 +1,11 @@ +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() diff --git a/docs/examples/custom_generator.py b/docs/examples/custom_generator.py new file mode 100644 index 0000000..19a0f27 --- /dev/null +++ b/docs/examples/custom_generator.py @@ -0,0 +1,12 @@ +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() diff --git a/docs/examples/custom_generator_finite.py b/docs/examples/custom_generator_finite.py new file mode 100644 index 0000000..1678fa6 --- /dev/null +++ b/docs/examples/custom_generator_finite.py @@ -0,0 +1,7 @@ +from gpiozero import LED +from signal import pause + +led = LED(17) +led.source = [1, 0, 1, 1, 1, 0, 0, 1, 0, 1] + +pause() diff --git a/docs/examples/led_button.py b/docs/examples/led_button.py new file mode 100644 index 0000000..ba66df5 --- /dev/null +++ b/docs/examples/led_button.py @@ -0,0 +1,9 @@ +from gpiozero import LED, Button +from signal import pause + +led = LED(17) +button = Button(2) + +led.source = button.values + +pause() diff --git a/docs/examples/led_button_loop.py b/docs/examples/led_button_loop.py new file mode 100644 index 0000000..8e28368 --- /dev/null +++ b/docs/examples/led_button_loop.py @@ -0,0 +1,7 @@ +from gpiozero import LED, Button + +led = LED(17) +button = Button(2) + +while True: + led.value = button.value diff --git a/docs/examples/matching_leds.py b/docs/examples/matching_leds.py new file mode 100644 index 0000000..542a711 --- /dev/null +++ b/docs/examples/matching_leds.py @@ -0,0 +1,11 @@ +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() diff --git a/docs/examples/negated.py b/docs/examples/negated.py new file mode 100644 index 0000000..e7cc2cf --- /dev/null +++ b/docs/examples/negated.py @@ -0,0 +1,9 @@ +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() diff --git a/docs/examples/pwmled_pot.py b/docs/examples/pwmled_pot.py new file mode 100644 index 0000000..00e1e5c --- /dev/null +++ b/docs/examples/pwmled_pot.py @@ -0,0 +1,9 @@ +from gpiozero import PWMLED, MCP3008 +from signal import pause + +led = PWMLED(17) +pot = MCP3008() + +led.source = pot.values + +pause() diff --git a/docs/examples/random_values.py b/docs/examples/random_values.py new file mode 100644 index 0000000..99a2572 --- /dev/null +++ b/docs/examples/random_values.py @@ -0,0 +1,8 @@ +from gpiozero import PWMLED +from gpiozero.tools import random_values +from signal import pause + +led = PWMLED(4) +led.source = random_values() + +pause() diff --git a/docs/images/combining_sources.png b/docs/images/combining_sources.png new file mode 100644 index 0000000..5f9c98e Binary files /dev/null and b/docs/images/combining_sources.png differ diff --git a/docs/images/custom_generator.png b/docs/images/custom_generator.png new file mode 100644 index 0000000..1434cb6 Binary files /dev/null and b/docs/images/custom_generator.png differ diff --git a/docs/images/source_tool.png b/docs/images/source_tool.png new file mode 100644 index 0000000..9563abf Binary files /dev/null and b/docs/images/source_tool.png differ diff --git a/docs/images/source_tool_value_processor.png b/docs/images/source_tool_value_processor.png new file mode 100644 index 0000000..9e05a98 Binary files /dev/null and b/docs/images/source_tool_value_processor.png differ diff --git a/docs/images/source_value_processing.png b/docs/images/source_value_processing.png new file mode 100644 index 0000000..c31aed5 Binary files /dev/null and b/docs/images/source_value_processing.png differ diff --git a/docs/images/source_values.png b/docs/images/source_values.png new file mode 100644 index 0000000..a424928 Binary files /dev/null and b/docs/images/source_values.png differ diff --git a/docs/index.rst b/docs/index.rst index 256db1e..0f36e08 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -18,6 +18,7 @@ Table of Contents api_tools api_pins api_exc + source_values changelog license diff --git a/docs/source_values.rst b/docs/source_values.rst new file mode 100644 index 0000000..45d49e5 --- /dev/null +++ b/docs/source_values.rst @@ -0,0 +1,133 @@ +============= +Source/Values +============= + +.. currentmodule:: gpiozero + +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: + +.. literalinclude:: examples/led_button.py + +which is equivalent to: + +.. literalinclude:: examples/led_button_loop.py + +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. + +.. image:: images/source_values.* + +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. It is also possible to +set the source of an output device to the values of another output device (so +they match): + +.. literalinclude:: examples/led_button.py + +A more interesting example would be a potentiometer controlling the brightness +of an LED: + +.. literalinclude:: examples/pwmled_pot.py + +It is also possible to set an output device's ``source`` to the ``values`` of +another output device, to keep them matching: + +.. literalinclude:: examples/matching_leds.py + +The device's values can also be processed before they are passed to the +``source``: + +.. image:: images/source_value_processing.* + +For example: + +.. literalinclude:: examples/custom_generator.py + +Alternatively, a custom generator can be used to provide values from an +artificial source: + +.. image:: images/custom_generator.* + +For example: + +.. literalinclude:: examples/custom_generator.py + +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): + +.. literalinclude:: examples/custom_generator_finite.py + +Composite devices +----------------- + +Most devices have a ``value`` range between 0 and 1. Some have a range between +-1 and 1 (e.g. ``Robot``). The ``value`` of a composite device is a namedtuple +of such values. For example:: + + >>> 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 + +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: + +.. image:: images/source_tool.* + +In this example, random values between 0 and 1 are passed to the LED, giving it +a flickering candle effect: + +.. literalinclude:: examples/random_values.py + +Some tools take a single source and process its values: + +.. image:: images/source_tool_value_processor.* + +In this example, the LED is lit only when the button is not pressed: + +.. literalinclude:: examples/negated.py + +Some tools combine the values of multiple sources: + +.. image:: images/combining_sources.* + +In this example, the LED is lit only if both buttons are pressed (like an `AND`_ +gate): + +.. _AND: https://en.wikipedia.org/wiki/AND_gate + +.. literalinclude:: examples/combining_sources.py