Internet Controlled Raspberry Pi Garage Door Opener

The purpose of this project is to build a device to control an electric garage door opener, and show the status of the door, via the web, and make it smart phone friendly.  Even though the project is functionally done, I decided to start this blog to document the work put into it, and to track future updates to it as well.

History
This project started about two years ago in early 2011 from the idea that I could make my own internet controlled garage door when I found out shortly after purchasing a new garage door opener, that the “NEW” model supports Internet control.  I was a little upset that after spending a lot of money on a new door opener, that the newest model has something that I would have really like to have in mine.  Then I thought to myself, “Why not make my own?”  Sure.  I could use a simple processor that has a web server to control a relay that controls the door!

Now, my only experience with embedded controllers was with a PIC16F84 microcontroller that was used in my college robotics project back in 2000.  After some research and tinkering with a PIC32 Ethernet starter kit, I was able to get it to control a 12VDC relay and read two inputs, one for the door up sensor and one for the door down.  Unfortunately, putting anything larger than a few ~1kb html files or image files on the device is all that the PIC’s limited memory will support.  Even with finally getting a 4GB USB drive to work with the PIC, there were still issues with images being garbled when they were over ~40kb in size.  From what I could tell, it had something to do with the PIC’s TCP/IP stack not being designed for files larger than a certain size, since the device had a very limited amount of flash memory.  I am not ruling out, the possibility that it “Could” be some of my code! 🙂

So, I basically gave up…  Till I heard about the Raspberry PI.  Unfortunately, the Pi was just being released into production when I heard about it, so I would have to wait to get my hands on one.

The Project
Fast forward to December of 2012… The Pi arrived.  It took a few weeks for me to get started since the holidays had arrived, but once I got started it didn’t take long to have some promising results.  I was able to breadboard the circuit and control it via the Pi add-in module called webiopi.  From there I was able to build an IO board, with a 5VDC relay and about 10 inputs.  The relay is driven by a 2N2222 NPN transistor to bring the 3.3VDC output of the Pi to 5VDC.  The inputs are just wired to screw terminals.  I was able to use the circuit from here.

IMG_20130405_184433-1024x773

The Interface
I was quite familiar with Apache and PHP, but I had been hearing of this fairly new project called node.js.  So, I decided to give it a try as the web server.  I was able to get a webserver running in a few minutes!  Plus, there was a lot of information already available for node.js and it’s modules.

Node.js at the time was slightly unconventional but my thoughts were that since this didn’t need a full blown webserver, that node might be a better choice due to it’s lightweight nature.

First, I wanted to make the app secure, so after searching around on the net for some tips, I was able to have the app ask for credentials, since I didn’t want just anyone opening and closing the garage door 🙂  Granted it is using only basic authentication.  So, even though I do not have my own SSL certificate, I decided to add SSL to encrypt the traffic between the server and the client.  I know that all of this can essentially still be hacked, but I felt somewhat better with those two features in place.

Then, I had to get node.js to talk to the GPIO ports.  This is all done with a module called EnotionZ/Gpio.  The code to setup a pin as output is below:

// Calling export with a pin number will export that header and return a gpio header instance 
var doorActuator = gpio.export(17, {    
  // When you export a pin, the default direction is out. This allows you to set
  // the pin value to either LOW or HIGH (3.3V) from your program.    
  direction: 'out',

  // Due to the asynchronous nature of exporting a header, you may not be able to    
  // read or write to the header right away. Place your logic in this ready    
  // function to guarantee everything will get fired properly    
  ready: function() {       
    doorActuator.set(0);   // sets pin to low (can also call gpio4.reset()       
    console.log(strGetTimeStamp() + ' Door actuator is off.');    
  } 
});

Then I setup two input pins, one for the up position and one for the down position:

// creates Door Up pin instance with direction "in" 
var doorUpIf = gpio.export(27, {    
  direction: "in",
  ready: function() {            
    // bind to the "change" event       
    // see nodejs's EventEmitter       
    doorUpIf.on("change", function(value) {         
      // value will report either 1 or 0 (number) when the value changes         
      lastStatusUpdate();         
      doorUp = value / 1;         
      currentStatusUpdate();         
      if (doorUp == 0) {           
        //sendEmail();         
      }       
    });       
    doorUpIf._get(function(value) {         
      doorUp = value;         
      currentStatusUpdate();       
    });     
  } 
});
// creates Door Down pin instance with direction "in" 
var doorDownIf = gpio.export(22, {    
  direction: "in",    
  ready: function() {                  
    // bind to the "change" event       
    // see nodejs's EventEmitter       
    doorDownIf.on("change", function(value) {         
      // value will report either 1 or 0 (number) when the value changes         
      lastStatusUpdate();         
      doorDown = value / 1;         
      currentStatusUpdate();         
      if (doorDown == 1) { // 0 = door down, 1 = door not down           
        sendEmail();         
      }       
    });             
    doorDownIf._get(function(value) {         
      doorDown = value;         
      currentStatusUpdate();       
    });    
  } 
});

During the creation of this project, I decided to try adding email functionality, and it wasn’t that difficult.  If you’ll notice there is a call to a function called sendEmail().  That is a function that uses the module, emailjs.  My function for emailing my cellphone upon door open is:

function sendEmail () {
  if (currentState == STATE_OPENING) {
     var server = email.server.connect({
       user: EMAIL_USER,
       password: EMAIL_PASSWORD,
       host: EMAIL_HOST,
       ssl: EMAIL_SSL
     });
     var message = {
       text: EMAIL_BODY_DOOR_OPENING,
       from: EMAIL_FROM,
       to: EMAIL_TO,
       subject: EMAIL_SUBJECT_DOOR_OPENING,
       attachment:
       [
         {data:EMAIL_BODY_DOOR_OPENING + '<br /' + EMAIL_HTML_DOOR_OPENING, alternative:true}
       ]
     };
     server.send(message, function(err, message) { console.log(strGetTimeStamp() + ' ' + (err || 'Email sent.')); });
   } 
}

The variables in all CAPS are defined earlier in the code.  The rest of the code just ties all of the pieces together.

Here is the project in action:

As far as the sensing of the inputs goes, I installed two proximity sensors using some left over angle braces from the installation of the door opener.  I had some two-conductor wire laying around and ran it from each sensor to the location of the Raspberry Pi, and connected them.

IMG_20130415_155632a2-1024x768 IMG_20130415_155646a-1024x768 IMG_20130415_155655-1024x768
(Click an image to view the full size)

Overall this project was a success.  there are however a few things that I would like to do better and there are some thing I would like to see added, like using the PiFace add-on board for the Pi instead of my homemade I/O Board.  This would make it easier for anyone else to build this project on their own.  Any other ideas are welcome.

Advertisements

11 thoughts on “Internet Controlled Raspberry Pi Garage Door Opener

  1. Hi,

    Can you share circuit schematics that you used for Pi and code you used for this? You can take out informations about your ip or passwords. I want to do something similar but have 0 knowledge about electronic interfacing.

  2. Nice project, that’s exactly what I want t do with my pi
    Any chance of you posting more infomation about your setup, webcam etc, making all your code avaible without your passwords pretty please.
    git hub maybe
    I have the relay part bult but I have litte coding knowlege and don’t know were to start on that end
    I’ve used webiopi to turn the gpio ports of and on, that’s as far as I’ve got

    I don’t think there is anyting wrong with using a home made 1/0 board, if anything your blog encourage others to get out there and do it themselves
    Your blog links to the infomation needed it bulid it, and is more complete that others I’ve come across most just have a picture of the diy I/O with no information

  3. Any chance you can help with this
    crypto.js:100
    c.context.setKey(options.key);
    ^
    Error: error:0906D06C:PEM routines:PEM_read_bio:no start line
    at Object.exports.createCredentials (crypto.js:100:17)
    at Server (tls.js:1044:28)
    at new Server (https.js:35:14)
    at Object.exports.createServer (https.js:54:10)
    at Object. (/home/pi/app/door-if.js:338:7)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)

    • I would check a few things:

      1. If you followed the steps here:
      http://dotnetnuts.wordpress.com/2011/06/20/secure-nodejs-app-with-self-signed-certificate-step-by-step-tutorial/
      then you should make sure that you have a certificate file named “cert.pem” and that it is located in the same directory as door-if.js.

      2. Check that the file actually has something in it. It should look similar to this:

      —–BEGIN PRIVATE KEY—–
      MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDYfQKSDvxdFKt7
      WGCX3ZCI30jkoTWlXq9Q9dh4V62b6yE7aRdhtUbvLqNpjfyjYSAklDp/rYV9Haof
      .
      . (24 lines of 64 random characters in each line,
      . the 25th line will be less than 64 characters)
      .
      664wHyslRCheQ610aklZNZ/El0TT2m8wDA6eSdQQgfUwTR8E8+722E+lJ8ataQt/
      pP6umD/6ciiNs8Yy3hzU/VxSyPA=
      —–END PRIVATE KEY—–
      —–BEGIN CERTIFICATE—–
      MIIDWzCCAkOgAwIBAgIJAOYvHw7PjGA0MA0GCSqGSIb3DQEBBQUAMEQxCzAJBgNV
      85+8puTgFq+vRL+MAT6KOQ0LVCnXXABH7n9DLA0Rx+NBYTjWsnbXQMT8hytOuZ1J
      .
      . (18 lines of 64 random characters. All lines should have
      . exactly 64 characters)
      .
      jFVlkvbso0B6BluLGGvZmjfXDNEUp9fYyP5qh/5PlXZA6cXTNgnWs37M1ADIInE=
      —–END CERTIFICATE—–

      3. If this is correct, then I would go back and recreate the certificate file in the link above.

      Hope this helps!

      • That helped that is what it was the command didn’t combine the two keys into one. Once I got them together it started working. Now I am just trying to use a magnetic door switch versus proximity sensors for the door open closed section. So next I will try to change the code to just look for 1 or 0 on one GPIO pin. Unless you have a better way.

      • A Proximity sensor, I believe is just a technical name for a magnetic door switch, so you should be ok with that, as long as the switch is NO (Normally open), i.e., it only completes the circuit when the magnet comes close to the switch. If it is the other way around, (Always closed, until the magnet comes close to the switch, then it opens), then you will have to reverse the 1 an 0. But otherwise it should just work. My circuit has a pull-up resistor on the input pin(s), that is hooked to the switch, then when the switch closes, or grounds the input pin, the Pi will read a 0. So, the Pi will always be at 1 until the switch closes, which then it will be a 0.

        Hope that helps!

    • I also connected to the wired push button connection on the garage door opener
      my Rpi is connected over WiFi

      I did have problems with stability months ago but that was nothing to do with eveready1010’s code or node. The Raspberry pi would drop wireless connection at random times and wifi would stay dead till the RPi was either rebooted or restarted wifi from terminal . The latest raspbian wheezy updates seemed to have fixed the problem. It’s been rock solid for months now.

  4. Hello I have a project but I need help I would like to use webiopi with piface but when I interact with the web webiopi LEDs or relay does not turn on ,on my piface

    • This article is about building your own relay circuit to control your garage door, but can be adapted to use the PiFace Digital board, and I have also worked with using the PiFace in place of my own relay board, but I currently have very little time to put together the documentation for it. For now all I can suggest is that you search Google. Here is one site that might help you:
      http://www.farnell.com/datasheets/1684425.pdf

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s