All posts by ajgiampa

TechClicker Clinic: A Raspberry Pi Based Garage Door Opener Using WebIOPi and an SR04 Ultrasonic Sensor

The Raspberry Pi is a great tool for many DIY Internet-of-Things projects.  It is inexpensive, relatively simple to use, and offers beginner and advanced hobbyists a platform to learn and experiment with IoT concepts.  Many of the most popular project implementations involving the Rasbperry Pi  attempt to make traditional devices “smart”.  In a previous TechClicker Clinic, we explained how to use a Raspberry Pi as the core of a networked digital picture frame.  Now, we’ll outline step-by-step a comprehensive and inexpensive Raspberry Pi based garage door opener.

Most traditional garage door openers require the operator to press a button to open the door, but don’t include a feedback sensor that can read and display the door’s actual physical state.  A Raspberry Pi based garage door opener has the ability to incorporate a sensor to detect whether the door is actually open or closed and then report that information to the user even when the user isn’t in visual proximity to the door.

A list of items used to create this Raspberry Pi based garage door opener is below with links to purchase them.  In some cases, substitutions are possible without conceptually changing the functionality of the system.

Raspberry Pi Model B+ or earlier

Raspberry Pi Case

Wifi USB adapter

Micro SD Card, Class 10

Two-Channel Relay Module

SR04 Ultrasonic Sensor

Electronics Prototyping Breadboard

Breadboard Wires Male to Female, Male to Female

Step 1:  Configure the Raspberry Pi for Initial Setup

Before we can begin creating the Raspberry Pi based garage door opener, the Raspberry Pi needs to be configured with an operating system and wireless network connection.  Please follow steps 1 through 5 from our Digital Photo Frame project instructions.

Step 2:  Install WebIOPi Framework

WebIOPi is an extremely useful framework developed for the Raspberry Pi that creates a web interface through which users can interact with the Raspberry Pi and its GPIO pins.  With it the Raspberry Pi garage door opener will be able to send signals to the relay responsible for opening and closing the garage door, as well as use an ultrasonic sensor to check and confirm the garage door’s physical state.  Installation of WebIOPi is simple, and the software is well documented, although no longer under development.  Since WebIOPi’s developer has abandoned it, it’s only proven to work with Raspberry Pi models prior to but not including the Rasbperry Pi 2.

Begin by downloading the most recent version (x.y.z) of WebIOPi to the configured Raspberry Pi.  From the SSH terminal window, extract the downloaded file by typing

tar xvzf WebIOPi-x.y.z.tar.gz

In the terminal window, change directories to the extracted WebIOPi directory.  Install WebIOPi by typing

sudo ./setup.sh

Wait for the software to finish installing.  WebIOPi isn’t setup to run automatically when the Raspberry Pi boots up.  To enable auto start of WebIOPi, type

sudo update-rc.d webiopi defaults

 Now, rebooting the Raspberry Pi should allow access to the GPIO pins via the WebIOPi interface.  This can be tested by entering the Raspberry Pi’s IP address at port 8000 (xxx.xxx.xxx.xxx:8000) into a web browser.  WebIOPi will serve a default password protected webpage (username = webiopi, password = raspberry) through which the user can interface with the GPIO pins.

Step 3:  Create the Physical Circuits Necessary for the Raspberry Pi Garage Door Opener

 Using a breadboard or other suitable method, layout the circuit shown in the diagram below.  If for some reason the actual layout of your circuit uses different GPIO pins than those shown in this schematic, note their numbers so that they can be changed in the script files that make the Raspberry Pi garage door opener “smart”.  Although the relay has two channels, this initial garage door opener implementation only requires using one channel.  If you wanted to add other functionality to the Raspberry Pi garage door opener in the future, the second channel can be setup and controlled in a similar manner to the first channel.

doc1

It is important to implement the voltage divider shown in the schematic.  The SR04 ultrasonic sensor operates at 5V, but sending a 5V signal to the  GPIO pin could overload and damage the Raspberry Pi.  The voltage divider reduces the voltage to nearer the 3.3V that the Raspberry Pi can handle.

Step 4:  Configure WebIOPi for GPIO pins and Scripts

To edit the WebIOPi configuration file, type

sudo nano /etc/webiopi/config

at the prompt in an SSH terminal window.

The first section of the configuration file lets the user define individual GPIO pins as having input or output functionality, and an initial high or low state.  Per the schematic for the Raspberry Pi garage door opener project, we’re using three GPIO pins, which can be configured in the [GPIO] section of the WebIOPi configuration file.  The numbers to the left of the equals sign represent the BCM GPIO pin numbering scheme.

[GPIO]
18 = OUT 1
24 = OUT 0
25 = IN

Pin 18, which triggers the relay, will “output” its signal for the relay to receive.  The “1” after OUT tells WebIOPi to keep initialize pin 18 at a high voltage state by default when the Raspberry Pi boots and the software is running.  We want this pin “high” because the two-channel relay is off in this state and turns on when the value of the GPIO pin drops to zero.  Pin 24 is used to trigger the SR04 ultrasonic sensor, but its initial state is required to be low, thus the “0” after OUT.  Finally, pin 25, which listens for the return (input) signal from the SR04 ultrasonic sensor, is define with IN.  Pins defined with as inputs do not have an initial high or low state.

The [~GPIO] portion of the configuration file can be ignored for this project since WebIOPi will always be running.  Note the “#” sign is used to “comment out” portions of the configuration file that aren’t to be used.

The [SCRIPTS] section of the configuration file is used to define the location of any Python scripts to which WebIOPi should have access.  The only Python script the Raspberry Pi garage door opener requires is used by the SR04 ultrasonic sensor to sense the presence of the door, thus determining if it is open or closed.

[SCRIPTS]
garage = /home/pi/Downloads/WebIOPi-0.7.1/htdocs/range.py

Note that all the file paths we’re using are the defaults created by the initial installation of WebIOPi.  If you change any of these paths, make sure these changes are carried through to the various configuration files and scripts.

The final section of the WebIOPi configuration file that needs attention is the [HTTP] heading.  Here, you can change the defaults web server port that you’ll use when accessing the Raspberry Pi garage door opener user interface via a web browser.  You can also change the path to the HTML files to be served.

[HTTP]
enabled = true
port = 8000
passwd-file = /etc/webiopi/passwd
doc-root = /home/pi/Downloads/WebIOPi-0.7.1/htdocs/

 

The other items in the [HTTP] section, and other section headings in the configuration file, can remain at their default values.

Step 5:  Create the HTML and Python Script Files

To create the HTML and script files for the Raspberry Pi garage door opener, open an SSH terminal session and go to the WebIOPi htdocs directory defined in step 4.

cd /home/pi/Downloads/WebIOPi-0.7.1/htdocs/

There are many default WebIOPi files in this folder.  You can remove any of them except the .css and .js files.

To create the Python script that will trigger the SR04 ultrasonic sensor, type

sudo nano range.py

to open the nano text editor.

Type or copy the following code text into the file.  The code text has comments explaining what each line does to trigger the sensor, listen for the echo, calculate the actual distance, and return the value for use by the Javascript in the HTML page interface.

#!/usr/bin/python
#import relavent libraries
import RPi.GPIO as GPIO
import time
import webiopi
import json
import sys
import time
import datetime
import os
import subprocess

#use bcm gpio numbering scheme
GPIO.setmode(GPIO.BCM)

#constants
SPEED_OF_SOUND = 34000 #cm/s 
SAMPLE_SPEED = 5 #seconds

# GPIO pin numbers used with U.S. Sensor
TRIG = 24
ECHO = 25

#for webiopi macro to send values to web interface
sys.path.append("/home/pi/Downloads/WebIOPi-0.7.1/htdocs")

#initialize gpio pins appropriately
GPIO.setup(TRIG, GPIO.OUT)
GPIO.setup(ECHO,GPIO.IN)

#function to read distance with U.S. Sensor
def readDistance():

max_time = 0.05 #used as timeout in case sensor misreads - CPU would spike otherwise as loops go out of control
 GPIO.output(TRIG, True) #fire sensor
 time.sleep(0.00001) #wait
 GPIO.output(TRIG, False) #turn off sensor and wait for pulse to return
 
 pulse_start = time.time()
 timeout = pulse_start + max_time #establishes timeout if pulse isn't heard by sensor

while GPIO.input(ECHO)==0 and pulse_start <= timeout: #conditions to determine the heard pulse start time
 pulse_start = time.time()
 
 pulse_end = time.time()
 timeout = pulse_end + max_time #establishes timout if pulse isn't heard by sensor

while GPIO.input(ECHO)==1 and pulse_end <= timeout: #conditions to determine heard pulse end time
 pulse_end = time.time() 
 
 pulse_duration = pulse_end - pulse_start #total pulse length determines distance via some maths
 roundtrip_duration = pulse_duration * SPEED_OF_SOUND
 one_way_distance = roundtrip_duration/2
 return one_way_distance #returns value sent to web interface via webiopi

@webiopi.macro #webiopi macro callout
def getData(): #name of webiopi macro function is getData
 status = readDistance() #status variable will carry distance value to web interface
 #Return the result from GET_DATA to index.html
 #print(status)
 return json.dumps (status) #dump the status value into the JSON data used by web interface

Exit the text editor and save the contents of the file.   Now, create an HTML file similarly by typing

sudo nano garage.html

Type or copy the following code text into the file.

<!DOCTYPE html>
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <meta name="viewport" content = "height = device-height, width = device-width, user-scalable = no" /> 
 <title>Garage Door Opener</title>
 <script type="text/javascript" src="/webiopi.js"></script>
 <script type="text/javascript">
 webiopi().ready(function() {
 var content, button;
 content = $("#content");

button = webiopi().createButton("Open/Close", "Open/Close", outputSequence);
 content.append(button); // append button to content div
 });

setInterval ("callMacro_getData()", 3000);{
 }
 
 function callMacro_getData(){
 webiopi().callMacro("getData",[], macro_getData_Callback);
 }
 
 function macro_getData_Callback(macro, args, data) {
 var status = JSON.parse(data);
 //Parse data from python macro getData
 if (status < 12) {
 myDiv0.innerHTML = "Door is Open";
 } else {
 myDiv0.innerHTML = "Door is Closed"; } 
 }

function outputSequence() {
 var sequence = "01" // sequence
 // output sequence on gpio 18 with a XXXXXms period
 webiopi().outputSequence(18, 500, sequence); 
 }

</script>
 <style type="text/css">
 button {
 display: block;
 margin: 15px 15px 15px 15px;
 width: 300px;
 height: 150px;
 font-size: 24pt;
 font-weight: bold;
 color: black;
 }

input[type="range"] {
 display: block;
 width: 160px;
 height: 45px;
 }

#gpio18.LOW {
 background-color: White;
 }

#gpio18.HIGH {
 background-color: Red;
 }
 </style>
</head>
<body>
 <div id="content" align="center"></div>
<table align="center" border="1" width="160px"></tr>
 <tr><td><center><div id="myDiv0"></center></div></td></tr>
</table>
</body>
</html>

It is very important that when the Raspberry Pi garage door opener is actually installed in a garage, the line of code in the HTML file that states

if (status < 12) {

will very likely need to be updated based on the physical proximity of the open or closed garage door.  This piece of code tells the program to report the garage door as open if the variable “status” is less than 12cm.  This means that if the SR04 ultrasonic sensor is measuring the distance between itself and the open garage door as 12cm or less, but your actual open garage door is more than 12cm from the ultrasonic sensor when open and the system is installed, the reported status of the door will be incorrect.

Also, the interface is setup to send a 1/2 second pulse to the relay when the Open/Close button is pushed, which is a common way to trigger garage door openers when the relay is connected to the switch terminals many commercially available garage door openers use.  The function below is what defines this pulse in the HTML file.

function outputSequence() {
 var sequence = "01" // sequence
 // output sequence on gpio 18 with a XXXXXms period
 webiopi().outputSequence(18, 500, sequence); 
 }

Depending on your actual garage door opener, this pulse length may need to be adjusted from 500ms to some other number or sequence.  The “01” sequence definition tells the relay to stay off (0), then on (1), each for 1/2″ second.  When the sequence is finished, the relay turns off again until the button is pressed again.

With the script and HTML files in place, we can reboot the Raspberry Pi and test the system’s functionality.  After rebooting, use a PC or mobile device on the same network as the Raspberry Pi to browse to the garage door opener.  The address typed into the browser will be similar to http://xxx.xxx.xxx.xxx:8000/garage.html, where the X’s represent the IP address (and port) of the Raspberry Pi.  If everything is working correctly, the user should be presented with a button and door status box as shown below.

clipboard01

Holding an object less than 12cm from the SR04 ultrasonic sensor should cause the door status to report the door as open.  Conversely, if the sensor measures an object greater than 12cm away, the door status will report closed.

Step 6:  Install the Raspberry Pi Garage Door Opener into a Garage

This final step requires the components of the Raspberry Pi garage door opener to be mounted in the operational environment.  Only an AC outlet is needed since the rest of the system is self contained or wireless.  Users can bookmark the interface for quick access and save or eliminate the WebIOPi password required to see the web interface.

Conclusion

It is important to note that as described in this TechClicker Clinic, this garage door opener will not work on devices that do not share the same network as the Raspberry Pi.  Although port forwarding could easily be employed to present the user interface on devices outside the LAN, this eliminates an inherent degree of security.  On a future iteration of this project, we’d like to employ a PIN entry system when the Open/Close button is pressed, as well as a possible security camera video feed.  Logging and time-stamping the garage door status to display on the user interface would also make this project even better.  We’ll keep updating this TechClicker Clinic with additional features as they’re added, so check back often.

As usual, we hope this Raspberry Pi garage door opener project is enjoyable and educational for you.