Hacker School is a three-month self-directed environment for becoming a better programmer. I’m in the current batch.
Several of the current Hacker Schoolers expressed a desire to learn more about hardware hacking. @leocadiotine and I decided to spend an evening building a Raspberry Pi sensor interface project to show how easy it can be to get into hardware.
@sashalaundy gave a short talk this week on RESTful API design. She used the Twilio API for phone and SMS as an example — Leo and I decided to give it a try for this project.
Leo and I wanted to build a project that improved our surroundings in some small way. The Hacker School space in NYC has two restrooms: one attached to the main work area, and one downstairs. It’s a short walk, but we thought it would nice to know if the bathroom is occupied before taking the time to walk.
Our project makes it possible to check the bathroom status by phone or text message.
Bathroom occupancy status is determined using a light sensor attached to a Raspberry Pi. If the lights are on in the bathroom, we assume that the bathroom is occupied.
We created a web application hosted on Heroku which accepts periodic bathroom state updates from the Raspberry Pi and handles incoming requests from Twilio. When a user calls or texts the Twilio phone number, Twilio sends a request to the web app, which responds with an appropriate message to be spoken or texted to the user.
In addition to the voice and text interface, @gelstudios created a nice web interface using Bootstrap.
The project certainly isn’t doing anything that hasn’t been done before, but for an evening project it made a nice demo. I hope this post will serve as a nice guide for anyone looking to get started with a web-interfaced Raspberry Pi sensor project.
Twilio is a web-based service for sending and receiving phone calls and SMS text messages. It provides an easy-to-use API accessible via HTTP and a convenient Python package. A free trial of the service is available, though it does insert a nag notice into outgoing messages. We used the Twilio Python Quickstart Tutorials as our introduction.
Heroku is a service which provides a complete, integrated stack for hosting web applications with a range of choices in language, framework, web server and data store. We created the server application for the project in Python using the Flask microframework. The Heroku Dev Center article Getting Started with Python on Heroku is a good walkthrough for setting up Flask on Heroku.
Full source for the web application can be found at github.com/qqrs/twilio-light-sensor-server/blob/master/run.py. Interesting sections are included below.
The sensor state is not persisted to database — if the Heroku app instance spins down, the sensor state will be unknown when the next request causes it to spin up again. For purposes of a demo, the server will be kept active by frequent updates from the remote sensor — it should only spin down when there are no remote sensors sending data.
/twilio/text routes handle requests from Twilio.
When a user calls or sends an SMS message to the phone number assigned to our account, Twilio is configured so that it will make an HTTP POST request to these routes.
When the server receives the request from Twilio, it generates an appropriate message indicating the status of the bathroom.
The message is returned to Twilio in the HTTP response and is sent to the user as either audio (by text-to-speech) or as an SMS message.
/update route accepts sensor state updates from the remote sensor via HTTP POST.
Each request includes
sensor_val parameters to identify
the sensor and report the current value.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
The Raspberry Pi is a single-board computer with an ARM-core processor, SD card slot, HDMI and composite video, USB, and optional Ethernet. While similar ARM dev boards and single-board computers have existed for years the Raspberry Pi was able to hit an enticing price point and combines several attractive qualities in one package, making it a popular choice for hobby electronics projects.
Price point: $35 with Ethernet, $25 without (plus cost of shipping, tax, power supply, SD card). This is down into Arduino territory — low enough to build a project without worrying about tearing it apart right away to recover the Raspberry Pi.
Integrated Peripherals: It has HDMI video (1080p with hardware decoding), audio, Ethernet, USB (with support for Wi-Fi). It also has an expansion header with general purpose input/output (GPIO) pins for interfacing to digital signals (LEDs, pushbuttons) and a UART, a SPI bus, and an I²C bus (memory devices, sensors). The combination of video and networking with low-level interfaces in one low-cost device opens up many possibilities.
Linux OS: The 700 MHz ARM11-core processor is fast enough to run a full Linux distribution. The Raspberry Pi Foundation provides images of Debian and Arch Linux tailored for the hardware. Many other distributions have been contributed by users. Having a full Linux OS allows the use of higher-level languages like Python and interactive debugging on the device.
A 5V USB power supply and an SD card with an operating system installed are required to begin using the Raspberry Pi. A good guide to getting started can be found at the elinux.org wiki. Preloaded SD cards can be purchased from several vendors or an operating system image can be loaded onto a blank SD card.
Note that it is important to have a stable power supply. Some USB 5V supplies may be inadequate.
I experienced SD card corruption several times until I bought a good supply
over_voltage=2 in the config.txt file as described here.
Any good supply with at leat a 1.0 amp current rating should be acceptable.
The light sensor is a 10k CdS photocell, interfaced to a Raspberry Pi with an analog-to-digital converter (ADC) daughterboard. The light sensor is connected to an input of the ADC in a voltage divider configuration with a 10k resistor. With illumination from overhead lighting, the resistance of the photocell drops to about 1.5k.
An analog-to-digital converter (ADC) is required to read the signal from the light sensor. The Raspberry Pi does not have an integrated ADC like the Arduino and many microcontroller dev boards. However, it is straightforward to interface an external ADC via the SPI or I²C buses. Adafruit provides a good guide to using the Microchip MCP3008: Analog Inputs for Raspberry Pi Using the MCP3008.
I had soldered up an an MCP3008 on protoboard for another project so I reused it for this project.
A number of assembled expansion boards which provide an ADC are available from third-party vendors.
Raspberry Pi Remote Sensor Monitoring Script
Adafruit provides sample code in Python to read from the ADC via the SPI bus.
Full source for the remote sensor monitoring script can be found at github.com/qqrs/twilio-light-sensor-remote/blob/master/twilio_light_sensor.py. Interesting sections are included below.
The monitoring script consists of a polling loop which reads the sensor at a defined interval.
readadc(), a function provided by Adafruit which bit-bangs the SPI communication in software — some versions of the Raspberry Pi did not include hardware SPI.
Sensor state is determined by comparing the ADC value to a fixed threshold — if greater than the threshold, the light is assumed to be on.
A moving average is used to prevent a noisy read from being interpreted as a change in state.
The sensor state is reported to the server via an HTTP POST request by
update_server_state() whenever the sensor state changes, or at least every 60 seconds when it has not changed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
To run the script, Python packages must be installed. See the Adafruit article
The script can be run at the terminal:
To run the script automatically at boot, it can be added to the end of
immediately before the
exit 0 line:
python /home/pi/twilio_light_sensor/twilio_light_sensor.py &
(modifying the path to script if necessary).
Note that the trailing ampersand
& is required — this forks a subshell and allows the rest of the init sequence to complete.
The script can be stopped by switching to another tty with Ctrl-Alt-F2, logging in, finding the process ID with
ps aux | grep twilio, and killing the process with
With the server running on Heroku and the light sensor attached to the Raspberry Pi, Twilio responds to text messages with the bathroom status:
The bathroom is vacant. or
The bathroom is occupied.. Same for voice calls — it speaks the bathroom status. Success!