A simple interface to GPIO devices with Raspberry Pi
—
Source chaining utility functions for complex device interactions and value transformations. These functions enable declarative programming patterns and advanced device coordination in GPIO Zero's source/values system.
from gpiozero.tools import negated, inverted, scaled
from gpiozero.tools import all_values, any_values, averaged
from gpiozero.tools import booleanized, clampedNegate boolean values in a stream.
def negated(values):
"""
Returns the negation of the supplied values (True becomes False, False becomes True).
Parameters:
- values: Iterable of boolean values or ValuesMixin device
Returns:
Generator yielding negated values
"""Usage Example:
from gpiozero import LED, Button
from gpiozero.tools import negated
from signal import pause
led = LED(17)
button = Button(2)
# LED is on when button is NOT pressed
led.source = negated(button)
pause()Invert numeric values within a specified range.
def inverted(values, input_min=0, input_max=1):
"""
Returns the inversion of supplied values within the specified range.
Parameters:
- values: Iterable of numeric values or ValuesMixin device
- input_min: float - Minimum value of input range (default: 0)
- input_max: float - Maximum value of input range (default: 1)
Returns:
Generator yielding inverted values
"""Usage Example:
from gpiozero import PWMLED, MCP3008
from gpiozero.tools import inverted
from signal import pause
led = PWMLED(17)
pot = MCP3008(0)
# LED brightness is inverted - bright when pot is low
led.source = inverted(pot)
pause()Scale values from one range to another.
def scaled(values, output_min, output_max, input_min=0, input_max=1):
"""
Scale values from input range to output range.
Parameters:
- values: Iterable of numeric values or ValuesMixin device
- output_min: float - Minimum value of output range
- output_max: float - Maximum value of output range
- input_min: float - Minimum value of input range (default: 0)
- input_max: float - Maximum value of input range (default: 1)
Returns:
Generator yielding scaled values
"""Usage Example:
from gpiozero import Motor, MCP3008
from gpiozero.tools import scaled
from signal import pause
motor = Motor(20, 21)
pot = MCP3008(0)
# Scale potentiometer (0-1) to motor range (-1 to 1)
motor.source = scaled(pot, -1, 1)
pause()Clamp values to stay within specified bounds.
def clamped(values, min_value=0, max_value=1):
"""
Clamp values to stay within specified minimum and maximum bounds.
Parameters:
- values: Iterable of numeric values or ValuesMixin device
- min_value: float - Minimum allowed value (default: 0)
- max_value: float - Maximum allowed value (default: 1)
Returns:
Generator yielding clamped values
"""Logical AND operation on multiple value sources.
def all_values(*sources):
"""
Returns True only when all source values are True (logical AND).
Parameters:
- *sources: Variable number of value sources (devices or iterables)
Returns:
Generator yielding True when all sources are True
"""Logical OR operation on multiple value sources.
def any_values(*sources):
"""
Returns True when any source value is True (logical OR).
Parameters:
- *sources: Variable number of value sources (devices or iterables)
Returns:
Generator yielding True when any source is True
"""Logical Combination Example:
from gpiozero import LED, Button, MotionSensor
from gpiozero.tools import all_values, any_values
from signal import pause
security_light = LED(17)
manual_button = Button(2)
motion1 = MotionSensor(4)
motion2 = MotionSensor(5)
# Light turns on when button pressed OR motion detected on either sensor
security_light.source = any_values(manual_button, motion1, motion2)
# Alternative: Light only when button pressed AND motion detected
# security_light.source = all_values(manual_button, any_values(motion1, motion2))
pause()Average values over a time window.
def averaged(values, samples=10):
"""
Returns the mean average of the last n samples from values.
Parameters:
- values: Iterable of numeric values or ValuesMixin device
- samples: int - Number of samples to average (default: 10)
Returns:
Generator yielding averaged values
"""Usage Example:
from gpiozero import PWMLED, MCP3008
from gpiozero.tools import averaged
from signal import pause
led = PWMLED(17)
light_sensor = MCP3008(0)
# LED brightness follows smoothed light sensor reading
led.source = averaged(light_sensor, samples=20)
pause()Convert numeric values to boolean based on threshold.
def booleanized(values, threshold=0.5):
"""
Convert numeric values to boolean based on threshold comparison.
Parameters:
- values: Iterable of numeric values or ValuesMixin device
- threshold: float - Threshold for True/False conversion (default: 0.5)
Returns:
Generator yielding boolean values
"""Usage Example:
from gpiozero import LED, LightSensor
from gpiozero.tools import booleanized
from signal import pause
night_light = LED(17)
light_sensor = LightSensor(7)
# Light turns on when sensor reads below 0.1 (dark)
night_light.source = booleanized(light_sensor, 0.1)
pause()Generate random values within a specified range.
def random_values(*, min_value=0, max_value=1):
"""
Generate infinite stream of random values.
Parameters:
- min_value: float - Minimum random value (default: 0)
- max_value: float - Maximum random value (default: 1)
Returns:
Generator yielding random values
"""Convenience function to scale half-range values (0..1) to full-range (-1..1).
def scaled_full(values):
"""
Scale half-range values (0..1) to full-range (-1..1).
Parameters:
- values: Iterable of numeric values or ValuesMixin device
Returns:
Generator yielding full-range values
"""Convenience function to scale full-range values (-1..1) to half-range (0..1).
def scaled_half(values):
"""
Scale full-range values (-1..1) to half-range (0..1).
Parameters:
- values: Iterable of numeric values or ValuesMixin device
Returns:
Generator yielding half-range values
"""Clamp values to specified minimum and maximum bounds.
def clamped(values, output_min=0, output_max=1):
"""
Clamp values to specified bounds.
Parameters:
- values: Iterable of numeric values or ValuesMixin device
- output_min: float - Minimum output value (default: 0)
- output_max: float - Maximum output value (default: 1)
Returns:
Generator yielding clamped values
"""Return absolute values (all negative values become positive).
def absoluted(values):
"""
Return absolute values of supplied values.
Parameters:
- values: Iterable of numeric values or ValuesMixin device
Returns:
Generator yielding absolute values
"""Quantize values to specified number of discrete steps.
def quantized(values, steps, input_min=0, input_max=1):
"""
Quantize values to discrete steps.
Parameters:
- values: Iterable of numeric values or ValuesMixin device
- steps: int - Number of quantization steps
- input_min: float - Minimum input value (default: 0)
- input_max: float - Maximum input value (default: 1)
Returns:
Generator yielding quantized values
"""Sum values from multiple sources.
def summed(*values):
"""
Return sum of all supplied value streams.
Parameters:
- values: Variable number of iterables or ValuesMixin devices
Returns:
Generator yielding summed values
"""Multiply values from multiple sources.
def multiplied(*values):
"""
Return product of all supplied value streams.
Parameters:
- values: Variable number of iterables or ValuesMixin devices
Returns:
Generator yielding multiplied values
"""Queue values with specified buffer size.
def queued(values, qsize):
"""
Queue values with specified buffer size.
Parameters:
- values: Iterable of values or ValuesMixin device
- qsize: int - Queue buffer size
Returns:
Generator yielding queued values
"""Smooth values using specified averaging function.
def smoothed(values, qsize, average=mean):
"""
Smooth values using moving average.
Parameters:
- values: Iterable of values or ValuesMixin device
- qsize: int - Size of smoothing window
- average: function - Averaging function (default: statistics.mean)
Returns:
Generator yielding smoothed values
"""Add delay before processing values.
def pre_delayed(values, delay):
"""
Add delay before yielding each value.
Parameters:
- values: Iterable of values or ValuesMixin device
- delay: float - Delay in seconds before each value
Returns:
Generator yielding delayed values
"""Add delay after processing values.
def post_delayed(values, delay):
"""
Add delay after yielding each value.
Parameters:
- values: Iterable of values or ValuesMixin device
- delay: float - Delay in seconds after each value
Returns:
Generator yielding values with post-delay
"""Filter values periodically before processing.
def pre_periodic_filtered(values, block, repeat_after):
"""
Filter values periodically before processing.
Parameters:
- values: Iterable of values or ValuesMixin device
- block: float - Duration to block values
- repeat_after: float - Period after which to repeat blocking
Returns:
Generator yielding filtered values
"""Filter values periodically after processing.
def post_periodic_filtered(values, repeat_after, block):
"""
Filter values periodically after processing.
Parameters:
- values: Iterable of values or ValuesMixin device
- repeat_after: float - Period after which to repeat blocking
- block: float - Duration to block values
Returns:
Generator yielding filtered values
"""Generate sine wave values.
def sin_values(period=360):
"""
Generate sine wave values.
Parameters:
- period: int - Period in steps for complete sine wave (default: 360)
Returns:
Generator yielding sine wave values (-1 to 1)
"""Generate cosine wave values.
def cos_values(period=360):
"""
Generate cosine wave values.
Parameters:
- period: int - Period in steps for complete cosine wave (default: 360)
Returns:
Generator yielding cosine wave values (-1 to 1)
"""Generate alternating True/False values.
def alternating_values(initial_value=False):
"""
Generate alternating boolean values.
Parameters:
- initial_value: bool - Starting value (default: False)
Returns:
Generator yielding alternating boolean values
"""Generate ramping values (sawtooth wave).
def ramping_values(period=360):
"""
Generate ramping sawtooth wave values.
Parameters:
- period: int - Period in steps for complete ramp (default: 360)
Returns:
Generator yielding ramping values (0 to 1)
"""Combine multiple device value streams.
def zip_values(*devices):
"""
Combine multiple device value streams into tuples.
Parameters:
- devices: Variable number of ValuesMixin devices
Returns:
Generator yielding tuples of values from each device
"""from gpiozero import LED, Button, MotionSensor, LightSensor
from gpiozero.tools import all_values, any_values, booleanized, negated
from signal import pause
# Devices
security_light = LED(17)
disable_switch = Button(2)
motion_sensor = MotionSensor(4)
light_sensor = LightSensor(7)
# Security light logic:
# - Motion detected AND it's dark AND system not disabled
motion_active = motion_sensor
is_dark = booleanized(light_sensor, 0.2) # Dark when < 0.2
system_enabled = negated(disable_switch) # Enabled when switch not pressed
security_light.source = all_values(motion_active, is_dark, system_enabled)
pause()from gpiozero import Motor, MCP3008, Button
from gpiozero.tools import scaled, clamped, negated
from signal import pause
motor = Motor(20, 21)
speed_pot = MCP3008(0) # Speed control potentiometer
reverse_button = Button(2) # Reverse direction button
# Scale potentiometer to motor speed range
base_speed = scaled(speed_pot, 0, 1) # 0 to 1 forward
# Apply direction based on button (negate for reverse)
def directional_speed():
for speed in base_speed:
if reverse_button.is_pressed:
yield -speed # Reverse direction
else:
yield speed # Forward direction
motor.source = directional_speed()
pause()from gpiozero import OutputDevice, MCP3008, TimeOfDay
from gpiozero.tools import all_values, booleanized, inverted
from signal import pause
irrigation_pump = OutputDevice(17)
soil_moisture = MCP3008(0) # Soil moisture sensor
daytime = TimeOfDay(start_time=(6, 0), end_time=(20, 0))
# Irrigation logic:
# - Soil is dry (low moisture reading)
# - During daytime hours only
soil_dry = booleanized(inverted(soil_moisture), 0.3) # Invert: low reading = dry
during_day = daytime
irrigation_pump.source = all_values(soil_dry, during_day)
pause()from gpiozero import Motor, CPUTemperature
from gpiozero.tools import scaled, clamped
from signal import pause
cooling_fan = Motor(20, 21)
cpu_temp = CPUTemperature()
# Fan speed based on CPU temperature
# - No fan below 50°C
# - Full speed at 80°C and above
def temp_to_fan_speed():
for temp in cpu_temp.values:
if temp < 50:
yield 0 # No cooling needed
elif temp > 80:
yield 1 # Full speed
else:
# Scale from 50-80°C to 0-1 fan speed
yield (temp - 50) / 30
cooling_fan.source = clamped(temp_to_fan_speed(), 0, 1)
pause()These utility functions enable powerful declarative programming patterns where device behavior is described through value transformations and logical combinations rather than imperative control loops.
Install with Tessl CLI
npx tessl i tessl/pypi-gpiozero