Garage Door Timeout

Well, this is my first major project that's been put into practice. This project came about after leaving the garage door open a few times going to work, so the wife asked me for something to manage that. The first thought was to be able to check and control it remotely, which is something I'd like to implement eventually, but for now, this does the trick. I created a Garage Door class that is there just for the sake of object oriented design, it's not really necessary.

It's programmed with a 10 minute timeout. If after 10 minutes, the garage is still open it "presses the button" to try to close it. To account for errors in it not closing, it will try again after 20 seconds until it reads it as closed. If after 5 tries, it's still not closed, it enters fail mode and blinks a red led.


// Sketch: GarageDoorSketch.pde
// Adds a timeout to the garage door in case it is left open for an extended period

#include "GarageDoor.h" // Simple class for controlling a garage door

#define readPin 5 // Pulled high with 10k resistor.
#define failLED 6 // Connected to LED
#define relayPin 7 // Connected to a relay and LED
#define maxCloses 5 // Number of times we attemopt to close before entering fail mode

GarageDoor garage(readPin, relayPin, failLED); // Create the garage door with the provided pins

// Global Variables
unsigned long openTimeout = 600; // in seconds, time door has remained open before trying to close
unsigned long timeToClose = 25; // in seconds, estimated time it takes to try and close the door
unsigned long lastClosed = millis(); // Keeps track of the last time the garage was closed.
bool isClosing = false; // Keeps track of whether or not we are trying to close the garage
int closeAttempts = 0; // The number of times we've tried to close the garage
bool failMode = false; // Keeps track of if we are in fail mode
unsigned long startedClosing = 0; // Keeps track of the time when we tried to start closing the garage

void setup() {
  // Do Nothing

void loop() {
  unsigned long time = millis(); // Get the current time
  if (garage.isClosed()) { // Check if the garage is closed
    lastClosed = time; // It is, so set the time it was last read as closed to now
    isClosing = false; // It's closed, so we don't have to try anymore if we were
    closeAttempts = 0; // Reset the attempts for next time
    failMode = false; // Clear failMode if we were in it
  } else { // The garage is open
    if (failMode) { // Check if we are we in fail mode
      garage.blinkFailLED(); // We are, so blink our LED
    } else if (isClosing) { // Check if we're trying to close the garage
      if ( (time - startedClosing) > (timeToClose * 1000) ) { // Are we past our close timeout (Time it takes to close the garage)
        if (closeAttempts >= maxCloses) // We are, so check if we've hit out attempt threshold
          failMode = true; // We have, so enter failMode
          tryToClose(); // We haven't, so try to close the garage
    } else { // It's open, but we haven't tried to close it
      if ( (time - lastClosed) > (openTimeout * 1000) ) // Are we past out timeout for leaving it open
        tryToClose(); // We are, try to close it
  delay(200); // Small delay

void tryToClose() {
  garage.toggle(); // Push the button to close
  isClosing = true; // We are now trying to close it
  startedClosing = millis(); // Set the time we started to close as now.
  closeAttempts++; // Add one to our attempts


// File: GarageDoor.h
// Description: A class for managing a garage door. 

#ifndef GarageDoor_h
#define GarageDoor_h

#include "WProgram.h"

class GarageDoor {
    GarageDoor(int statusPin, int togglePin, int failPin); // Constructor
    bool isClosed(); // Check if garage is closed
    void toggle(); // Press the button to open/close
    void blinkFailLED(); // Blink the fail LED for one second
    int _statusPin; // Keeps track of status
    int _togglePin; // Simulates a button press to close garage
    int _failPin; // Flashes when close attempts have failed



// File: GarageDoor.cpp
// Implements the GarageDoor class

#include "WProgram.h"
#include "GarageDoor.h"

#define SECOND 1000 // One Second
#define CLOSED LOW // A low pin means a closed garage

GarageDoor::GarageDoor(int statusPin, int togglePin, int failPin)
  _statusPin = statusPin;
  pinMode(_statusPin, INPUT);
  _togglePin = togglePin;
  pinMode(_togglePin, OUTPUT);
  _failPin = failPin;
  pinMode(_failPin, OUTPUT);
bool GarageDoor::isClosed()
  int state = digitalRead(_statusPin);
  if (state == CLOSED)
    return true;
    return false;

void GarageDoor::toggle()
  // Pushes the button for 1 second
  digitalWrite(_togglePin, HIGH);
  digitalWrite(_togglePin, LOW);

void GarageDoor::blinkFailLED()
  // Blinks the LED for one second
  digitalWrite(_failPin, HIGH);
  digitalWrite(_failPin, LOW);



Some pictures of the setup...

Shorting these two pins simulates pressing the garage door button, so I hooked up some speaker wire to it and ran it to the jumpers on my secondary circuit.

Reed Switch pinned to the wall, two small magnets connected to the garage door.

Circuitry on the roof. Used a small perf board for the secondary circuitry and a Picoduino to run the ATMega.

Spliced a cheap USB cable and a wall-to-usb charger to provide regulated power.

I know it's a bit overdone, and I'm sure there are readily available commercial products for this, but where's the fun in that? Eventually, I'll add wireless communication to it, just working on a class that helps provide authorization to prevent any unscrupulous individuals from opening the garage :).

NIce job and well documented!

it obviously works - so well done you
I suspect, however, that the reed relay should be connected the other way round
coil to arduino
pins to control box!

You're right. The schematic was wrong, it's hooked up correctly and I fixed the schematic.

Very cool. You should add an override function for times you need to be in the garage, say soldering wire. Maybe a delay for 10 minutes (to start) then try to close. Something like that.

Very cool. You should add an override function for times you need to be in the garage, say soldering wire. Maybe a delay for 10 minutes (to start) then try to close. Something like that.

Yeah, that was something the wife suggested. The garage door has a lock/unlock switch that I can move the wire to to prevent it from closing it while it's locked, I'll probably just do that when I get the chance instead of adding more wiring and another switch. The only disadvantage is that it's essentially just disconnecting the button, so the Arduino doesn't know the difference and will inevitably enter fail mode.