A few days ago, Ben Croston updated the RPi.GPIO Python library so that the ‘board’ pin numbering system would work with all of the pins on the B+. It doesn’t really affect the way I work, as I always use BCM port numbers. They already worked on the B+ and the compute module.
While he was at it, he made a couple of bug-fix tweaks. Looking at what was tweaked, I realised there are a couple of features of RPi.GPIO that I hadn’t yet documented. In this blog post I hope to update my RPi.GPIO documentation. RPi.GPIO 0.5.6 is already in the Raspbian repository, so to update to 0.5.6, just…
sudo apt-get update
sudo apt-get upgrade
Edge Detection Addition
In my previous tutorials on threaded callbacks we used edge detection of RISING and FALLING edges. Somewhere along the line, Ben introduced an option to test for BOTH falling and rising edges. I knew about this, but hadn’t tried it before.
So, where previously we had the code…
for a rising edge
GPIO.add_event_detect(25, GPIO.RISING, callback=my_callback)
GPIO.add_event_detect(25, GPIO.FALLING, callback=my_callback) for a falling edge
Now we can also detect edges in either changing direction, using BOTH…
GPIO.add_event_detect(25, GPIO.BOTH, callback=my_callback) for either rising or falling edges.
“Hold on”, you say. “That’s all very well, but how do I know whether it’s FALLING or RISING?”
It’s easy, when you think about it. Just read the port using GPIO.input(25) in the callback function. If it’s 0/LOW/False, it was FALLING, and if it’s 1/HIGH/True, it was RISING. As Andrew correctly points out in the comments, it’s a good idea to have as little code as possible in your callback function to avoid missing any transitions while the code is executing.
That’s a bit abstract, so to test it, we’ll need a little circuit and some code.
Let’s Make a Circuit
The 10k resistor is a pull-down, to give the port a default status of 0/LOW/False.
The 1k resistor is to protect the port.
The 100 nF capacitor is needed in order to see the effect we’re looking for. It debounces the switch in hardware because we’ve removed the ‘bouncetime=300’ from the ‘GPIO.add_event_detect’. We did that so we can see what’s happening in real-time.
When you press the button, 3V3 connects to GPIO 25 (through the 1k resistor) and causes a Rising edge on the port. If you keep the button pressed, nothing should happen. When you release the button, the 10k pull-down resistor will pull GPIO 25 back to GND and a Falling edge will result.
The program ends after 30 seconds.
Here’s what my circuit looked like (I used a 330R instead of a 1k)…
Here’s the Full Code
#!/usr/bin/env python2.7 # demo of "BOTH" bi-directional edge detection # script by Alex Eames http://RasPi.tv # http://raspi.tv/?p=6791 import RPi.GPIO as GPIO from time import sleep # this lets us have a time delay (see line 12) GPIO.setmode(GPIO.BCM) # set up BCM GPIO numbering GPIO.setup(25, GPIO.IN) # set GPIO25 as input (button) # Define a threaded callback function to run in another thread when events are detected def my_callback(channel): if GPIO.input(25): # if port 25 == 1 print "Rising edge detected on 25" else: # if port 25 != 1 print "Falling edge detected on 25" # when a changing edge is detected on port 25, regardless of whatever # else is happening in the program, the function my_callback will be run GPIO.add_event_detect(25, GPIO.BOTH, callback=my_callback) print "Program will finish after 30 seconds or if you press CTRL+C\n" print "Make sure you have a button connected, pulled down through 10k resistor" print "to GND and wired so that when pressed it connects" print "GPIO port 25 (pin 22) to GND (pin 6) through a ~1k resistor\n" print "Also put a 100 nF capacitor across your switch for hardware debouncing" print "This is necessary to see the effect we're looking for" raw_input("Press Enter when ready\n>") try: print "When pressed, you'll see: Rising Edge detected on 25" print "When released, you'll see: Falling Edge detected on 25" sleep(30) # wait 30 seconds print "Time's up. Finished!" finally: # this block will run no matter how the try block exits GPIO.cleanup() # clean up after yourself
So when you run the program, you should see the wiring instructions, then you press <ENTER> to start.
After that, when you press the button, you get a single “Rising Edge” message and when you release it, you get a single “Falling Edge” message.
Here’s a little video clip to show what should happen…
Hope you enjoyed that little experiment. If you want to learn more about RPi.GPIO and GPIO hacking on the Raspberry Pi, there’s a whole series of tutorials here…