Project showcase
Monitor Your Garage Door

Monitor Your Garage Door © GPL3+

Automatic garage doors are a blessing. However.. Did you push the button when leaving Or worse... Did the kids close the door when leaving

  • 5,636 views
  • 1 comment
  • 13 respects

Components and supplies

About this project

This project monitors two garage doors. On the LCD screen you can see the last movements of your doors. When a door opens or closes the movements are logged. A door that is not completely opened or stays open for to long triggers an alarm.

Alarms are sent by SMS.

Using one (for security reasons) other mobile number, it is possible to send a command to open or close a door. Only acceptable commands are processed (close when door is open or open when door is closed).

SMS is used as a communication system as this is more secure as a plain internet connection. In order to check the door state proximity magnetic switches are used. Of course those can be replaced by microswitches.

(The protoshield on the left of the arduino replaces the breadboard)

Code

garagedeur_klok_lcd_v12.inoArduino
/*
Pin configuration
D0
D1
D2      GSM
D3      GSM
D4      
D5      
D6      
D7      
D8      close door1
D9      close door2
D10
D11     
D12     
D13
A0 D14  Upper door1
A1 D15  Lower door1
A2 D16  Upper door2
A3 D17  Lower door2
A4 D18  clock
A5 D19  clock

*/
//Library for LCD
#include <LiquidCrystal_I2C.h>
//Library for Clock
#include <Wire.h>
#include "RTClib.h"
//Library for GSM
#include <SoftwareSerial.h>
#include <SerialGSM.h>

DS1307 rtc;

SerialGSM cell(2,3);

// initialize the library with the i2c adress and chars and lines
LiquidCrystal_I2C lcd(0x3F,20,4);

const byte Doors = 2;//number of doors to manage
const byte Lines = 2;//number of lines on the lcd
const byte Chars = 16;//number of characters on the lcd
const long int ClosingTrigger = 60000;//time before an alarm is triggered
const long int ClosingTime = 20000;//time needed to close the door !!Measure this time for your door!!
static const uint8_t PinsIn[] = {14,15,16,17};//Array of pins used to minitor the doors
static const uint8_t PinsOut[] = {8,9};//Array of pins used to control the doors
char GSMNum[13]="+XXXXXXXXXXX";  // telephone number to send sms
String ValidAction;//used to check if incomming sms is valid
String PrevMessage01;//used to move the LCD message one line
String PrevMessage02;//used to move the LCD message one line
String PrevMessage03;//used to move the LCD message one line
byte PrevLine = 1; //previous used line on the LCD
byte UpperSensor[Doors];
byte PrevUpperSensor[Doors];
byte LowerSensor[Doors];
byte PrevLowerSensor[Doors];
char DoorState[Doors];//M=movement, O=open, C=Closed
byte x=0;//for loop trough number of doors. We start at 0 because list numbering starts at 0
byte DoorToActivate;//door that has to be activated extracted from SMS
long int StartMillis[Doors];//remember the starttime of the not closed timer
bool TimerStarted[Doors];//remember if the not closed timer has been started for a given door
bool SMSsend[Doors];//remember if a SMS has been send


void setup() {
//start LCD
lcd.init();
lcd.backlight();
// Print a message to the LCD.
lcdmessage("LCD Booted", 1);
// init clock
  Wire.begin();
  rtc.begin();

if (! rtc.isrunning()) {
lcdmessage("RTC is NOT running!", 1);
// following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(__DATE__, __TIME__));
  }

//loop trough the inputs. 2 inputs for each door
  for(byte y=0;y<2*Doors;y++)
  {
   pinMode(PinsIn[y],INPUT);
  }
//loop trough the outputs. 1 output for each door
//reset timers voor each door
 for(byte y=0;y<Doors;y++)
 {
   pinMode(PinsOut[y],OUTPUT);
//In order to work with a relay module HIGH is Normal Open   
   digitalWrite(PinsOut[y], HIGH);
   StartMillis[y]=0;
   TimerStarted[y]=0;
   SMSsend[y]=0;
 }
Serial.begin(9600);

//setup GSM shield  
cell.begin(9600);
//for debug  cell.Verbose(true);
lcdmessage("Booting GSM", 1);
cell.Boot(); 
cell.FwdSMS2Serial();
cell.DeleteAllSMS();
lcdmessage("GSM Booted", 1);
}

void loop() {
  if (x < Doors)
    { 
//check uppersensors and compare to previous state
      PrevUpperSensor[x] = UpperSensor[x];
      UpperSensor[x] = digitalRead(PinsIn[(2*x)]);
      if (!(PrevUpperSensor[x] == UpperSensor[x]))
        {
          MakeMessage(x, 'U');
        }
//check lowersensors and compare to previous state
      PrevLowerSensor[x] = LowerSensor[x];
      LowerSensor[x] = digitalRead(PinsIn[(2*x)+1]);
      if (!(PrevLowerSensor[x] == LowerSensor[x]))
        {
          MakeMessage(x, 'L');
        }
//Start timer if door not closed else reset timers
      if (!(DoorState[x] == 'C'))
        {
          CheckTimer(x);
        }
       else
        {
          TimerStarted[x] = 0;
          StartMillis[x]=0;
          SMSsend[x]=0;
        }
      x= x+1;
    }
  else
    {
      x=0;//reset doornumber in order to restart the checking cycle
    }
//process incomming SMS messages
  if (cell.ReceiveSMS())
    {
//check if number is valid
      String SMSSender=cell.Sender();
      SMSSender.remove(12);
      String ValidSender=GSMNum;        
        if (SMSSender == ValidSender)
          {
//retrieve DoorToActivate from SMSMessage
      String SMSMessage=cell.Message();
            lcdmessage(SMSMessage, 1);
            SMSMessage.remove(1);
            DoorToActivate=SMSMessage.toInt();
            
            switch (DoorState[DoorToActivate-1])
              {
                case 'C':
                  ValidAction="Open";
                break;
                
                case 'O':
                  ValidAction="Close";
                break;
              }
            
            SMSMessage=cell.Message();
            SMSMessage.substring(2);
            if (SMSMessage.substring(2) == ValidAction)
            {
              ActivateDoor(DoorToActivate);
            }
            else
            {
              lcdmessage("No Valid action", 10);
            }
//delete all SMS messages
            cell.DeleteAllSMS();
            SMSsend[DoorToActivate-1]=0;
          }
        else
          {
            lcdmessage("Wrong number", 10);
          }
   } 
}

//make message for logging if doorstate has changed.
void MakeMessage(byte door, char location)
{
  String message = "D";
  message.concat(door+1);
  switch (location)
  {
    case 'U':
      if (PrevUpperSensor[door] < UpperSensor[door])
        {
          message.concat(" = O ");
          DoorState[door]='O';
        }
      else
        {
          message.concat(" > C ");
          DoorState[door]='M';
        }
      break;
    
    case 'L':
      if (PrevLowerSensor[door] < LowerSensor[door])
        {
          message.concat(" = C ");
          DoorState[door]='C';
        }
      else
        {
          message.concat(" > O ");
          DoorState[door]='M';
        }
      break;
  }
  DateTime now = rtc.now();
  char buf[100];
  strncpy(buf,"hh:mm:ss\0",100);
  message.concat(now.format(buf));
  lcdmessage(message, 1);
}

//Check if timer has started for a door and if trigger has been reached, then send SMS
void CheckTimer(byte door)
{
   if (TimerStarted[door] == 0)
     {
         TimerStarted[door]=1;
         StartMillis[door]=millis();
     }
   else
     {
         if ((millis()-StartMillis[door] > ClosingTrigger) && (SMSsend[door] == 0))
           {
             Warning(door);
// Wait till door normally should be closed
             delay (ClosingTime);
           }
      }
}

//Creates a message and sends it by SMS
void Warning(byte door)
{
//create the message
  char txtMsg[100];
  String SMSMessage = "Door ";
  SMSMessage.concat(door+1);
  SMSMessage.concat(" is not closed.");
  SMSMessage.toCharArray(txtMsg,100);
//send the message
  sendSMS(GSMNum, txtMsg);
  SMSsend[door]=1;
}

//Sends a SMS message to a number
void sendSMS(char num[13], char msg[100])
{
  cell.DeleteAllSMS();
  cell.Rcpt(num);
  lcdmessage(msg, 1);
  cell.Message(msg);
  cell.SendSMS();
}

//Activate a door in order to close or open. Action is always the same.
//HIGH is normal mode LOW is activated state
void ActivateDoor(byte door)
{
    Serial.print("Digital out to low : ");
    Serial.println(PinsOut[door-1]);
    String Message = "Activate D";
    Message.concat(door);
    lcdmessage(Message, 1);
    digitalWrite(PinsOut[door-1], LOW);
    delay(2000);
    digitalWrite(PinsOut[door-1], HIGH);
}

//shows a message on the LCD screen
void lcdmessage(String message, byte visible)
{
 lcd.clear();
 lcd.setCursor(0,0);
 lcd.print(PrevMessage03);
 lcd.setCursor(0,1);
 lcd.print(PrevMessage02);
 lcd.setCursor(0,2);
 lcd.print(PrevMessage01);
 lcd.setCursor(0,3);
 lcd.print(message);
 PrevMessage03 = PrevMessage02;
 PrevMessage02 = PrevMessage01;
 PrevMessage01 = message;
 delay(visible*1000);  
}

Schematics

Fritzing scheme
hsBXDeAwOdgE2T8x78EK.fzz

Comments

Similar projects you might like

Windows 10 Universal Bluetooth Garage Door Opener

Project showcase by Ronald P. Kessler

  • 1,098 views
  • 1 comment
  • 6 respects

Automatic Sliding Door for the Garage

Project tutorial by DVDMDN

  • 13,383 views
  • 32 comments
  • 64 respects

IoT arduino ESP Garage Door opener (UD)

Project in progress by David Smerkous

  • 10,854 views
  • 6 comments
  • 16 respects

Arduino RFID Garage Door Opener

Project tutorial by Team RobotGeek Projects Team

  • 2,139 views
  • 1 comment
  • 6 respects

Garage Door Opener with Siemens TC35i Modem and Pro Mini

Project showcase by Grubits Gábor

  • 3,966 views
  • 2 comments
  • 9 respects
Add projectSign up / Login