victormarinus
Published © GPL3+

Monitor Your Garage Door

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

IntermediateShowcase (no instructions)12,669
Monitor Your Garage Door

Things used in this project

Story

Read more

Schematics

Fritzing scheme

Code

garagedeur_klok_lcd_v12.ino

Arduino
/*
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);  
}

Credits

victormarinus

victormarinus

2 projects • 1 follower

Comments