Event-Driven Input/Output

The button-blink example shows how to read from a GPIO pin, but not how to react promptly to a signal on the pin. It reads the pin's value at regular intervals, but if a signal occurs on the pin between reads the program won't react until the next time it reads from the pin.

To react promptly to GPIO input we must change the way our program works. Instead of being in control, polling the GPIO pins and sleeping for fixed amounts of time, our program needs to be event driven: reacting as soon as the signal at the input pin changes and using timer events to decide when to blink the LED.

An event-driven program uses a Selector object to wait for events to occur on a number of event sources -- for example GPIO input pins, timers or network connections. The program creates a Selector, creates event source objects that can signal events, adds the event sources to the Selector, and runs an event loop in which it waits on the Selector for an events to occur and then handles the latest event reported by the Selector.

As we are converting the button-blink example to be event-driven, we need two event sources: the GPIO pin connected to the button and, because we can't put the process to sleep for half a second to blink the LED, a repeating timer that tells the program when to turn the LED off it is currently on and vice versa.

#!/usr/bin/env python3
 
from quick2wire.gpio import pins, In, Out, Both
from quick2wire.selector import Selector, Timer
 
selector = Selector()
button = pins.pin(0, direction=In, interrupt=Both)
led = pins.pin(1, direction=Out)
 
timer = Timer(interval=0.5)
 
with selector, button, led, timer:
    selector.add(button)
    selector.add(timer)
    
    while True:
        selector.wait()
        
        if selector.ready == timer:
            timer.wait()
            
            led.value = not led.value
        
        elif selector.ready == button:
            is_pressed = button.value
            
            if is_pressed:
                led.value = 1
                timer.start()
            else:
                led.value = 0
                timer.stop()

When you run this program you will see that it reacts promptly to button presses.

Generated with Code Guide.