General-Purpose I/O on Raspberry Pi’s 40-pin J8 header:
In this article I’ll be wiring up four inputs to pushbuttons, and four outputs to light-emitting diodes, then writing software to light up yellow to replay a remote control signal, and the green/red when certain aircraft flights are detected overhead, all controlled through the GPIO port. All the components I’m using are from the Sparkfun Raspberry Pi 3 Starter Kit.
Pi Wedge for breaking out the J8 header to a breadboard, uses abbreviated pin name labels, like “G17” for GPIO 17, and when a GPIO pin has an alternate function it lists that function instead, so GPIO 2 on pin #3 is labeled “SDA”.
Port selection is arbitrary, but I wanted to keep the overloaded pins available for their other purposes in the future, so I decided on:
- Pin #11 / GPIO 17: green pushbutton
- Pin #12 / GPIO 18 red pushbutton
- Pin #13 / GPIO 27: yellow pushbutton
- Pin #15 / GPIO 22: blue pushbutton
- Pin #29 / GPIO 5: green LED
- Pin #31 / GPIO 6: red LED
- Pin #32 / GPIO 12: yellow LED
- Pin #33 / GPIO 13: blue LED
Sparkfun also sells a larger assortment of tactile buttons but the Raspberry Pi 3 starter kit includes one each of red, yellow, green, and blue. The pins connect as follows:
I had already connected these buttons in SDR first project: initial setup, node-hackrf, GNU Radio on Linux, OS X, RPi 3 w/ FM tuner, where they functioned as volume and channel controls, but I moved them further apart in the breadboard to allow room for the LEDs.
This is a garden variety pack of LEDs, there are many other colors not included: orange (600–610 nm) and violet (395–400 nm), infrared (940–950 nm, or 840–850 nm), ultraviolet (395–400 nm). There are other types of LEDs available, including different wavelengths of ultraviolet (UVA/UVB), from other suppliers such as LEDsupply and ThorLabs.
Ultraviolet could be useful as a blacklight, and infrared could be useful to send to infrared sensors on some RTL-SDR dongles (but not the RTL-SDR Blog silver dongle). But for now, I’ll only be using these red, yellow, green, and blue color LEDs from the starter kit.
Conveniently, resistors are included for current-limiting, 20 total (one each for the 5*4 LEDs):
All of the LEDs are suitable for use with the 330 Ω resistors at 3.3 V, at a reasonable brightness. Connect the resistor to one side of the LED, and to a GPIO port. Wiring should be straightforward, or see below for a photo.
After wiring up all the pushbuttons and LEDs and resistors to the GPIO pins, wrote a simple Python script using RPi.GPIO:
import RPi.GPIO as GPIO
BTN_G = 11 # G17
BTN_R = 12 # G18
BTN_Y = 13 # G27
BTN_B = 15 # G22
LED_G = 29 # G5
LED_R = 31 # G6
LED_Y = 32 # G12
LED_B = 33 # G13
GPIO.setup([BTN_G, BTN_R, BTN_Y, BTN_B], GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup([LED_G, LED_R, LED_Y, LED_B], GPIO.OUT, initial=GPIO.LOW)
[g, r, y, b] = [GPIO.input(BTN_G), GPIO.input(BTN_R), GPIO.input(BTN_Y), GPIO.input(BTN_B)]
GPIO.output(LED_G, not g)
GPIO.output(LED_R, not r)
GPIO.output(LED_Y, not y)
GPIO.output(LED_B, not b)
Script available here: gptest.py. Press a button and the corresponding LED should light up. Testing with all LEDs lit up:
Application: remote control signal replay
As described in Receiving IR signals with RTL-SDR dongles, I’m using the IR sensor of a NooElec NESDR RTL-SDR dongle to receive signals from remote controls, currently for powering off or rebooting the device. But it would be nice to know whether IR is working without performing those actions, and to know what pulses are being sent.
Updated nec-pwr.py to flash the yellow LED, “replaying” the infrared signal 100x slower:
for group in groups:
if ‘0’ in group: light_leds(False)
time.sleep(len(group) * 20e-6 * 100)
It could be replayed even lower to help visually discern the pulses, or near realtime if desired, but I went with 100x for the time being.
Application: flight watchlist
On this same device I’m also running dump1090, tracking flights using ADS-B. But some aircraft are more interesting than others.
dump1090 can be interfaced through TCP port 30003, which streams CSV data using the SBS1 port 30003 format. We can connect to this port, pick out the callsign, and light up the LEDs appropriately. Script to do this:
- /etc/init.d/flightled — startup script
- /home/pi/ads-b/flightled.py — daemon script (be sure to chmod a+x)
Update 2016/07/12: latest version of flightled moved to https://github.com/rxseger/flightled
Edit the settings as needed, run sudo /etc/init.d/flightled start to begin, and sudo ln -s /etc/init.d/flightled /etc/rc5.d/S01flightled to run on boot. The script is configured to turn on the green LED when any flight with a callsign is observed, for one second. And the red LED turns on for 12 hours when a callsign listed in watchlist.txt is observed.
How to find “interesting” flights to watch? A good start is ListFAA-BARRpgm_2013.pdf, a list of 6912 callsigns from what used to be known as the Block Aircraft Registration Request BARR program, now the FAA Aircraft Situation Display to Industry ASDI Block. These aircraft are voluntarily blocked from FlightAware, FlightRadar24 (though not ADS-B Exchange), but homemade ADS-B receivers will receive them.
You can also find interesting callsigns by other means:
The GPIO is an easy and convenient means of providing simple button input and LED output on a headless Raspberry Pi. With a quick glance I can now test for remote control infrared signal decoding, dump1090 flight tracking status, and whether any particularly interesting fights were recently seen.
This is only a relatively unsophisticated configuration, much more is possible with GPIO including controlling various peripheral devices. The blue LED is software-controllable, but I haven’t figured out a use for it yet, nor the pushbutton inputs. Lots of possibilities for future expansion.