Question 9.12: You want to respond to some event, such as a button push, wi......

You want to respond to some event, such as a button push, without having to continually poll the input pin to see if its state has changed.

Step-by-Step
The 'Blue Check Mark' means that this solution was answered by an expert.
Learn more on how do we answer questions.

Use the add_event_detect function of the RPi.GPIO library.

The upcoming example shows how you can attach an interrupt service routine to be triggered when a button is pressed.

Wire the switch onto a breadboard, as shown in Figure 9-16.

Open an editor (nano or IDLE) and paste in the following code. As with all the program examples in this book, you can also download the program from the Code section of the Raspberry Pi Cookbook website, where it is called interrupts.py.

This example code continually updates a count in seconds and displays a message when the button is pressed:

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
def my_callback(channel):
print(‘You pressed the button’)
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(18, GPIO.FALLING, callback=my_callback)
i = 0
while True:

i = i + 1
print(i)
time.sleep(1)

Try running the program with superuser privileges—you should see something like this happen when you press the button:

$ sudo python interrupts.py
1
2
3
You pressed the button
4
You pressed the button
5
You pressed the button
You pressed the button
6

Discussion

You could detect when a button has been pressed, or a GPIO input has changed, by simply checking repeatedly in a loop; for example:

while True:
if GPIO.input(18) == False:
# put the code to be actioned here
time.sleep(0.1)

The disadvantage here is that you can’t do much else while you are checking for button presses. A second disadvantage is that if the button press is very quick, it could come and go before you can register it with the GPIO.input. This approach is called polling.

Interrupts work differently. They allow you to associate a function with one of the pins so that when the voltage at the input changes either from low to high or vice versa, you can trigger the function to be run.

You can see how this works in the preceding example program. First, define a function called my_callback that takes a single argument. This argument specifies the input that triggered the interrupt, allowing you to use the same handler function for a number of interrupts.

def my_callback(channel):
print(‘You pressed the button’)

In this case, the callback function just displays a message.

The line of code that does the actual linking is:

GPIO.add_event_detect(18, GPIO.FALLING, callback=my_callback)

The first parameter specifies the pin (18). The second can be GPIO.FALLING or GPIO.RISING. If this is set to FALLING, the function will only be called if the GPIO pin goes from high to low. This is the case in this example, as the switch pulls the input low against the internal pull-up resistor. If, on the other hand, the second argument is set to RISING, the function will only be called when the input goes from low to high (when the switch is released).

The event handler function does not stop the main counting loop while it runs; it actually runs in its own separate thread of execution.

Switches often bounce when pressed. This means they don’t always transition cleanly from open to closed, but bounce between the two, possibly several times, making it appear that the button was pressed multiple times, in very rapid succession, when actually it was pressed only once.

If you keep pressing the button, you’ll probably see this reflected in the output as the message appearing more than once for one button press.

The library actually has an option to stop bounce from being a problem, by preventing the interrupt from being triggered again within a certain amount of time. To make use of this feature, just add the extra optional parameter bouncetime to the add_event_de tect call. The value of bouncetime is in milliseconds.

GPIO.add_event_detect(18, GPIO.FALLING, callback=my_callback, bouncetime=100)

See Also

For more information on using switches with the Raspberry Pi, see Recipe 11.1.

9-16

Related Answered Questions

Question: 9.11

Verified Answer:

Assuming you have a 5V volt meter, you can use a P...
Question: 9.10

Verified Answer:

The way to do this is to use a technique called Ch...
Question: 9.9

Verified Answer:

Use PWM to control the power to each of the red, g...
Question: 9.8

Verified Answer:

Using the Tkinter user interface framework, write ...
Question: 9.7

Verified Answer:

Using the Tkinter user interface framework, write ...
Question: 9.5

Verified Answer:

Use a relay and small transistor. Figure 9-5 shows...
Question: 9.1

Verified Answer:

Connect an LED (see “Opto-Electronics” on page 381...
Question: 9.3

Verified Answer:

Use a piezo-electric buzzer connected to a GPIO pi...
Question: 9.4

Verified Answer:

These high-power LEDs use far too much current to ...
Question: 9.6

Verified Answer:

Use a PowerSwitch Tail II (see “Modules” on page 3...