Mario DArrisso
Published © GPL3+

Monitor Your Garage Door using a Wemos D1 mini

A garage door opener with monitoring state (open/close) using an ESP8266.

BeginnerFull instructions provided6 hours8,932
Monitor Your Garage Door using a Wemos D1 mini

Things used in this project

Hardware components

Wemos D1 Mini
Espressif Wemos D1 Mini
×1
2 Relays board
×1
2 terminal block connector
×2

Story

Read more

Custom parts and enclosures

Magnectic contact - Part1

Magnectic contact - Part2

Schematics

Schematics

Wemos D1 mini & Relay board

D1 (GPIO-5) : To relay IN1 (use for opening or closing garage-1)
D2 (GPIO-4) : To relay IN2 (use for opening or closing garage-1)
D5 (GPIO-14) : to terminal 1 (contact switch)
D6 (GPIO-12) : to terminal 2 (contact switch)

Code

Code

C/C++
Compiled using Visual Studio Code
#include <Arduino.h>                    // Needed for V.Studio code
#include "NodeMCU_Pinouts.h"
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <time.h>
#include <EEPROM.h>

const char* ssid     = "MyWifi";
const char* password = "MyPassword";

String host_name = "GarageIoT";         // Give it a name - hostname

ESP8266WebServer server(80);

//---------------------------------------------------------------------------- 
// DEFINE Variables
#define Garage1       D1
#define Garage2       D2
#define DoorContact1  D5
#define DoorContact2  D6
#define G_Open 0                        // contact reed is 0 = garage is open
#define G_Close 1                       // contact reed is 1 = garage is close

const long TimerInterval = 60000UL;     // timer ~ 10min
unsigned long TimerPrevious = 0;        // timer will store last time timer was updated

bool GarageDoor1Status = 1;
bool GarageDoor2Status = 1;

int EEaddress = 0;                      // EEprom address storing 0 or 1 (manual or automatic mode)
bool autoPilot = true;
unsigned long WatchDogTimerDoor1 = 0;
unsigned long WatchDogTimerDoor2 = 0;
bool WatchDogDoor1_state = 0;
bool WatchDogDoor2_state = 0;
String Displaymode = "";                // display 'automatic' or 'manual' in webpage - webpage_Execute()

String strGarageDoor1 = "";
String strGarageDoor2 = "";

String htmlpage = "";                   // Web page 


//---------------------------------------------------------------------------- 
// sub-routines

void webpage_append()
{
  htmlpage += "<!DOCTYPE HTML>";
  htmlpage += "<html>";
  htmlpage += "<head>";
  htmlpage += "<meta name = \"viewport\" content = \"width = device-width, initial-scale = 1.0, maximum-scale = 1.0, user-scalable=0\">";
  htmlpage += "<title>IoT</title>";
  htmlpage += "<style>";
  htmlpage += "\"body { background-color: #808080; font-family: Arial, Helvetica, Sans-Serif; Color: #000000; }\"";
  htmlpage += "</style>";
  htmlpage += "<script type=\"text/javascript\"> function reloadPage() {window.location.reload(true)} </script>";
  htmlpage += "</head>";
  htmlpage += "<body>";
  htmlpage += "<center>";
  htmlpage += "<h2>Garage</h2>";
  htmlpage += "<br>";
  htmlpage += "<FORM action=\"/\" method=\"post\">";
  htmlpage += "<P>";
  htmlpage += "<br>";
  htmlpage += "<INPUT type=\"submit\" name=\"GAR\" value=\"Garage-1\">";
  htmlpage += "<INPUT type=\"submit\" name=\"GAR\" value=\"Garage-2\">";
  htmlpage += "<br>";
  htmlpage += "<br>";
  htmlpage += "<INPUT type=\"submit\" name=\"GAR\" value=\"Auto-OR-Manual\">";
  htmlpage += "<br>";
  htmlpage += "<br>";
}

void returnOK()
{
  server.sendHeader("Connection", "close");
  server.sendHeader("Access-Control-Allow-Origin", "*");
  server.send(200, "text/plain", "OK\r\n");
}

void returnFail(String msg)
{
  server.sendHeader("Connection", "close");
  server.sendHeader("Access-Control-Allow-Origin", "*");
  server.send(500, "text/plain", msg + "\r\n");
}

void autoMode_oNoFF(bool val)
{
  if(val)
  {
    autoPilot = true;
    Displaymode = "Automatic";
  }
  else
  {
    autoPilot = false;
    Displaymode = "Manual";
  }
  
  EEaddress = 0;                          // EEprom address of autoPilotSetting
  EEPROM.write(EEaddress, autoPilot);     // Write to memory
  EEPROM.commit();                        // written to flash                   
}

void GarageDoorState()
{
  GarageDoor1Status = digitalRead(DoorContact1);
  GarageDoor2Status = digitalRead(DoorContact2);

  if (GarageDoor1Status)           
  {strGarageDoor1 = "Close";}
  else{strGarageDoor1 = "Open";}

  if (GarageDoor2Status)           
  {strGarageDoor2 = "Close";}
  else{strGarageDoor2 = "Open";}
}

void OpenGarage(int GarageNum) 
{
  if (GarageNum == 0)           // GarageNum = 0 opens or close Garage-1
  {
    digitalWrite(Garage1, 0);
    delay(1150);
    digitalWrite(Garage1, 1);
  }
  else if (GarageNum == 1)      // GarageNum = 1 opens or close Garage-2
  {
    digitalWrite(Garage2, 0);
    delay(1150);
    digitalWrite(Garage2, 1);
  }
}

void watchdog_CheckGarageDoor()     // Enabling timers on garage doors - Will close garage if open more than 10min...
{
  if(WatchDogDoor1_state == 0 && GarageDoor1Status == G_Open)     
  {
    WatchDogTimerDoor1 = millis();
    WatchDogDoor1_state = 1;
    // Serial.println("Enabling WatchDogDoor1_state to 1");  // -------------------------------------------------------------
  }
  else if(WatchDogDoor1_state == 1 && GarageDoor1Status == G_Close)
  {
    WatchDogDoor1_state = 0;
    // Serial.println("Garage1 is close - disabling timer watchdogDoor1_state");  // ----------------------------------------
  }
  else if(WatchDogDoor1_state == 1 && GarageDoor1Status == G_Open)
  {
    unsigned long Door1TimerNow = millis();
    if(Door1TimerNow - WatchDogTimerDoor1 >= TimerInterval)
    {
      OpenGarage(0);
      WatchDogDoor1_state = 0;
      // Serial.println("Garage1 open more than 10min... Closing garage");  // ----------------------------------------------
    }
  }     

  if(WatchDogDoor2_state == 0 && GarageDoor2Status == G_Open)     
  {
    WatchDogTimerDoor2 = millis();
    WatchDogDoor2_state = 1;
    // Serial.println("Enabling WatchDogDoor2_state to 1");  // -------------------------------------------------------------
  }
  else if(WatchDogDoor2_state == 1 && GarageDoor2Status == G_Close)
  {
    WatchDogDoor2_state = 0;
    // Serial.println("Garage2 is close - disabling timer watchdogDoor2_state");  // ----------------------------------------
  }
  else if(WatchDogDoor2_state == 1 && GarageDoor2Status == G_Open)
  {
    unsigned long Door2TimerNow = millis();
    if(Door2TimerNow - WatchDogTimerDoor2 >= TimerInterval)
    {
      OpenGarage(1);
      WatchDogDoor2_state = 0;
      // Serial.println("Garage2 open more than 10min... Closing garage");  // ----------------------------------------------
    }
  }     
}


void webpage_Execute()
{
  GarageDoorState();

  htmlpage = "";          // reset webpage to this form - else will have multiple pages...
  webpage_append();

  htmlpage += "</FORM>";
  htmlpage += "<br>";
  htmlpage += "<br>";
  htmlpage += "Garage-1 state : " + strGarageDoor1 + "";
  htmlpage += "<br>";
  htmlpage += "Garage-2 state : " + strGarageDoor2 + "";
  htmlpage += "<br>";
  htmlpage += "</P>";
  htmlpage += "<br>";
  htmlpage += "Garage mode : " + Displaymode + "";
  htmlpage += "<P></P>";
  htmlpage += "<br>";
  htmlpage += "<input type=\"button\" value=\"Refresh\" onclick=\"reloadPage()\" />";
  htmlpage += "</center>";
  htmlpage += "</body>";
  htmlpage += "</html>";
  server.send(200, "text/html", htmlpage);
}

void handleSubmit()
{
  String garNumber;
  if (!server.hasArg("GAR")) return returnFail("BAD ARGS");
  garNumber = server.arg("GAR");
  
  if (garNumber == "Garage-1") 
  {
    OpenGarage(0);
    webpage_Execute();
  }
  else if (garNumber == "Garage-2") 
  {
    OpenGarage(1);
    webpage_Execute();
  }
  else if (garNumber == "Auto-OR-Manual")       // Automatic mode
  {
 	  bool SetAutomode;
    
    if(autoPilot)
      {SetAutomode = false;}
    else{SetAutomode = true;}
    
    autoMode_oNoFF(SetAutomode);
    webpage_Execute();
  }

  else 
  {
    returnFail("Bad value");
  }
}

void handleRoot()
{
  if (server.hasArg("GAR"))
    {handleSubmit();}
  else {
    webpage_Execute();
  }
}

void handleNotFound()
{
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET)?"GET":"POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i=0; i<server.args(); i++){
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
}


//---------------------------------------------------------------------------- 
void setup() {
  Serial.begin(115200);
  EEPROM.begin(32);                     // EEPROM.begin(Size)
  delay(10);

  pinMode(Garage1, OUTPUT);             // Initialize Pin as an output
  pinMode(Garage2, OUTPUT);             // Initialize Pin as an output
  pinMode(DoorContact1, INPUT_PULLUP);  // Initialize Pin as an inpput
  pinMode(DoorContact2, INPUT_PULLUP);  // Initialize Pin as an inpput

  digitalWrite(Garage1, 1);             // Set Garage PIN to 1 = Do Nothing
  digitalWrite(Garage2, 1);             // Set Garage PIN to 1 = Do Nothing
  
  WiFi.hostname(host_name);             
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  WiFi.mode(WIFI_STA);
  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println("hostname : ");
  Serial.println(WiFi.hostname());

  EEaddress = 0;                          // Read EEProm memory and set for automatic or manual mode
  autoPilot = EEPROM.read(EEaddress);
  if(autoPilot)
    {Displaymode = "Automatic";}
  else
    {Displaymode = "Manual";}

  // Enable server mode
  server.on("/", handleRoot);
  server.onNotFound(handleNotFound);
	server.begin();                  //Start server
	Serial.println("HTTP server started");
}

void loop() 
{
  server.handleClient();                  // Listen for HTTP requests from clients
  
  static unsigned long loopTimer;       
  if(millis() - loopTimer >= 12000UL)      // Loop every 12 sec...
  {
    if(autoPilot)                         // Garage mode is on Automatic - Meaning will close
    {                                     // the garage door if open more than 10min...
      GarageDoorState();                  // Check garage door state
      watchdog_CheckGarageDoor();
    }
    else
    {
      WatchDogDoor1_state = 0;
      WatchDogDoor2_state = 0;
    }

    loopTimer = millis();                 // Reset the 12sec...
  }
}

Credits

Mario DArrisso

Mario DArrisso

2 projects • 4 followers
Daytime IT consultant and electronic DIY on weekends...

Comments