Arduino Grow Light Timer Six Switch/Relay Dual on/off Control V3.0 no oled/button version


 //*****************************************************************************************************************  
 //*****************************************************************************************************************  
   
   
 //************<<<< Arduino Nano, DS3231 Real Time Clock & Six Relay Module Lights Timer V3.0 >>>>******************  
   
   
 //*****************************************************************************************************************  
   
 //*****************************************************************************************************************  
 /*  
 Sketch uses 5722 bytes (18%) of program storage space. Maximum is 30720 bytes.  
 Global variables use 286 bytes (13%) of dynamic memory, leaving 1762 bytes for local variables. Maximum is 2048 bytes.  
   
  ************** UPDATED ON Oct 13 2018 *************  
   
 */  
   
   
 // no oled version  
 // six lights/relay control each with two on/off routines  
 // for oled version   
   
 //*****************************************************************************************************************  
   
   
 //*********************<<<< PLEASE VISIT / SUBSCRIBE MY YOUTUBE CHANNEL >>>>***************************************  
   
 // comment for more info  
   
   
 //*********************<<<<  Youtube.com/CrazyGuyOfficial  >>>>*****************************************  
   
   
   
 //*****************************************************************************************************************  
   
   
 //*****************************************************************************************************************  
 // INCLUDE LIBRARIES  
 //*****************************************************************************************************************  
   
   
   
   
   
   
 #include <Time.h>  // Time Manipulation   
 #include <Wire.h>  
 #include <DS1307RTC.h> // DS1307 RTC   
   
   
   
   
   
   
   
   
 //**********************//**********************//**********************  
 //  PINS AND CONNECTIONS  
 //**********************//**********************//**********************  
 const byte lightBlink  = 3 ;  
   
 const byte lightOne   = 5 ;  
 const byte lightTwo   = 6 ;  
 const byte lightThree  = 4 ;  
 const byte lightFour  = 7 ;  
 const byte lightFive   = 2 ;  
 const byte lightSix   = 8 ;  
   
   
   
 // DS3231 RTC "SDA to A4", "SCL to A5" "Vcc to 5V arduino pin Gnd to Gnd"  
 // Add more names/pins for more relays  
   
   
 //##################################################  
   
 // Light Timer ON/OFF Time Settings DEFAULT  
   
 //##################################################  
   
   
   
 byte OnOne1   = 14 ; // Hour when Light 1 will turn ON (24 hr format NO zeros before single digits)  
 byte OffOne1  = 8 ; // Hour when Light 1 will turn OFF (24 hr format NO zeros before single digits)  
 byte OnOne2   = 14 ;  // Hour when Light 1 will turn ON (24 hr format NO zeros before single digits)  
 byte OffOne2  = 8 ;  // Hour when Light 1 will turn OFF (24 hr format NO zeros before single digits)
   
   
 byte OnTwo1   = 20 ;  
 byte OffTwo1  = 8 ;  
 byte OnTwo2   = 20 ;  
 byte OffTwo2  = 8 ;  
   
 byte OnThree1  = 14 ;  
 byte OffThree1 = 8 ;  
 byte OnThree2  = 14 ;  
 byte OffThree2 = 8 ;  
   
 byte OnFour1  = 14 ;  
 byte OffFour1  = 8 ;  
 byte OnFour2  = 14 ;  
 byte OffFour2  = 8 ;  
   
 byte OnFive1  = 14 ;  
 byte OffFive1  = 8 ;  
 byte OnFive2  = 14 ;  
 byte OffFive2  = 8 ;  
   
 byte OnSix1   = 14 ;  
 byte OffSix1  = 8 ;  
 byte OnSix2   = 14 ;  
 byte OffSix2  = 8 ;  
   
   
   
 //*****************************************************************************************************************  
   
 bool RTCerr = 0;  
   
 bool LightOneSts   = 0 ;  
   
 bool LightTwoSts   = 0 ;  
   
 bool LightThreeSts  = 0 ;  
   
 bool LightFourSts  = 0 ;  
   
 bool LightFiveSts  = 0 ;  
   
 bool LightSixSts   = 0 ;  
   
   
 bool ppOne1     = 0 ;  
 bool ppOne2     = 0 ;  
   
 bool ppTwo1      = 0 ;  
 bool ppTwo2      = 0 ;  
   
 bool ppThree1      = 0 ;  
 bool ppThree2      = 0 ;  
   
 bool ppFour1      = 0 ;  
 bool ppFour2      = 0 ;  
   
 bool ppFive1      = 0 ;  
 bool ppFive2     = 0 ;  
   
 bool ppSix1      = 0 ;  
 bool ppSix2      = 0 ;  
   
 unsigned long SecsOne = 0;  
   
   
   
 //##################  
 //## RTC ADDRESS ##  
 //##################  
   
   
 #define DS1307_ID 0x68 // I2c Address of the RTC    
   
 byte zero = 0x00; //workaround for issue #527  
   
 //#################################  
   
   
   
   
   
 //*****************************************************************************************************************  
 // SETUP BEGINS  
 //*****************************************************************************************************************  
   
   
 void setup()  
 {  
  digitalWrite(lightOne,  HIGH);  
  digitalWrite(lightTwo,  HIGH); // turn the relay "OFF" and turning the pin "LOW" turns the relay "ON"  
  digitalWrite(lightThree, HIGH);  
  digitalWrite(lightFour, HIGH);  
  digitalWrite(lightFive, HIGH); // turn the relay "OFF" and turning the pin "LOW" turns the relay "ON"  
  digitalWrite(lightSix,  HIGH);  
   
   
  pinMode(lightBlink, OUTPUT);  
   
  pinMode(lightOne,  OUTPUT);  
  pinMode(lightTwo,  OUTPUT);  
  pinMode(lightThree, OUTPUT);  
  pinMode(lightFour, OUTPUT);  
  pinMode(lightFive, OUTPUT);  
  pinMode(lightSix,  OUTPUT);  
   
  //**********************//**********************//***********************//**********************  
  //Check to see if the RTC is present.if yes then Set the ARDUINO's INTERNAL clock accordingly  
  //**********************//**********************//***********************//**********************  
   
   
  Wire.beginTransmission(DS1307_ID);  
  Wire.write((uint8_t)0x00);  
   
  setSyncProvider(RTC.get);   //Yes it did, Sync the time from the RTC  
  setSyncInterval(20);  
   
   
   
  if (timeStatus() != timeSet)  
   RTCerr = 1;  
  else  
   RTCerr = 0;  
   
   
   
    
   
   
   
  Delay15S();  
   
 }  
   
 //*****************************************************************************************************************  
 //        SETUP END  
 //*****************************************************************************************************************  
   
   
   
 void Delay15S()  
 {  
  delay(1500);  
   
 }  
   
   
 //*****************************************************************************************************************  
   
   
 //     LOOP BEGINS  
   
   
 //*****************************************************************************************************************  
   
   
   
   
 void loop()  
 {  
    
   
   
   
  //#####################################  
  //####### LIGHTs ON/OFF ###############  
  //#####################################  
   
   
   
  //########## LIGHT ONE PP1##########################  
   
  if (OffOne1 > OnOne1)  
  {  
   
   
   if (hour() >= OnOne1 && hour () <= OffOne1 - 1)  
   {  
    TurnLightOneOn1();  
   }  
   
   else  
   {  
    TurnLightOneOff1();  
   
   }  
   
  }  
   
   
  //**********************************************************  
   
   
  if (OffOne1 < OnOne1 )  
  {  
   
   
   if (hour() >= OnOne1 || hour () <= OffOne1 - 1)  
   {  
    TurnLightOneOn1();  
   }  
   
   
   
   else  
   {  
    TurnLightOneOff1();  
   
   }  
  }  
   
   
  //########## LIGHT ONE PP2 ##########################  
   
  if (OffOne2 > OnOne2)  
  {  
   
   
   if (hour() >= OnOne2 && hour () <= OffOne2 - 1)  
   {  
    TurnLightOneOn2();  
   
   
   }  
   
   else  
   {  
    TurnLightOneOff2();  
   
   }  
   
  }  
   
   
  //**********************************************************  
   
   
  if (OffOne2 < OnOne2 )  
  {  
   
   
   if (hour() >= OnOne2 || hour () <= OffOne2 - 1)  
   {  
    TurnLightOneOn2();  
   
   
   }  
   
   
   
   else  
   {  
    TurnLightOneOff2();  
   
   
   }  
  }  
   
  //####################################################################  
   
  //########## LIGHT TWO pp1 ##########################  
   
  if (OffTwo1 > OnTwo1)  
  {  
   
   
   if (hour() >= OnTwo1 && hour () <= OffTwo1 - 1)  
   {  
    TurnLightTwoOn1();  
   
   }  
   
   else  
   {  
   
    TurnLightTwoOff1();  
   
   }  
   
  }  
   
   
  //**********************************************************  
   
   
  if (OffTwo1 < OnTwo1)  
  {  
   
   
   if (hour() >= OnTwo1 || hour () <= OffTwo1 - 1)  
   {  
    TurnLightTwoOn1();  
   
   
   }  
   
   
   
   else  
   {  
    TurnLightTwoOff1();  
   
   
   }  
  }  
  //########## LIGHT TWO pp2 ##########################  
   
  if (OffTwo2 > OnTwo2)  
  {  
   
   
   if (hour() >= OnTwo2 && hour () <= OffTwo2 - 1)  
   {  
    TurnLightTwoOn2();  
   }  
   
   else  
   {  
    TurnLightTwoOff2();  
   
   }  
   
  }  
   
   
  //**********************************************************  
   
   
  if (OffTwo2 < OnTwo2)  
  {  
   
   
   if (hour() >= OnTwo2 || hour () <= OffTwo2 - 1)  
   {  
    TurnLightTwoOn2();  
   
   }  
   
   
   
   else  
   {  
    TurnLightTwoOff2();  
   
   
   }  
  }  
   
   
   
  //####################################################################  
   
  //########## LIGHT THREE pp 1 ##########################  
   
  if (OffThree1 > OnThree1)  
  {  
   
   
   if (hour() >= OnThree1 && hour () <= OffThree1 - 1)  
   {  
    TurnLightThreeOn1();  
   }  
   
   else  
   {  
    TurnLightThreeOff1();  
   
   
   }  
   
  }  
   
   
  //**********************************************************  
   
   
  if (OffThree1 < OnThree1)  
  {  
   
   
   if (hour() >= OnThree1 || hour () <= OffThree1 - 1)  
   {  
    TurnLightThreeOn1();  
   
   }  
   
   
   
   else  
   {  
   
    TurnLightThreeOff1();  
   
   
   
   
   }  
  }  
  //########## LIGHT THREE pp 2 ##########################  
   
  if (OffThree2 > OnThree2)  
  {  
   
   
   if (hour() >= OnThree2 && hour () <= OffThree2 - 1)  
   {  
    TurnLightThreeOn2();  
   }  
   
   else  
   {  
    TurnLightThreeOff2();  
   
   }  
   
  }  
   
   
  //**********************************************************  
   
   
  if (OffThree2 < OnThree2)  
  {  
   
   
   if (hour() >= OnThree2 || hour () <= OffThree2 - 1)  
   {  
    TurnLightThreeOn2();  
   
   }  
   
   
   
   else  
   {  
   
    TurnLightThreeOff2();  
   
   }  
  }  
   
  //####################################################################  
   
  //########## LIGHT FOUR pp1 ##########################  
   
  if (OffFour1 > OnFour1)  
  {  
   
   
   if (hour() >= OnFour1 && hour () <= OffFour1 - 1)  
   {  
    TurnLightFourOn1();  
   }  
   
   else  
   {  
    TurnLightFourOff1();  
   
   
   }  
   
  }  
   
   
  //**********************************************************  
   
   
  if (OffFour1 < OnFour1)  
  {  
   
   
   if (hour() >= OnFour1 || hour () <= OffFour1 - 1)  
   {  
    TurnLightFourOn1();  
   
   }  
   
   
   
   else  
   {  
    TurnLightFourOff1();  
   
   
   }  
  }  
  //########## LIGHT FOUR pp2 ##########################  
  if (OffFour2 > OnFour2)  
  {  
   
   
   if (hour() >= OnFour2 && hour () <= OffFour2 - 1)  
   {  
    TurnLightFourOn2();  
   
   }  
   
   else  
   {  
    TurnLightFourOff2();  
   
   }  
   
  }  
   
   
  //**********************************************************  
   
   
  if (OffFour2 < OnFour2)  
  {  
   
   
   if (hour() >= OnFour2 || hour () <= OffFour2 - 1)  
   {  
    TurnLightFourOn2();  
   
   }  
   
   
   
   else  
   {  
    TurnLightFourOff2();  
   
   
   }  
  }  
   
  //####################################################################  
   
  //########## LIGHT FIVE pp1 ##########################  
   
  if (OffFive1 > OnFive1)  
  {  
   
   
   if (hour() >= OnFive1 && hour () <= OffFive1 - 1)  
   {  
    TurnLightFiveOn1();  
   }  
   
   else  
   {  
    TurnLightFiveOff1();  
   
   
   }  
   
  }  
   
   
  //**********************************************************  
   
   
  if (OffFive1 < OnFive1)  
  {  
   
   
   if (hour() >= OnFive1 || hour () <= OffFive1 - 1)  
   {  
    TurnLightFiveOn1();  
   
   }  
   
   
   
   else  
   {  
    TurnLightFiveOff1();  
   
   }  
  }  
   
  //########## LIGHT FIVE pp2 ##########################  
   
  if (OffFive2 > OnFive2)  
  {  
   
   
   if (hour() >= OnFive2 && hour () <= OffFive2 - 1)  
   {  
    TurnLightFiveOn2();  
   
   }  
   
   else  
   {  
    TurnLightFiveOff2();  
   
   
   
   }  
   
  }  
   
   
  //**********************************************************  
   
   
  if (OffFive2 < OnFive2)  
  {  
   
   
   if (hour() >= OnFive2 || hour () <= OffFive2 - 1)  
   {  
    TurnLightFiveOn2();  
   
   }  
   
   
   
   else  
   {  
    TurnLightFiveOff2();  
   
   
   }  
  }  
   
   
  //####################################################################  
  //########## LIGHT SIX pp1 ##########################  
   
  if (OffSix1 > OnSix1)  
  {  
   
   
   if (hour() >= OnSix1 && hour () <= OffSix1 - 1)  
   {  
    TurnLightSixOn1();  
   }  
   
   else  
   {  
    TurnLightSixOff1();  
   
   
   
   }  
   
  }  
   
   
  //**********************************************************  
   
   
  if (OffSix1 < OnSix1)  
  {  
   
   
   if (hour() >= OnSix1 || hour () <= OffSix1 - 1)  
   {  
    TurnLightSixOn1();  
   
   }  
   
   
   
   else  
   {  
    TurnLightSixOff1();  
   
   }  
  }  
   
  //########## LIGHT SIX pp2 ##########################  
   
  if (OffSix2 > OnSix2)  
  {  
   
   
   if (hour() >= OnSix2 && hour () <= OffSix2 - 1)  
   {  
    TurnLightSixOn2();  
   }  
   
   else  
   {  
   
   
    TurnLightSixOff2();  
   
   
   
   }  
   
  }  
   
   
  //**********************************************************  
   
   
  if (OffSix2 < OnSix2)  
  {  
   
   
   if (hour() >= OnSix2 || hour () <= OffSix2 - 1)  
   {  
    TurnLightSixOn2();  
   
   }  
   
   
   
   else  
   {  
    TurnLightSixOff2();  
   }  
  }  
   
  //####################################################################  
   
   
   
  //#####################################  
  // Blink Led And Call RTC TEST  
  //#####################################  
   
  if (millis() / 1000 - SecsOne > 10 ) //  
  {  
   digitalWrite (lightBlink, HIGH); // blink status LED  
   
   
   rtctest();  
   
   SecsOne = millis() / 1000; // then reset the timer  
   
   
   
  }  
   
   
 }  
   
   
   
   
   
 //**********************//**********************//**********************  
 //        LOOP END  
 //**********************//**********************//**********************  
 void TurnLightOneOn1()  
 {  
  if (!LightOneSts)  
  {  
   digitalWrite(lightOne, LOW);  
   
   LightOneSts = 1 ;  
   
   Delay15S();  
   
  }  ppOne1 = 1 ;  
   
 }  
   
   
   
 void TurnLightOneOff1()  
 {  
  if (!ppOne2)  
  {  
   digitalWrite(lightOne, HIGH);  
   LightOneSts = 0 ;  
  }  
  ppOne1 = 0 ;  
   
   
 }  
   
   
   
   
   
 void TurnLightOneOn2()  
 {  
   
  if (!LightOneSts)  
  {  
   digitalWrite(lightOne, LOW);  
   LightOneSts = 1 ;  
   
   Delay15S();  
   
  }  ppOne2 = 1 ;  
   
   
   
 }  
   
 void TurnLightOneOff2()  
 {  
  if (!ppOne1)  
  {  
   digitalWrite(lightOne, HIGH);  
   LightOneSts = 0 ;  
  }  
  ppOne2 = 0 ;  
 }  
   
   
   
   
   
   
 void TurnLightTwoOn1()  
 {  
  if (!LightTwoSts)  
  {  
   digitalWrite(lightTwo, LOW);  
   
   LightTwoSts = 1 ;  
   
   Delay15S();  
   
  }  ppTwo1 = 1 ;  
   
 }  
   
   
   
 void TurnLightTwoOff1()  
 {  
  if (!ppTwo2)  
  {  
   digitalWrite(lightTwo, HIGH);  
   LightTwoSts = 0 ;  
  }  
  ppTwo1 = 0 ;  
   
   
 }  
   
 void TurnLightTwoOn2()  
 {  
   
  if (!LightTwoSts)  
  {  
   digitalWrite(lightTwo, LOW);  
   LightTwoSts = 1 ;  
   
   Delay15S();  
   
  }  ppTwo2 = 1 ;  
   
 }  
   
   
 void TurnLightTwoOff2()  
 {  
   
  if (!ppTwo1)  
  {  
   digitalWrite(lightTwo, HIGH);  
   LightTwoSts = 0 ;  
  }  
  ppTwo2 = 0 ;  
 }  
   
   
 void TurnLightThreeOn1()  
 {  
   
  if (!LightThreeSts)  
  {  
   digitalWrite(lightThree, LOW);  
   LightThreeSts = 1 ;  
   
   Delay15S();  
   
  }  ppThree1 = 1 ;  
   
 }  
   
   
   
 void TurnLightThreeOff1()  
 {  
  if (!ppThree2)  
  {  
   digitalWrite(lightThree, HIGH);  
   LightThreeSts = 0 ;  
  }  
  ppThree1 = 0 ;  
 }  
   
   
 void TurnLightThreeOn2()  
 {  
   
  if (!LightThreeSts)  
  {  
   digitalWrite(lightThree, LOW);  
   LightThreeSts = 1 ;  
   Delay15S();  
   
  } ppThree2 = 1 ;  
 }  
   
   
 void TurnLightThreeOff2()  
 {  
  if (!ppThree1)  
  {  
   digitalWrite(lightThree, HIGH);  
   LightThreeSts = 0 ;  
  }  
  ppThree2 = 0 ;  
   
 }  
   
 void TurnLightFourOn1()  
 {  
  if (!LightFourSts)  
  {  
   digitalWrite(lightFour, LOW);  
   LightFourSts = 1 ;  
   
   Delay15S();  
   
  }  
  ppFour1 = 1;  
   
 }  
 void TurnLightFourOff1()  
 {  
  if (!ppFour2)  
  {  
   
   digitalWrite(lightFour, HIGH);  
   LightFourSts = 0 ;  
  }  
  ppFour1 = 0;  
   
 }  
 void TurnLightFourOn2()  
 {  
  if (!LightFourSts)  
  {  
   digitalWrite(lightFour, LOW);  
   LightFourSts = 1 ;  
   Delay15S();  
   
  }  ppFour2 = 1;  
   
 }  
   
 void TurnLightFourOff2()  
 {  
  if (!ppFour1)  
  {  
   
   digitalWrite(lightFour, HIGH);  
   LightFourSts = 0 ;  
  }  
  ppFour2 = 0;  
   
 }  
   
 void TurnLightFiveOn1()  
 {  
  if (!LightFiveSts)  
  {  
   digitalWrite(lightFive, LOW);  
   LightFiveSts = 1 ;  
   
   Delay15S();  
   
  }  ppFive1 = 1;  
   
   
   
 }  
   
 void TurnLightFiveOff1()  
 {  
   
   
  if (!ppFive2)  
  {  
   
   
   digitalWrite(lightFive, HIGH);  
   LightFiveSts = 0 ;  
  }  
  ppFive1 = 0;  
   
   
   
   
   
 }  
 void TurnLightFiveOn2()  
 {  
   
  if (!LightFiveSts)  
  {  
   digitalWrite(lightFive, LOW);  
   LightFiveSts = 1 ;  
   Delay15S();  
   
  }  ppFive2 = 1;  
   
 }  
 void TurnLightFiveOff2()  
 {  
  if (!ppFive1)  
  {  
   
   
   digitalWrite(lightFive, HIGH);  
   LightFiveSts = 0 ;  
  }  
  ppFive2 = 0;  
 }  
   
   
   
   
 void TurnLightSixOn1()  
 {  
  if (!LightSixSts)  
  {  
   digitalWrite(lightSix, LOW);  
   LightSixSts = 1 ;  
   
   Delay15S();  
   
  }  
  ppSix1 = 1;  
   
 }  
   
 void TurnLightSixOff1()  
 {  
   
  if (!ppSix2)  
   
  {  
   
   
   digitalWrite(lightSix, HIGH);  
   LightSixSts = 0 ;  
  }  
  ppSix1 = 0;  
   
   
 }  
   
 void TurnLightSixOn2()  
 {  
   
  if (!LightSixSts)  
  {  
   digitalWrite(lightSix, LOW);  
   LightSixSts = 1 ;  
   Delay15S();  
   
  }  ppSix2 = 1;  
   
 }  
 void TurnLightSixOff2()  
 {  
  if (!ppSix1)  
   
  {  
   
   
   digitalWrite(lightSix, HIGH);  
   LightSixSts = 0 ;  
  }  
  ppSix2 = 0;  
   
 }  
   
   
   
 //#####################  
 // RTC Test ##########  
 //#####################  
 void rtctest()  
 {  
    
  if (Wire.endTransmission() == 0) //Did the RTC respond?  
   
  {  
   
   
   
   RTCerr = 0;    // set RTC error status boolean to false  
   digitalWrite (lightBlink, LOW); // blink status LED  
   
  }  
   
  else  
  {  
   
   RTCerr = 1;  
   digitalWrite (lightBlink, HIGH);  
   
  }  
   
 }  
   
   
   

ESP 8266 MQTT Switch for Home Assistant V2.0

   
 /* ################################################################  
   ################################################################  
   ########## ESP 8266 MQTT Switch for Home Assistant V2.0 #######  
   ################################################################  
   ###################*** MOSQUITTO ***############################  
 */  
   
   // UPDATED: SEP 5 2018
   // CHANGE SwitchReset and SwitchResetConfirm to SwitchOta and SwitchOtaConfirm in the .yaml file
 //########################################################################################  
   
 // You Can find this sketch on Home Assistant forum i have just modified it according to my  
 // Requirements as it is just a waste of time trying to re-invent the wheel  
 // so thank you for it random citizen :D  
   
 //** INCLUDE LIBRARIES ** make sure you have all the Libraries installed  
 // Get them from within the Arduino IDE Sketch > Include Libraries > Manage Libraries  
   
 //########################################################################################  
 // Update libraries from library Manager and Boards from Boards Manager to latest  
   
   
 #include <PubSubClient.h>  
 #include <ESP8266WiFi.h>  
 #include <ArduinoOTA.h>  
 #include <ESP8266mDNS.h>  
 #include <WiFiUdp.h>  
   
   
   
 //##################################################################  
   
   
 void callback(char* topic, byte* payload, unsigned int length);  
   
   
   
 #define MQTT_SERVER "192.168.1.6"   // IP of your MQTT Server    
   
   
   
 const char* ssid = "Internet";  // SSID for you Wifi Hotspot  
 const char* password = "12345678qwerty";     // Password for Wifi Hotspot  
   
   
 //########### ESP 8266 GPIO Pins ###########################################  
   
   
 const int switchPin1 = 4;  
 const int switchPin2 = 5;  
 const int switchPin3 = 13;  
 const int switchPin4 = 12;  
   
 unsigned long secs = 0;  
   
 //#########################################################################  
   
   
 // ***** MQTT Topics Defined In Home Assistant's Configuration.yaml file ***  
   
   
 //#########################################################################  
   
 char const* switchTopic1 = "/house/switch1/";   //four switches for relays  
   
 char const* switchTopic2 = "/house/switch2/";  
   
 char const* switchTopic3 = "/house/switch3/";  
   
 char const* switchTopic4 = "/house/switch4/";  
   
   
   
 char const* switchSleep = "/house/switchSleep/"; // fifth for putting the Esp in sleep mode  
   
 char const* switchOta = "/house/switchOta/"; // sixth for updating the Esp  // port 8266 //check firewall 
   
 //##########################################################################  
   
   
   
 WiFiClient wifiClient;  
   
   
 PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient);  
   
   
   
   
   
   
 //#################################################################################  
 //#################################################################################  
   
 //############## SETUP BEGINS #####################################################  
   
 //#################################################################################  
 //#################################################################################  
   
   
   
 void setup()  
 {  
  digitalWrite(switchPin1, LOW);  
   
  digitalWrite(switchPin2, LOW);  
   
  digitalWrite(switchPin3, LOW);  
   
  digitalWrite(switchPin4, LOW);  
   
  // These lines will keep the Relays off during start-up  
   
  // Because i'm Using NPN transistors for  
   
  // switching the relays which are actually  
   
  // LOW-level-trigger type  
   
  // adding the transistor will invert that logic  
   
  // and LOW will be OFF because Transistor is off  
   
   
   
   
  pinMode(switchPin1, OUTPUT);  // Relay Switch 1  
   
  pinMode(switchPin2, OUTPUT);  // Relay Switch 2  
   
  pinMode(switchPin3, OUTPUT);  // Relay Switch 3  
   
  pinMode(switchPin4, OUTPUT);  // Relay Switch 4  
   
   
   
  //####################################################################################  
   
   
   
   
  Serial.begin(115200);  
  delay(100);  
   
   
   
   
   
   
  WiFi.mode(WIFI_STA);    // Set Esp8266 in Station mode  
   
  WiFi.begin(ssid, password);  
   
   
  secs = millis() / 1000 ;  
   
  while (WiFi.waitForConnectResult() != WL_CONNECTED)  
  {  
   
   Serial.println("Waiting for WiFi Connection ...");  
   
   delay(2000);  
   
   /*if (millis() / 1000 - secs > 60)  
   {  
    Serial.println("Going to Sleep for 10 secs ...");  
   
    ESP.deepSleep(10 * 1000000);  
   }  */
  }  
   
   
   
   
  //############################################################################################  
  //############################################################################################  
   
  //############# CHANGE OTA UPDATE PASSWORD ###################################################  
  //############################################################################################  
  //############################################################################################  
   
  ArduinoOTA.setPassword((const char *)"123"); // Password for OTA Update "123"  
  ArduinoOTA.begin();  
   
   
   
   
 }  
   
 //##########################################################################################  
   
 //############ SETUP END ###################################################################  
   
 //##########################################################################################  
   
   
 bool ota_update = false ; // Don't change this manually  
   
   
   
   
   
 //#########################################################################################  
   
 //######### LOOP BEGINS ##################################################################  
   
 //#########################################################################################  
   
   
 void loop()  
 {  
   
  if (!client.connected() && WiFi.status() == 3)  
   
  {  
   
   reconnect(); // Reconnect if connection is lost  
   
  }  
   
   
  client.loop(); // Maintain MQTT connection  
  if (ota_update)    
  {     secs = millis() / 1000 ;  }
   
  delay(10);   // MUST delay to allow ESP8266 WIFI functions to run  
  OTA();  
   
 }  
   
   
 //#########################################################################################  
 //################# WAIT FOR OTA UPDATE ON EVERY START UP #################  
 //#########################################################################################  
 void OTA()  
 {  
  if (ota_update)    
  {  
   Serial.println("Waiting for Ota update");  
   
   while (millis() / 1000 - secs < 20 )  
   {  
    ArduinoOTA.handle() ;  
    delay(10);  
   }  
  }  
 }  
 //#################################################3  
   
   
   
 //#########################################################  
   
   
   
 void callback(char* topic, byte* payload, unsigned int length) {  
   
   
  String topicStr = topic;  
   
   
   
  Serial.println("Callback update.");  
  Serial.print("Topic: ");  
  Serial.println(topicStr);  
   
   
  //################## Switch 1 ################### COPY THESE BLOCKS FOR MORE SWITCHES ####################  
   
  if (topicStr == "/house/switch1/")  
  {  
   
   if (payload[0] == '1')  
   {  
   
    digitalWrite(switchPin1, HIGH);  
   
    client.publish("/house/switchConfirm1/", "1");  
    delay(1000);  
   }  
   
   
   
   else if (payload[0] == '0')  
   {  
   
    digitalWrite(switchPin1, LOW);  
   
    client.publish("/house/switchConfirm1/", "0");  
   
   }  
   
  }  
   
   
   
   
  //################## Switch 2 #####################################################  
   
   
   
   
   
   
  else if (topicStr == "/house/switch2/")  
  {  
   
   
   
   if (payload[0] == '1')  
   {  
   
    digitalWrite(switchPin2, HIGH);  
   
    client.publish("/house/switchConfirm2/", "1");  
    delay(1000);  
   
   }  
   
   
   
   else if (payload[0] == '0')  
   {  
   
    digitalWrite(switchPin2, LOW);  
   
    client.publish("/house/switchConfirm2/", "0");  
   
   }  
   
  }  
   
   
   
  //################## Switch 3 #####################################################  
   
   
   
   
   
   
  else if (topicStr == "/house/switch3/")  
  {  
   
   
   
   if (payload[0] == '1')  
   {  
   
    digitalWrite(switchPin3, HIGH);  
   
    client.publish("/house/switchConfirm3/", "1");  
   
    delay(1000);  
   
   }  
   
   
   
   else if (payload[0] == '0')  
   {  
   
    digitalWrite(switchPin3, LOW);  
   
    client.publish("/house/switchConfirm3/", "0");  
   
   }  
  }  
   
   
   
   
   
  //################## Switch 4 #####################################################  
   
   
   
   
  else if (topicStr == "/house/switch4/")  
  {  
   
   
   if (payload[0] == '1')  
   {  
    digitalWrite(switchPin4, HIGH);  
   
    client.publish("/house/switchConfirm4/", "1");  
   
    delay(1000);  
   
   }  
   
   
   
   else if (payload[0] == '0')  
   {  
    digitalWrite(switchPin4, LOW);  
   
    client.publish("/house/switchConfirm4/", "0");  
   }  
  }  
   
   
  //################## Switch 5 Sleep Mode #######################################  
   
   
  else if (topicStr == "/house/switchSleep/")  
  {  
   
   
   if (payload[0] == '1')  
   {  
   
    client.publish("/house/switchSleepConfirm/", "1");  
   
    Serial.println("going to sleep for 60 secs");  
   
    delay(1000);  
   
    ESP.deepSleep(60 * 1000000);  
   
   
   }  
   
   
   
   else if (payload[0] == '0')  
   {  
    client.publish("/house/switchSleepConfirm/", "0");  
   }  
  }  
   
   
   
   
  //################## Switch 6 ota #######################################  
   
   
  else if (topicStr == "/house/switchOta/")  
  {  
   
   
   if (payload[0] == '1')  
   {  
    client.publish("/house/switchOtaConfirm/", "1");  
   
    ota_update = true ;  
   
   }  
   
   else if (payload[0] == '0')  
   {  
    client.publish("/house/switchOtaConfirm/", "0");  
    ota_update = false ;  
   
   }  
  }  
   
   
   
   
   
   
   
   
   
   
   
 }  
   
   
 //#########################################################################################  
   
 //######### LOOP ENDS ##################################################################  
   
 //#########################################################################################  
   
   
   
   
   
   
 void reconnect() {  
   
   
   
  if (WiFi.status() != WL_CONNECTED)  
  {  
   
   Serial.print("Connecting to ..");  
   
   Serial.println(ssid);  
   
   
   
   while (WiFi.status() != WL_CONNECTED)  
   {  
   
    delay(500);  
   
    Serial.print(".");  
   
   }  
   
   
   
   Serial.println("");  
   
   Serial.println("WiFi connected");  
   
   Serial.println("IP address: ");  
   
   Serial.println(WiFi.localIP());  
  }  
   
   
   
   
   
  if (WiFi.status() == WL_CONNECTED) {  
   
   while (!client.connected()) {  
   
    Serial.print("Attempting MQTT connection...");  
   
   
   
    // Generate client name based on MAC address and last 8 bits of microsecond counter  
    String clientName;  
    clientName += "esp8266-";  
    uint8_t mac[6];  
    WiFi.macAddress(mac);  
    clientName += macToStr(mac);  
   
   
    //#########################################################################################  
   
    //######### CHANGE MQTT USER NAME AND PASSWORD BELOW ####################################  
   
    //#########################################################################################  
   
   
   
   
    if (client.connect((char*) clientName.c_str(), "newuser", "12345")) {  
   
     Serial.print("\tMQTT Connected");  
   
   
   
     client.subscribe(switchSleep);  
   
   
     client.subscribe(switchOta);    // the order in which topics are arranged here  
   
   
     // is how ESP will Subscribe and if you put  
   
     // relays first and also turn them on and ota or sleep too  
   
     // the switches will turn on momentarily untill it gets the message to sleep or ota update  
   
     client.subscribe(switchTopic1);  
   
     client.subscribe(switchTopic2);  
   
     client.subscribe(switchTopic3);  
   
     client.subscribe(switchTopic4);  
   
     // ##**************************######## Add MORE TOPICS FOR SWITCHES HERE  #####################  
   
   
    }  
   
   
    else  
    {  
     Serial.println("\tFailed.");  
   
     delay(2000);  
   
     break;  
   
    }  
   
   }  
   
  }  
   
 }  
   
   
   
   
   
 String macToStr(const uint8_t* mac)  
 {  
   
  String result;  
   
  for (int i = 0; i < 6; ++i) {  
   result += String(mac[i], 16);  
   
   if (i < 5) {  
    result += ':';  
   }  
  }  
   
  return result;  
 }  

Raspberry Pi Home Assistant Hassbian Camera Motion Mqtt

Usb Camera as a Motion sensor on Raspberry pi 3 Hassbian using Mosquitto MQTT broker/client 

Using "motion"(software) the images and Videos from the Usb webcam are recorded and streamed on the (same)Rpi3 which is also running Hassbian. 


I have edited the motion.conf file to run commands when motion is detected and when the motion event ends so that it publishes Mqtt messages to a Topic using Mosquitto MQTT broker and in the Homeassistant configuration.yaml file i have made an mqtt sensor that shows motion detected TRUE or FALSE .


It works and using Automations  it can be used to send mqtt messages to some other mqtt switches connected to the Hassbian to turn lights on or off or do something else.


#######################################

# In motion.conf file edit the following lines (in addition to the settings that are necessary for 
# your camera to work 
#######################################

# Command to be executed when an event starts. (default:none)


on_event_start mosquitto_pub -u newuser -P 12345 -t /house/system/motion -m "TRUE"


# Command to be executed when an event ends after a period of no motion


on_event_end mosquitto_pub -u newuser -P 12345 -t /house/system/motion -m "FALSE"


# Command to be executed when a motion frame is detected 


on_motion_detected mosquitto_pub -u newuser -P 12345 -t /house/system/motion -m "TRUE"


# the commands should also contain an ip number and a port number for connecting with 

# mosquitto broker if it is running on a different device within a network

###########


#########################

In Configuration.YAML file
#########################


camera:



####


  - platform: mjpeg    ## camera is on same device i.e. localhost

    mjpeg_url: http://localhost:8081
    name: Usb Cam

####

  - platform: mjpeg        ## camera is a different device
    mjpeg_url: http://192.168.1.7:8081
    name: RCam1
    username: user
    password: qwerty12345
    authentication: basic

######################

# MOSQUITTO MQTT 
######################


mqtt:

  broker: localhost
  port: 1883
  client_id: home-assistant-1
  keepalive: 60
  username: newuser
  password: 12345
  protocol: 3.1 

###############

# SENSORS 
###############
sensor 1:
  - platform: mqtt
    name: "Motion Detect"
    state_topic: "/house/system/motion"
  #  payload_on: "TRUE"
  # payload_off: "FALSE"
    qos: 0
    expire_after: 60
####################
sensor 6:
  - platform: mqtt
    name: "RCam1 Motion"
    state_topic: "/house/rcam1/motion"
 #   payload_on: "TRUE"
 #   payload_off: "FALSE"
    qos: 0
    expire_after: 60
####################

############################################


##################

In groups.YAML file
##################
default_view:
  view: true
  icon: mdi:home
  entities:
  #- group.time
  #- group.sun
  #- group.weathertoday
  - group.usbcam
  #- group.systeminfo
  name: default_view

###

usbcam:
  name: Usb Cam
  view: false
  entities:
  - camera.usb_cam
  - sensor.motion_detect

####

testview:
  name: TestView
  view: true
  entities:
  - group.rcam1

##########

rcam1:
  name: RCam1
  view: false
  entities: 
  - sensor.rcam1_motion
  - camera.rcam1




################ HOW TO ##################



First, make the camera work and configure motion by editing motion.conf file.Keep the resolution and frame rate at a minimum, for example : height x width 640 x 480 and 10 fps.

You need to make motion and your camera work with each other first so you can view the camera feed using the ip address of your Pi and a port at which motion is streaming the video from your camera.


Then add camera component and all the related settings in configuration.yaml file to show the camera on the homeassistant page. 

In the example above I have shown two ways to do it. 


First is for a USB cam attached directly to the Pi which is Running Homeassistant.


Second is for a different Pi with Raspbian Jessie,a CSI camera, and running motion and mosquitto and sends video and mqtt messages to the first Pi which is running Homeassistant/Hassbian.


Then use sensor component and make a "Sensor" by adding text in the Configuration.yaml file make sure the text has proper "spaces" because it will not work if the text is not formatted according to the YAML syntax. In the example above I have made Two sensors for motion detection from two camera feeds.


First is from the Usb cam and motion running on the same Pi where Hassbian is running.Second is for a different Pi with a CSI camera in the same Wifi network.They should have different mqtt "Topics"and the Payloads can be either "1" and "0" or "true" and "false".


Then make a "card" to show on the HomeAssistant page that can show camera feed and  motion detect = True / False  by adding text to the groups.yaml file. there are two ways to do it. 


First, is by adding it as a new tab by making two groups. First group with "view" set to "true", like in the example above the "Test View" in groups.yaml file . Then make a second group and set its view to "false"and add camera and sensor entity names to the second group (with view false),like in the example above the RCam1 group.Then add the second group's name to the first group (with view set  to true). Like I did above in the TestView entities section.If you do it like I did a new "TAB" will appear in the HomeAssistant webpage with the name Test View and it will show both the rcam1 video feed  and it's motion detection sensor using mqtt.


Second is by making a group with view set to false and add usb camera and motion sensor entity names to it then adding that group name to the default view entities section will show the video feed from usb cam and its motion sensor on the main home tab on the homeassistant page. 


Then test the Commands for Publishing a Message to the mqtt topics from command line and at the same time watch the changes on the motion detect cards on the homeassistant page. 

If the command is correct with correct topic,username,password and payload (TRUE/FALSE) and if on a different device with correct ip and port in the command too. (ip and port where the mosquitto broker is running) then you should be able to manually publish to the sensor topic and the motion detect status will change to TRUE or FALSE and in case no new message after expiry time is up it will change to UNKNOWN.  


Then add those tested/working commands for mosquitto_pub to the motion.conf file to automate the process of publishing messages to the mqtt topic as a result of motion events.


Please Keep it in mind that if this is being done on the same Raspberry Pi running Home Assistant,Motion and Mosquitto the Mosquitto commands that are executed on motion detection do not contain an ip and a port number for the mosquitto broker but will be necessary for communicating with the broker running on a different device/pi in a network.


Which means if you have two raspberry Pis FIRST with HomeAssistant and Mosquitto Broker and the SECOND with usb/csi Camera , Motion and Mosquitto Client then the SECOND Rpi with camera and motion has to know the Ip and port for the FIRST Rpi so it can communicate with it and send a message upon motion detection. 


If you are planing to use a second Pi as a camera then MotionEyeOS will not work as mqtt or Mosquitto cannot be installed on it at least not easily you will have to build it from source and add all the necessary packages to the image .Use Raspbian with MotionEye and Mosquitto I have used it and it works.



If anything is still not clear then Comment on my Youtube Channel and Please SUBSCRIBE to the CHANNEL. 

DIY Use Soil Moisture Sensor,Oled,Arduino,Breadboard,Battery Part 01


 #include <U8glib.h> // Version 1.19.1   
   
   
   
 # define font  u8g.setFont(u8g_font_helvB08) // set font One for oled display  
   
 byte Scroll   = 4 ; // Scroll Text x axis  
   
 int soilHumVal   = 0 ;  // for reading analog value from Soil Humidity Sensor's Analog output  
   
 const byte soilHumA  = A1 ; // pin for Soil Humidity Sensor's ANALOG Output Signal Pin it gives raw voltage values  
   
 U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_NO_ACK|U8G_I2C_OPT_FAST); // Fast I2C / TWI   
   
 unsigned long secs = 0;  
   
   
   
   
 void setup()  
 {  
  Serial.begin(9600);  
    
  pinMode(soilHumA, INPUT)  ;  
   
  analogReference(DEFAULT);  
    
  Start();  
  delay(2000);  
   
    
  soilHumCalc() ;  
   
 }  
   
   
 void Start()  
   
 {  
   
   
  u8g.firstPage();   // START SCREEN "Picture loop" for OLED  
   
  do  
  {  
   
   font;  
   u8g.drawFrame(10, 12, 108, 31); // Draw Frame and it's Size  
   u8g.drawFrame(0, 0, 128, 64); // Draw Frame and it's Size  
   u8g.drawStr(15, 25, "Soil Humidity"); // Draw a string   
   u8g.drawStr(85, 32, "V 1.0");     
   u8g.drawStr( 37, 40, "Meter");  
   u8g.drawStr(53, 60, "Made by:AMK");  
   
   
  }  
  while ( u8g.nextPage() );  
   
 }  
   
   
   
   
   
   
   
 //####################################  
 // Function for Reading Soil Humidity#  
 //####################################  
 void  soilHumCalc()  
 {  
   
  soilHumVal = analogRead(soilHumA);  
   
  Serial.print("Raw 10-bit Number Value : ");  
  Serial.println(soilHumVal );  
  soilHumVal = map(soilHumVal, 1023, 0, 0, 100);  
  Serial.print("Percentage Value : " );  
  Serial.println(soilHumVal );  
   
  if(soilHumVal<3) soilHumVal=0;  
 }  
   
   
   
   
 //############  
 // Loop #####  
 //############  
   
   
   
 void loop()  
 {  
  delay(200);  
  soilHumCalc() ;  
  delay(200);  
   
   
    
    
  u8g.firstPage();  
   
  do  
  {   
   u8g.setColorIndex(1);  
   
   u8g.drawFrame(0, 0, 128, 20); // Draw frame  
   u8g.drawFrame(0, 22, 128, 42); // Draw fram  
   if(millis()- secs > 100)//Check Timer  
   {  
   Scroll = Scroll -1; // Minus 1  
   Scroll--;// Minus 1  
   secs=millis(); //Reset Timer  
   }  
   
     
     
   
     
   font;  
   u8g.setPrintPos(Scroll, 14);  
   u8g.print( "YouTube.com/CrazyGuy/Official");  
   u8g.setPrintPos(4, 34);  
   u8g.print( "Moisture");  
    
   if(soilHumVal>18)   
   {  
    u8g.setPrintPos(113, 34);  
    if(soilHumVal < 30)   
    {   
     u8g.print("M");  
    }   
    else   
    {   
     u8g.print("H");}  
    }  
     
   u8g.setFont(u8g_font_osr18); // set font for oled display  
   u8g.setPrintPos(102, 59);  
   u8g.print("%");  
    
   if(soilHumVal>30)   
   {  
    u8g.drawBox(52,36,49,25);  
    u8g.setColorIndex(0);  
   }  
      
   u8g.setPrintPos(51, 59);  
   u8g.print(soilHumVal);  
    
  }  
   
  while ( u8g.nextPage() );  
   
 }  
   

Arduino Grow Box Green House Controller 5.0 [OUT-DATED] Cooler,Heater,Lights,Humidifier,Fan,Water Level,Soil Humidity,Pump


  /*   
   
    
   
    
   
  ************** UPDATED ON DEC 2017 *************  
   
 *************** GETTING BETTER THAN BEFORE *************  
   
    #############################################
   FOR UPDATED 6.5 VERSION WATCH/READ DESCRIPTION:
    ##############################################
   https://youtu.be/yrm0VjUKILo

    
   
  *** MAKING A MODULAR SYSTEM FOR D.I.Y. GROWBOX / GREENHOUSE   
   
   
   
     
  ***Independent Grow Box Controller that can be used to Control all the Important devices to maintain   
  *  
  *  
  the ""Grow Environment"" for example Lights, Heater,Cooler,Fan for blowing air inside the box ,Fan for exhaust,   
  Humidifier or mist maker,Water pump ,Solenoids etc   
     
    
      
  *****i WILL improve it as i learn more :)   
    
  //**********************//**********************//**********************   
     
     
     
  //**********************//**********************//**********************//**********************//**********************//**********************   
     
  // Arduino Nano Grow-box / Green-House Controller v 5.0 :)   
     
  //**********************//**********************//**********************//**********************//**********************//**********************   
     
     
 //###############################################################  
 //***************************************************************  
 
   
 // PLEASE SUBSCRIBE  
   
 // comment for any question or help with this sketch   
   
   
   
   
 //  My youtube Channel:  https://youtube.com/CrazyGuyOfficial  
   
   
 //****************************************************************  
 //################################################################   
     
     
     
  //       ***Made by Ali khan from Pakistan :)   
     
     
  //**********************//**********************//**********************   
     
  // **PARTS required (for this sketch to work as it is )   
     
  //**********************//**********************//**********************   
     
  1.Arduino Nano   
     
  2.A thermistor (i used A 10K WATERPROOF ONE)   
     
  3.A resistor (matching the value of the thermistor's "nominal resistance at 25 DEGREES C" for example: 5k resistor for 5k thermistor)   
     
  4.SPI OLED display ssd1306 (mine is ssd1306 but got it working by using sh1106 constructor also got rid of the "white line problem")   
     
  5. DHT 22 (WITH PULL UP RESISTOR I USED 10k OHM)  
     
  6.RELAY MODULE LOW LEVEL TRIGGER TYPE (6 Relays required in total for all the pins, can be separate 4 CAN WORK TOO )   
     
  7. DS3231 RTC MODULE (RESISTOR from charging circuit REMOVED and charging DISABLED..BECAUSE I USED CR2032(NON-rechargeable)Cell   
     
  8. AN LED WITH APPROPRIATE RESISTOR FOR USE AS A STATUS LED   
     
  9. Soil Humidity Sensor   
   
  10. Water Level Sensor  
   
  11. Two Stable 5 Volts DC Power Sources with Separate Grounds For Complete Optical Isolation (one can work)  
    
  */   
     
 //**********************//**********************//**********************   
 // INCLUDE LIBRARIES make sure you have them all installed   
 //**********************//**********************//**********************   
     
   // Get them from within you Arduino IDE 1.6.9 that i used   
   // get the correct version  
   // by correct i mean the version that i used and   
   // because i can't guarantee that this sketch will work with  
   // other latest versions of the same libraries  
   
    
    
    
 #include "DHT.h"   // use DHTsensorLibrary // Version 1.2.3 //latest is the AdafruitUnifiedSensorLibrary    
 #include <U8glib.h>  // OLED  // Version 1.19.1  
 #include <Wire.h>  // I2C  // Version 1.0.0  
 #include <Time.h>  // Time Manipulation  // Version 1.5.0  
 #include <DS1307RTC.h> // DS1307 RTC  // Version 1.4.0  
 #include <TimeAlarms.h> // time alarm library // Version 1.5.0   
    
    
        // Changed Number of alarms " dtNBR_ALARMS to 8 "   
        // BY EDITING TIMEALARM.H FILE IN LIBRARIES FOLDER.   
          
        // increasing this number increases size of the sketch too   
        // and the use of ram  
   
        // if you don't want to change the number then remove alarms and keep only   
        // that number of Alarms that is specified in YOUR TimeAlarms Library   
          
        // I have Left 8 Alarms BELOW that Call a Function to Sync Arduino's Clock with RTC  
        // if you Uncomment the Rest you will get some Errors  
   
        // if you increase the Number in TimeAlarms.H file then   
        // Don't UN-comment Void SPrintStatusTwo   
        // That prints out Switch Status  
        // OR you will get Low Memory Error for Nano/UNO  
         
   
    
    
    
    
    
 #define DS1307_ID 0x68 // I2c Address of the RTC   
     
     
      
     
     
 //######################################################################    
 //******************************************************************/   
 //  TEMPERATURE and HUMIDITY DEFAULT "CONTROL PARAMETERS"              
 //******************************************************************\  
 //######################################################################    
   
   
  // Default Temperature and Humidity Settings   
     
 byte Tmax  =  29 ;   // Set temperature Maximum point at which "Cooler" will turn ON   
 byte Tnor  =  25 ;   // Set temperature point at which "heater" and "cooler" will turn OFF   
 byte Tmin  =  19 ;   // Set temperature Minimum point at which Heater will turn ON   
 byte Hmax  =  60 ;   // set humidity max at which "bigfan" will turn ON   
 byte Hnor  =  45 ;   // Set humidity normal at which "bigfan" and "spray" will turn OFF   
 byte Hmin  =  25 ;   // Set humidity low at which "spray will turn ON   
     
   
  // Separate Temperature and Humidity Settings for Day and Night time can be done by Alarms function belowwww   
    
  // but anything done by Alarms is lost if a Reset happens or power up/down cycle   
  // and so in that case everything will return to their default state   
    
    
    
    
    
 //######################################  
 //*********************************/  
 // PUMP TURN ON/OFF Settings ####  
 //*********************************\  
 //######################################  
    
   
   
  
 byte pumpT  = 30 ; // Time in Seconds for which the Pump will run if Soil goes Dry  
            // after the Time is up the pump will Turn Off   
   
 byte dryVal = 50 ;  // Soil Humidity percentage Value below which the Pump will be Turned ON   
            // when the Alarm Calls the WateringA function   
            // pump will turn OFF after the Time "pumpT" is up   
   
 int DV = 1023 ; // Dry Value the MAX Analog Read Value Above which the Soil gets DRY //max 1023   
 int HV = 0  ; // Humid / Wet Value below which the Soil should not be watered   // min 0   
          // these numbers are used to "map" analog read values in SoilHumCalc Function   
          // can be used for Calibration   
   
   
 byte waterOne = 50 ; // Water Level Sensor 1 percentage Value below which the water reservoir will be considered empty         
   
 int  FV1   = 800 ; // MAX value when Tank is FULL // i used it because my sensor doesn't give out 5V/max 1023 when 100% wet   
 int  EV1   = 0  ; // MIN Value Below Which Tank is Empty // min 0  
     
   // Separate Function for watering using the Digital/Analog Read method for Soil Humidity Sensor's Digital/Analog output Pins   
   // can be called from alarm functions belowwwww       
     
   
 //##################################################  
 //***********************************************/   
 //  Light Timer ON/OFF Time Settings DEFAULT    
 //***********************************************\   
 //##################################################    
     
   
   
 const byte OnTime = 14 ; // Hour when Light will turn ON (24 hr format NO zeros before single digits)   
 const byte OffTime = 8 ; // Hour when Light will turn OFF (24 hr format NO zeros before single digits)   
     
     
  // SET RTC'S TIME USING DS1307 EXAMPLE SKETCH FROM ABOVE FILE > EXAMPLE > DS1307 > SETTIME   
  // THEN UPLOAD THIS SKETCH   
     
     
   
    
    
    
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
   
 //***************************************************   
 //  MAKING CHARACTER ARRAYS or C strings  for OLED   
 //***************************************************   
     
     
     
 char str[10]; // for Display   
     
     
     
    
//#################################################################################################################   
//*****************************************************************************************************************   
//************ some important variables *************** Values NOT TO BE CHANGED MANUALLY *************************   
//*****************************************************************************************************************   
//#################################################################################################################  

float t2    =  0;  // for Temperature 2 from Thermistor            
   

float t  =0;       // floats for Temperature1 and Humidity from DHT  
float h  =0;          
 
 
 
byte TempSts  = 0 ;   // used for updating the oled display   
byte HumSts   = 0 ;      
    
   
float TmaxR  =  0;  // for Recording Max and Min Values from DHT  
float HmaxR  =  0;  
    
float TminR  =  0;  
float HminR  =  0;     

 
   
    
    
bool DHTerr   = 0 ;    
bool RTCerr   = 0 ;  
   
 
   
bool LightSts  = 0 ;    // THESE ARE FOR STATUS UPDATES IN SERIAL MONITOR     
bool CoolerSts = 0 ;    // and ESP8266 to show on Html Webpage   
bool HeaterSts = 0 ;   
bool BigFanSts = 0 ;   
bool SpraySts  = 0 ;   
bool PumpSts   = 0 ; 

   

 
 
int soilHumVal     = 0  ; // for reading analog value from Soil Humidity Sensor's Analog output  

bool waterTimeA   = 0 ;  
bool waterTimeD   = 0 ; 



int waterLvlOneVal = 0  ; // for reading analog value from Water Level Sensor's Analog output   

bool REmpty   = 0 ;   // water reservoir empty    

    
unsigned long Secs = 0;   
unsigned long SecsTwo = 0;   
unsigned long SecsThree = 0;   
  
   
   
   
   
   
   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
   
    
    
    
 //##################################  
 //********************************/  
 //    PINS AND CONNECTIONS   
 //********************************\  
 //##################################   
   
 const byte Bigfan   = 2 ;  // Bigfan pin turns on at high humidity should be Two fans (inside,exhaust)    
   
 const byte cooler   = 3 ;  // Cooler pin turns on at high temp (T1 from DHT)   
   
 const byte spray    = 4 ;  // Spray turns on at low humidity   
   
 const byte lightone  = 5 ;  // Main Lights(for plants)    
    
 const byte heater   = 6 ;  // Heater pin turns ON at low temp (T1 from DHT)   
   
 const byte lighttwo  = 7 ;  // pin for "status LED'   
   
 const byte pumpPin   = 8  ;  // pin for turning the Water Pump ON/OFF  
   
 const byte waterLvlOne = A2 ;  // pin for water level Sensor's Signal output pin it gives it gives raw voltage values   
   
 const byte soilHumD  = A3 ;  // pin for Soil Humidity Sensor's DIGITAL Output Signal Pin it goes High/Low  
   
 const byte soilHumA  = A7 ;  // pin for Soil Humidity Sensor's ANALOG Output Signal Pin it gives raw voltage values  
   
   
   
     
  // ******** THERMISTOR AND DHT PINS BELOW *******   
  // Connect the RTC according to it's pinout    
  // DS3231 RTC "SDA to A4", "SCL to A5"(uno/nano) "Vcc to 5V arduino pin Gnd to Gnd"  
   
     
   
   
 //####################################  
 //********************************/   
 //  THERMISTOR PIN and SETTINGS   
 //********************************\  
 //####################################  
   
   
   
 #define THERMISTORPIN A0     // analog pin to connect to thermistor and the resistor "joint"     
     
     
     
     
 #define THERMISTORNOMINAL 10000 // resistance at 25 degrees C     
     
 #define TEMPERATURENOMINAL 25  // temp. for nominal resistance (almost always 25 C)   
     
 #define NUMSAMPLES 5       // how many samples to take and average,takes longer gets 'smooth'   
     
 #define BCOEFFICIENT 3500    // The beta coefficient of the thermistor (usually 3000-4000)   
     
 #define SERIESRESISTOR 9700   // the value of the 'other' resistor should be close to the thermistors nominal value    
     
 int samples[NUMSAMPLES];   
     
     
    
      
 //################################  
 //****************************/   
 //  DHT PIN and SETTINGS   
 //****************************\   
 //################################    
     
    
 #define DHTPIN A1  // pin connected to DHT output   
     
     
     
 #define DHTTYPE DHT22 // DHT 22 (AM2302)   
     
 DHT dht(DHTPIN, DHTTYPE, 6); // the number 6 is for slower chips like the one used in Arduino Nano/UNO   
     
     
     
     
     
     
   
            
     
 //######################################################################   
 //*****************************************************************/   
 // OLED CONSTRUCTOR / OLED PINS that are connected to Arduino  
 //*****************************************************************\  
 //######################################################################   
    
    
 U8GLIB_SH1106_128X64 u8g(13, 11, 10, 9); // SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9 // OLED "constructor" and pins info.   
   
              // the version of oled i have has a different chip inside so the above one works for me   
              // before it i used the one that was supposedly for my version of oled and it was not working as expected   
              // if this doesn't work for you then go to Example Sketches for U8glib Library it has All the Constructors   
              // try them for your version of OLED  
     
   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
   
    
    
    
  //**************************   
  //    SETUP BEGINS   
  //**************************   
     
  void setup()   
    
 {   
    
    
  digitalWrite(Bigfan, HIGH); // When using "LOW level trigger" type Relay module, turning a pin "HIGH" will   
  digitalWrite(cooler, HIGH); // turn the relay "OFF" and turning the pin "LOW" turns the relay "ON"    
  digitalWrite(heater, HIGH); // THIS WILL PREVENT STARTUP RELAY TRIGGERING PROBLEM   
  digitalWrite(spray, HIGH);   
  digitalWrite(pumpPin,HIGH);   
  digitalWrite(lightone,HIGH);   
    
     
   // add more if you have more relays or pins connected to something    
    
    
    
  Serial.begin(9600);     // for initializing serial monitor   
   
    
    
    
  pinMode(Bigfan, OUTPUT) ; // set output relay pins // add more if you have more relays or pins connected to something    
  pinMode(cooler, OUTPUT) ;   
  pinMode(heater, OUTPUT) ;   
  pinMode(spray, OUTPUT) ;   
  pinMode(lightone,OUTPUT) ;   
  pinMode(lighttwo,OUTPUT) ;   
  pinMode(pumpPin,OUTPUT) ;  
    
    
  pinMode(soilHumD, INPUT)  ;   
  pinMode(soilHumA,INPUT)   ;  
  pinMode(waterLvlOne,INPUT) ;   
     
     
     
     
   // add more if you have more relays or pins connected to something    
    
    
      
    
    
  analogReference(EXTERNAL); // AREF connected to 3.3 ON BOARD for accuracy of thermistor    
          //(go to adafruit using a thermistor tutorial )   
     
     
     
   
    
//******************************************   
//********* Display at Startup  ********   
//******************************************    
   
     
Start();  
Alarm.delay(3000);  
  
LightSet();  
Alarm.delay(5000);  
   
TempSet();  
Alarm.delay(5000);  
   
HumSet();  
Alarm.delay(5000);  
    
    
    
    
    
//**********************//**********************//***********************//**********************   
//Check to see if the RTC is present.if yes then Set the ARDUINO's INTERNAL clock accordingly   
//**********************//**********************//***********************//**********************   
     
     
// when using timer library the Arduino's "internal clock " is used for getting "current time"    
// Arduino's internal clock is NOT so accurate and gets off time so we use time from RTC (which IS    
// accurate at-least for our use) and we sync Arduino's internal Clock with the time from RTC and we    
// have to do this periodically (at-least once in every 24 hrs )so our tasks can be completed according    
// to the correct time we can put the sync command in the Loop and Alarm Functions too    
     
    
Wire.beginTransmission(DS1307_ID); // i2c devices have addresses which are used to communicate with them   
Wire.write((uint8_t)0x00);     // because same interface can be used to connect multiple i2c devices   
                      
setSyncProvider(RTC.get);   // Configure Time to automatically called the getTimeFunction() regularly.
 
setSyncInterval(60);
   
    

     
    
    
    
    
    
    
  
 //#####################  
 
Alarm.timerRepeat(10, Repeats); // timer for every 10 seconds blinking LIGHT TWO (status LED)   
                                 // and Serial Prints Data         
                            // TIMER ALARM THAT RUNS OVER AND OVER AFTER SECONDS // the Alarm in the Loop are different    
                            // see the Example Sketches with the TimeAlarms Lib   
                
   
    
    
dhtCalc()   ;  // call DHT,Thermistor calculation and Soil Humidity functions at setup   
    
thermCalc()  ;  // so the relays don't trigger accidentally in those two seconds after which the loop calls those functions again   
    
soilHumCalc() ;   
    
waterLvlCalc() ;  
   
Secs=SecsTwo=millis()/1000; // reset the timers and then in the loop it will be used again and again   
   
   
   
}   
     
    
  //**************************************************************   
    
  //*********   SETUP END ****************************************  
    
  //**************************************************************   
   
   
   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
    
   
    
    
//*************************************************  
//*** Function that Syncs Arduino's Clock with Rtc   
//*************************************************   
   
   
void SyncTime()  
{  
   
    
  if (Wire.endTransmission() == 0) //Did the RTC respond?   
    
  {   
    
   setSyncProvider(RTC.get);  // it did, get the time from the RTC   
    
   RTCerr=0;          // set RTC error status boolean to false  
     
  // Serial.println("Got Time");    
   
  }   
    
  else  
  {  
    
  RTCerr=1;  
    
  }  
    
}  
    
   
   
 //**************************************************   
 //*** Function For Display on the OLED *************   
 //**************************************************   
   
void Start()  
   
{  
   
       
 u8g.firstPage();     // START SCREEN "Picture loop" for OLED   
     
 do  
 {   
     
  u8g.setFont(u8g_font_helvB08);  // set font for oled display   
     
  u8g.drawFrame(10, 12, 108, 31); // Draw Frame and it's Size   
  u8g.drawFrame(0, 0, 128, 64);  // Draw Frame and it's Size   
  u8g.drawStr(15, 25, "Grow Box"); // Draw a string mentioned in quotes " "   
  u8g.setPrintPos(79,32);     // Set print position for the next line  
  u8g.print("V 5.0");       // Print on the oled   
  u8g.drawStr( 16, 40, "Controller");   
  u8g.drawStr(53, 60, "Made by:AMK");        
    
  }   
  while ( u8g.nextPage() );   
   
}   
   
   
   
   
//***************************************************************   
//*** Function For Light Control Settings Display on the OLED ***   
//***************************************************************   
   
void LightSet()  
{  
   
 u8g.firstPage();     // START SCREEN "Picture loop" for OLED   
     
 do   
 {   
    
  DrawFrame();
  
   
  u8g.drawStr(4, 14, "Light Control Hours");   
  u8g.drawStr( 4, 34,"ON:");    
    
  u8g.setPrintPos(31,34);   
  u8g.print(OnTime);   
     
  u8g.drawStr( 4, 46,"OFF:");    
    
  u8g.setPrintPos(37,46);   
  u8g.print(OffTime);  
    
 }   
    
 while ( u8g.nextPage() );   
     
}  
   
   
//*********************************************************************   
//*** Function For Temperature Control Settings Display on the OLED ***   
//*********************************************************************   
    
void TempSet()  
{  
       
 u8g.firstPage();     // //START SCREEN "Picture loop" for OLED   
     
 do   
 {   
  
  DrawFrame();

  u8g.drawStr(4, 14, "Temp Control Settings");   
     
  u8g.drawStr( 4, 34,"Max:");    
  u8g.setPrintPos(39,34);   
  u8g.print(Tmax);   
  u8g.drawStr( 58, 34, "\260C"); // make Degree Centigrade Symbol  
   
  u8g.drawStr( 4, 46,"Nor:");    
  u8g.setPrintPos(39,46);   
  u8g.print(Tnor);  
  u8g.drawStr( 58, 46, "\260C");   
    
  u8g.drawStr( 4, 58,"Min:");    
  u8g.setPrintPos(39,58);   
  u8g.print(Tmin);   
  u8g.drawStr( 58, 58, "\260C");   
    
     
 }   
     
 while ( u8g.nextPage() );   
     
}  
   
   
   
//*********************************************************************   
//*** Function For Humidity Control Settings Display on the OLED ***   
//*********************************************************************   
   
   
void HumSet()  
   
{  
   
 u8g.firstPage();     // //START SCREEN "Picture loop" for OLED   
     
 do   
 {   
  DrawFrame();

  u8g.drawStr(4, 14, "Humidity Settings");   
     
  u8g.drawStr( 4, 34,"Max:");    
  u8g.setPrintPos(39,34);   
  u8g.print(Hmax);   
  u8g.drawStr( 58, 34, "%");   
   
  u8g.drawStr( 4, 46,"Nor:");    
  u8g.setPrintPos(39,46);   
  u8g.print(Hnor);  
  u8g.drawStr( 58, 46, "%");   
   
  u8g.drawStr( 4, 58,"Min:");    
  u8g.setPrintPos(39,58);   
  u8g.print(Hmin);   
  u8g.drawStr( 58, 58, "%");   
   
 }   
     
 while ( u8g.nextPage() );   
    
}  
   
   
void DrawFrame()
{ u8g.drawFrame(0, 0, 128, 20);  // Draw frame
  u8g.drawFrame(0, 22, 128, 42); // Draw frame
}
   
   
   
   
//########################################################################################
//***************************************************************************************/   
//************ Function Called When Repeating Timer alarm triggers ******************   
//***************************************************************************************\   
//########################################################################################

void Repeats()   
{   
     
 if(!DHTerr && !RTCerr)   // blink the light only when DHTerr is not 1 because then status LED will constantly stay ON  
    
 {  
  digitalWrite(lighttwo, HIGH); // it is also used to indicate Dht read failed and lights up continuously below in dht part   
     
  Alarm.delay(30);   
     
  digitalWrite(lighttwo, LOW);   
 }   
     
    
    
    
 //TimeDateDisplayOne();  // Update the Clock Display on Tx line   
                          // this calls the function TimeDateDisplayOne   
                          // includes time,date,day,year only numbers   
                          // Formatted to be read by ESP8266 using Serial.Read  
    
    
 //SPrintStatusOne(); // SerialPrints data on the Tx line of Arduino  
                      // by connecting the Rx line of Esp8266 / Wemos D1 mini  
                      // that is running an html webserver  
                      // that data is read and categorized in Arrays and then displayed   
                      // on a simple html page  
              
    // *************         
    // * IMPORTANT * : if anything is changed Regarding serial.print/Serial.println   
    // *************  anywhere in the Sketch it WILL effect the Results of the sketch   
       //      running in Esp8266 because of the changed position/content of the   
       //      data printed on Tx line and Read by Rx of Esp8266 so keep it in mind   
   
    
  TimeDateDisplayTwo(); // For Humans Only  
   
    
  SPrintStatusTwo();  // For Humans Only  
   
   
}                
     
   
   
   
   
   
   
   
//##################################################################################################################   
//*****************************************************************************************************************   
//*****************************************************************************************************************   
//*****************************************************************************************************************   
//*****************************************************************************************************************   
//*****************************************************************************************************************   
//##################################################################################################################    
   
   
   
   
//########################################################################   
//***********************************************************************/   
     
//**********   LOOP BEGINS  ******************************************   
     
//***********************************************************************\   
//########################################################################   
     
     
     
void loop()   
    
{   
     
     
     
  if (hour() == 0 && minute() == 0 && second() == 0) //If it is 00:00:00 MIDNIGHT UPDATE the Arduino's INTERNAL Clock   
    
  {   
    
   SyncTime();   
     
  }   
     
     
     
     
     
     

  //####################################################################################################
  //####################################################################################################


  //###### LET THERE BE LIGHT ########################################################################


  //####################################################################################################
  //####################################################################################################

  // This will make sure that the light one (for plants) stays ON after reset or power down/up cycle
  // because Alarms will trigger on a given time and will turn the pin HIGH but if after the alarm is
  // triggered AND there is a reset the pin will turn off until next alarm that turns it ON again
  // which can interrupt photo-period for plants So, this makes sure that LIGHTS turn ON immediately
  // after reset which happens DURING the LIGHT period for plants




  //####################################################################################################

  // Turn Lights On/Off

  //####################################################################################################


  // if(!RTCerr)   // only if RTC error is 0 or False
  // {

  // IF Turning ON the Light is Required on one day and Turning OFF on the same day
  // within the 24 hrs of that day 00:00 --- 11:59


  if (OffTime > OnTime)  // Same Day

  { // GETS THE JOB DONE :)


    if (hour() >= OnTime && hour () <= OffTime - 1)

    {

      // if current hour is equal to or greater than ON time
      // AND equal to or less than OFF time minus 1 then turn the
      // lights ON (by turning pins LOW because of using LOW level Relays)

      // Minus 1 from OFF time because we are not using Minutes here
      // For Example turn off time is "16" (4 PM) the hour number will be "16" from
      // 16:00 till 16:59 (4:00 till 4:59)
      if (!LightSts)
      {
        digitalWrite(lightone, LOW);
        Alarm.delay(2000);
        LightSts = 1 ;
      }

    }


    else

    {
      digitalWrite(lightone, HIGH);

      LightSts = 0 ;

    }



  }


  //####################################################################################################


  if (OffTime < OnTime)  // Different Day

  {
    // IF Turning ON the Light is Required on ONE DAY and

    // Turning OFF on the SECOND DAY

    if (hour() >= OnTime || hour () <= OffTime - 1)

    {

      // if current hour is equal or greater than ON time
      // OR equal to or less than OFF time minus 1 then turn the
      // lights ON (by turning pins LOW because of using LOW level Relays)
      // Minus 1 from OFF time because we are not using Minutes here
      // For Example turn off time is "16" (4 PM) the hour number will be "16" from
      // 16:00 till 16:59 (4:00 till 4:59)
      // Minutes,Seconds even day,date,year can be used by adding code

      if (!LightSts)
      {
        digitalWrite(lightone, LOW);
        Alarm.delay(2000);
        LightSts = 1 ;
      }



    }


    else

    {

      digitalWrite(lightone, HIGH);

      LightSts = 0 ;

    }




  }



  // }
  // else
  // {
  //  digitalWrite (lighttwo,HIGH); // turn status LED indicate RTC error
  //  //Serial.println("Something Wrong with RTC.So, NOT Controlling Lights Now");

  // }


  if (RTCerr)
  {
    digitalWrite (lighttwo, HIGH); // turn status LED indicate RTC error
  }







   
   
   
   
//###############################################################################################################   
// *************************************************************************************************************/   

// DAILY TIMED ALARMS THAT TRIGGER ON SPECIFIED TIMES   
    
// these alarms will trigger once and will do "stuff" mentioned in the alarm functions at the end of the loop   
     
// *************************************************************************************************************\  
//###############################################################################################################    
    
    
    
      
Alarm.alarmRepeat(3, 0, 0, ONAlarm); // daily Alarm 1 for example // for triggering an alarm on ""03:00:00"" in the morning AM   
   
                      
                    // ONAlarm is the name of the function that will be called when the current time matches   
                    // the Time you have set for the specified alarm  
                    // the ONAlarm function is defined below and the name ONAlarm can be changed   
        // the fuctions will be called only at the moment when the time matches the alarm time  
        // and if the state of switch is changed and then Arduino is reset the state will change back to default   
      
     
      
Alarm.alarmRepeat(6, 0, 0, OFFAlarm);   // daily Alarm 2   
      
      
Alarm.alarmRepeat(9, 0, 0, OFFAlarm);   // daily Alarm 3   
    
       
Alarm.alarmRepeat(12, 0, 0, OFFAlarm);   // daily Alarm 4   
     
      
Alarm.alarmRepeat(15, 0, 0, OFFAlarm);   // daily Alarm 5    
     
      
Alarm.alarmRepeat(18, 0, 0, OFFAlarm);   // daily Alarm 6     
      
      
Alarm.alarmRepeat(21, 0, 0, OFFAlarm);   // daily Alarm  7   
     
/*

Alarm.alarmRepeat(15, 35, 0, ON2Alarm);   // daily Alarm 5    
     
      
Alarm.alarmRepeat(18, 37, 0, wateringD);   // daily Alarm 6     
      
      
Alarm.alarmRepeat(21, 38, 0, wateringA);   // daily Alarm  7   */

//############################################################
   




  //#####################################
  // Get Sensor Values after every 2 Secs
  //#####################################

  if (millis() / 1000 - Secs > 2 ) // Call dht and thermistor calculation fuction every 2 secs
  {

    dhtCalc()   ;

    thermCalc()  ;

    soilHumCalc() ;

    waterLvlCalc() ;
    if (waterLvlOneVal < waterOne)
    {

      REmpty = 1 ;

      u8g.firstPage();

      do
      {
        DrawFrame();

        u8g.drawStr(4, 14, "Water Tank");
        u8g.drawStr( 14, 44, "* EMPTY *");
      }

      while ( u8g.nextPage() );



      Alarm.delay(1300);


    }

    else
    {
      REmpty = 0 ;
    }


    Secs = millis() / 1000; // then reset the timer

  }








  //#########################################################################################################
  //###############################################################################################################

  // CONTROL PART turning things ON and OFF according to Temperature and Humidity (THE GOOD STUFF) "ifs"

  //###############################################################################################################
  //#########################################################################################################

  if (!DHTerr)         // only proceed to controlling things according to Temp1 and humidity
  { // if there is no DHT read error

    if (t >= Tmax )      // TURN COOLER ON IF TEMPERATURE IS EQUAL TO OR EXCEEDS "Tmax" (HEATER remains OFF)
    {
      if (!CoolerSts)
      {
        digitalWrite(cooler, LOW);// Turn Cooler Pin LOW // ON because of LOW Level trigger Relay

        Alarm.delay(2000);

        CoolerSts = 1 ;      // Cooler Status is ON // Status is used for Serial Print

      }
      TempSts = 4;      // High Temp // Status is used by Oled

    }




    if (t <= Tnor )       // Turn OFF the COOLER when TEMP GETS DOWN TO "setT" OR GOES BELOW

    {

      digitalWrite(cooler, HIGH);

      CoolerSts = 0 ;

    }




    if (t <= Tmin)       // TURN HEATER "ON" WHEN TEMPERATURE GETS TO "Tmin" OR BELOW (cooler remains OFF)

    {
      if (!HeaterSts)
      {
        digitalWrite(heater, LOW);

        Alarm.delay(2000);

        HeaterSts = 1 ;
      }


      TempSts = 1;      // Low Temp

    }




    if (t >= Tnor )     // TURN OFF HEATER WHEN TEMP GETS TO "setT" (and REMAINS LOWER THAN "Tmax")

    {

      digitalWrite (heater, HIGH);

      HeaterSts = 0 ;


    }



    //######################################/
    //######################################/
    //# Just for Setting Status of things #
    //######################################/
    //######################################\   


    if (t <= Tmax && t > Tnor)

    {
      TempSts = 3; // Upper Range
    }






    if (t <= Tnor && t > Tmin)

    {
      TempSts = 2; // normal range
    }



    if ( t > TmaxR)
    {

      TmaxR = t;   // Update Max Recorded Temperature For the Session

    }

    if ( t < TminR)
    {

      TminR = t;   // Update Minimum Recorded Temperature For the Session

    }
    else if (TminR == 0)
    {
      TminR = t;
    }





    //#######################################################

    //############### Control for HUMIDITY ###############

    //#######################################################


    if (h >= Hmax)

    {
      if (!BigFanSts)
      {
        digitalWrite(Bigfan, LOW); // Turn fan on when humidity is high

        Alarm.delay(2000);

        BigFanSts = 1 ;
      }

      HumSts = 4;        // humidity max/high

    }


    if (h <= Hnor )

    {

      digitalWrite(Bigfan, HIGH);

      BigFanSts = 0;

    }



    if (h <= Hmin)
    {
      if (!SpraySts)
      {
        digitalWrite(spray, LOW); // Turn Spray on when humidity is low

        Alarm.delay(2000);

        SpraySts = 1 ;
      }
      HumSts = 1;  // humidity low

    }

    if (h >= Hnor)

    {

      digitalWrite(spray, HIGH); // Turn Spray off when humidity is normal or high

      SpraySts = 0 ;

    }





    if (h > Hnor && h < Hmax)

    {
      HumSts = 3; // upper range
    }



    if (h > Hmin && h <= Hnor)
    {
      HumSts = 2; // normal range
    }

    if ( h > HmaxR)
    {

      HmaxR = h;   // Update Max Recorded Humidity For the Session

    }
    if ( h < HminR)
    {

      HminR = h;   // Update Max Recorded Humidity For the Session

    }
    else if (HminR == 0)
    {
      HminR = h;
    }


  }

  else

  {

    digitalWrite (lighttwo, HIGH); // turn status LED indicate DHT error
    //Serial.println("Something Wrong with DHT.So, NOT Controlling Things Now");
    digitalWrite(Bigfan, HIGH);
    digitalWrite(cooler, HIGH);
    digitalWrite(heater, HIGH);
    digitalWrite(spray, HIGH);


  }



//############################################################## 
//************************************************************//   
    
//*************** Control for Water Pump ***********   
     
//***********************************************************//     
//############################################################# 

//###############################################/   
// Using Soil Humidity Sensor's Digital OUTPUT
//###############################################\ 


   
  if(waterTimeD)     // using Digital OUT Pin from Soil Humidity Sensor 
  {     

    if(digitalRead (soilHumD) == HIGH   && !REmpty && !PumpSts)  
    {  

     digitalWrite(pumpPin,LOW);  
     Alarm.delay(2000);
     PumpSts   = 1 ; 
   
    } 
   
    else if (millis()/1000 -SecsThree > pumpT && PumpSts)
    {
    
     digitalWrite(pumpPin,HIGH);  
     PumpSts   = 0 ; 
     waterTimeD = 0;
    
    } 
 
 }   

//###############################################/   
// Using Soil Humidity Sensor's Analog OUTPUT
//###############################################\ 
  
  if(waterTimeA)     // Using Analog Pin from Soil Humidity Sensor 
  {     

    if(soilHumVal < dryVal && !REmpty && !PumpSts)  
    {  
    
     digitalWrite(pumpPin,LOW);  
     PumpSts   = 1 ; 
    
    } 
   
    else if (millis()/1000 -SecsThree > pumpT && PumpSts)  
    {
     
     digitalWrite(pumpPin,HIGH);  
     PumpSts   = 0 ;   
     waterTimeA = 0;
    
    } 
 
}       
   
//###################################   
//###################################   
 
  
  
  
  Display(); // Call the Main Display Loop function (beloww) for OLED  
     
    
//#######################################   
// Call Recorded Max & Min Display loops
//#######################################   
    
    
  if(millis()/1000 -Secs > 60 )  // Call Max & Min Recorded Temp & Hum Display Loop every 60 secs  
  {  
   
  RecMax();  
  Alarm.delay(2000);        // and show them for 5 secs each  
  RecMin();  
  Alarm.delay(2000);  
  Secs=millis()/1000;       // reset the timer "secs"  
   
     
  }   
   
 
 
 
}   
   
    
  //**********************//**********************//**********************   
  //        LOOP END   
  //**********************//**********************//**********************   
   
   
   
   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
 //*****************************************************************************************************************   
   
   
   
   
   
   
 //********************//**********************//************//   
 // Function for DHT 22 TEMPERATURE HUMIDITY CALCULATIONS   
 //********************//**********************//************//   
     
 void dhtCalc()   
 {   
     
     
  h = dht.readHumidity();  // READ HUMIDITY   
     
  t = dht.readTemperature(); // Read temperature as Celsius   
     
    
      
  if (isnan(h) || isnan(t) )   
  {   
     
   Alarm.delay(500);   
     
   DHTerr=1;   
        
  }   
    
  else  
  {    
   
   DHTerr=0;  
    
  }  
    
 }  
   
   
   
   
   
 //********************************************   
 // Function for THERMISTOR CALCULATIONS   
 //********************************************   
     
 void thermCalc()    
 {  
     
     
  byte i;   
  float average =0 ;   
     
     
  for (i = 0; i < NUMSAMPLES; i++) // take "N" number of samples in a row, with a slight delay   
  {    
    
   samples[i] = analogRead(THERMISTORPIN);   
   Alarm.delay(10);   
    
  }   
     
     
     
    
  for (i = 0; i < NUMSAMPLES; i++) // average all the samples out   
  {    
   average += samples[i];   
  }   
    
  average /= NUMSAMPLES;   
  average = 1023 / average - 1;    // convert the value to resistance   
  average = SERIESRESISTOR / average;   
       
  t2= average / THERMISTORNOMINAL;  // (R/Ro)   
  t2 = log(t2);     // ln(R/Ro)   
  t2 /= BCOEFFICIENT;     // 1/B * ln(R/Ro)   
  t2 += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)   
  t2 = 1.0 / t2;     // Invert   
  t2 -= 273.15;     // convert to C   
     
     
     
 }   
     
     
   
   
   
   
   
 //***************************************  
 // Function for Reading Soil Humidity   
 //***************************************  
   
   
 void soilHumCalc()  
 {  
  soilHumVal= analogRead(soilHumA) ;   
   
  //Serial.print("Soil Hum: ");  
  //Serial.println(soilHumVal);  
   
  soilHumVal = map(soilHumVal,DV,HV,0,100);  
   
   
   
 }  
   
   
   
   
   
   
 //***************************************  
 // Function for Reading Water Level    
 //***************************************  
    
   
 void waterLvlCalc()  
 {  
   
  waterLvlOneVal= analogRead(waterLvlOne) ;   
   
  //Serial.print("Water Lv: ");  
  //Serial.println(waterLvlOneVal);  
   
  waterLvlOneVal = map(waterLvlOneVal,EV1,FV1,0,100);  
   
   
  
   
   
}  
   
   
   
   
   
   
   
 //**************************************************   
    
 // Main Loop FUNCTION FOR Main DISPLAY ON THE OLED   
     
 //**************************************************   
     
     
     
     
 void Display()  
    
 {  
   
  char timebuf[5]; // array for Time   
     
     
  tmElements_t tm;     //formatting time and date before displaying   
     
     
  if (RTC.read(tm))   
  {   
   sprintf(timebuf, "%02d:%02d", tm.Hour, tm.Minute); // format time   
  }  
     
     
     
  u8g.firstPage();       
     
  do   
  {   
      
   DrawFrame();
   if(DHTerr)    // if DHT error is 1 or true then display dht error on oled  
   {  
    u8g.drawStr( 35, 14, "* DHT ERROR *");   
   }  
     
   
   else      // else display values  
   {  
     
    switch (HumSts)  // Display According to Humidity Status on OLED   
     
    {  
     
    case 4:  
        u8g.drawStr( 91, 14, "*H MX*"); // humidity is equal to max or more than max  
    break;  
      
      
    case 3:  
        u8g.drawStr( 91, 14, "*H AN*"); // above normal  
    break;  
      
     
    case 2:  
        u8g.drawStr( 91, 14, ">H NR<"); // Normal  
      
    break;  
      
      
    case 1:  
        u8g.drawStr( 91, 14, "*H LW*"); // Lower than Minimum Humidity  
    break;  
         
    }  
      
 //*********************************************************************    
   
      
      
    switch (TempSts) // Display According to Temperature Status on OLED   
    {  
    case 4:  
        u8g.drawStr( 34, 14, "*HI TMP*");   
    break;  
      
      
    case 3:  
        u8g.drawStr( 34, 14, "*ABV NR*");   
    break;  
      
      
    case 2:  
        u8g.drawStr( 34, 14, ">NR TMP<");   
    break;  
      
      
    case 1:  
        u8g.drawStr( 34, 14, "*LO TMP*");   
    break;  
         
    }  
     
     
     
     
  }  
     
     
     
  //************// Display Time on OLED//**************//   
        
   if(!RTCerr)  
   {     
    u8g.setPrintPos(2, 14); // set position for displaying time   
    u8g.print(timebuf);  //display time   
   }  
   else  
   {  
    u8g.drawStr( 2, 14, "RtcEr");   
   
   }  
     
     
     
     
     
  //****** Display CURRENT Temperature 1 & 2 , humidity,Set Tmax,Set Tnor and Set Tmin,Soil Humidity and Water Level on OLED *********************   
     
      
     
      
   u8g.drawStr(2, 32, "T :"); // first digit is screen coordinate for X-axis and second for Y-axis   
    
           // (it starts on left bottom corner of the text which is to be shown on the oled)   
      
           // T for temperature from DHT22 and T2 is from Thermistor   
      
   u8g.drawStr( 21, 32, dtostrf(t, 5, 2, str));    
   u8g.drawStr( 51, 32, "\260C");   
      
     
   u8g.drawStr( 2, 42, "M :");   
   u8g.drawStr( 21, 42, dtostrf(Tmax, 5, 2, str));   
   u8g.drawStr( 51, 42, "\260C");   
     
   u8g.drawStr( 2, 52, "N ");   
   u8g.drawStr( 15, 52, ":");   
   
   u8g.drawStr( 21, 52, dtostrf(Tnor, 5, 2, str));   
   u8g.drawStr( 51, 52, "\260C");   
     
   u8g.drawStr( 2, 62, "m ");   
   u8g.drawStr( 15, 62, ":");   
   
   u8g.drawStr( 21, 62, dtostrf(Tmin, 5, 2, str));   
   u8g.drawStr( 51, 62, "\260C");   
     
     
     
     
   u8g.drawStr( 65, 32, "T2:");   
   u8g.drawStr( 83, 32, dtostrf(t2, 5, 2, str));    
   u8g.drawStr( 113, 32, "\260C");   
      
      
   u8g.drawStr( 65, 42, "H :");   
   u8g.drawStr( 83, 42, dtostrf(h, 5, 2, str));   
   u8g.drawStr( 117, 42, "%");   
   
   
   u8g.drawStr( 67, 52, "SH:"); // Soil Humidity Value mapped to 0-100 %  
   u8g.setPrintPos(92, 52);   
   u8g.print(soilHumVal);    
   u8g.drawStr( 117, 52, "%");   
   
   u8g.drawStr( 67, 62, "WL:"); // water level mapped to 0-100 %  
   u8g.setPrintPos( 92, 62);   
   u8g.print(waterLvlOneVal);    
   u8g.drawStr( 117,62, "%");   
   
  }   
    
  while ( u8g.nextPage() );   
     
     
 }  
     
   
     
 //********************************    
 // Display Loop for Max Recorded    
 //********************************  
   
   
 void RecMax()  
 {  
       
  u8g.firstPage();       
     
  do   
  {   
   DrawFrame();
   
   u8g.drawStr(4, 14, "Max Recorded");   
     
   u8g.drawStr( 4, 34,"T Max:");    
   u8g.setPrintPos(47,34);   
   u8g.print(TmaxR);   
   u8g.drawStr( 75, 34, "\260C");   
   
   u8g.drawStr( 4, 46,"H Max:");    
   u8g.setPrintPos(47,46);   
   u8g.print(HmaxR);  
   u8g.drawStr( 79, 46, "%");   
  }   
     
  while ( u8g.nextPage() );   
     
  }   
    
   
   
   
   
 //********************************    
 // Display Loop for Min Recorded    
 //********************************  
    
    
 void RecMin()  
 {  
       
  u8g.firstPage();       
     
  do   
  {   
   DrawFrame();

   u8g.drawStr(4, 14, "Min Recorded");   
     
   u8g.drawStr( 4, 34,"T Min:");    
   u8g.setPrintPos(47,34);   
   u8g.print(TminR);   
   u8g.drawStr( 75, 34, "\260C");   
   
   u8g.drawStr( 4, 46,"H Min:");    
   u8g.setPrintPos(47,46);   
   u8g.print(HminR);  
   u8g.drawStr( 79, 46, "%");   
    
     
     
  }   
     
  while ( u8g.nextPage() );   
     
 }    
     
     
     
   
   
   
   
   
   
   
//**********************//**********************//**********************//**********************   
     
//Functions called when daily time specific alarms (above in the loop) triggers:    
     
//***********************************************//**********************//**********************   
     
/*    
void daySett()   
{   
     
//Tmax = 29;         // set day time temperatures   
//setT = 25;   
//Tmin = 19;   
  SyncTime();    
    
     
}   
     
void nightSett()   
{   
//Tmax = 26;        // set night time temperatures   
//setT = 23;   
//Tmin = 19;   
  SyncTime();    
   
}   
      
*/  
   
   
   
   
 void OFFAlarm() // when this fuction is called by the alarm it calls another fuction Synctime which syncs arduino's internal clock with RTC  
 {   
    
  SyncTime();    
   
 }   
   
   
   
   
 void ONAlarm() // this fuction calls two other fuctions   
 {   
  SyncTime();    
  
 }   
     
 
 
 
 void ON2Alarm() // this fuction calls two other fuctions   
 {   

 
  wateringA();  
  SyncTime();    
  
 }       
   
   
   
     
     
   
//*******************************************************************  
// Function for Watering using soil Humidity Sensor's Digital Output  
//*******************************************************************  
   
void wateringD()  
{ 

 SecsThree= millis()/1000; // reset the timer
   
 waterTimeD= 1 ;

 //Serial.println("water time D Flag set");    
  
}  
   
//*******************************************************************  
// Function for Watering using soil Humidity Sensor's Analog Output  
//*******************************************************************  
   
void wateringA()  
{  
 SecsThree= millis()/1000; // reset the timer
   
 waterTimeA = 1 ;

 //Serial.println("water time A Flag set");    
     
}  
   
   
   
   
   
   
///**************************************************************************************   
//*** Function for Serial Printing status of switches and other values ** FOR ESP8266 *   
//**************************************************************************************    
     
/*    
void SPrintStatusOne()  
   
{        
 Serial.print ('L');   
 Serial.print (LightSts);   
   
 Serial.print ('C');   
 Serial.print (CoolerSts);   
     
 Serial.print('H');   
 Serial.print(HeaterSts);  
     
 Serial.print('B');   
 Serial.print(BigFanSts);  
   
 Serial.print('S');  
 Serial.print(SpraySts);    
    
 Serial.print('E');   
 Serial.print(DHTerr);  
 Serial.print(RTCerr);  
    
 Serial.print('t');  
 Serial.print(t);  
    
 Serial.print('h');  
 Serial.print(h);  
   
 Serial.print('r');  
 Serial.println(t2);  
    
   
}  
   
*/  
    
//*************************************************************************************   
//*** Function for Serial Printing status of switches and other values ** FOR HUMAN ***   
//*************************************************************************************     
     
   
void SPrintStatusTwo()  
{  
 Serial.print("T1: ");  
 Serial.println(t);  
    
 Serial.print("H: ");  
 Serial.println(h);  
    
    
 Serial.print("T2: ");  
 Serial.println(t2);  
   
 Serial.print("Water Lv: ");  
 Serial.println(waterLvlOneVal);  
  
 Serial.print("Soil Hum: ");  
 Serial.println(soilHumVal);  
  
   
    
  if(LightSts)  
  {  
   Serial.println ("Light ON");   
  }  
    
  else  
  {  
   Serial.println("Light OFF");  
  }  
    
    
  if(CoolerSts)   
  {  
  Serial.println("Cooler ON");    
  }  
    
  else  
  {  
   Serial.println("Cooler OFF");  
  }  
    
  if(HeaterSts)   
  {  
  Serial.println("Heater ON");    
  }  
    
  else  
  {  
   Serial.println("Heater OFF");  
  }  
    
  if(BigFanSts)   
  {  
  Serial.println("Fan ON");    
  }  
    
  else  
  {  
   Serial.println("Fan OFF");  
  }  
    
  if(SpraySts)  
  {  
   Serial.println("Spray ON");  
  }  
    
  else  
  {  
   Serial.println("Spray OFF");  
  }  
   if(PumpSts)  
  {  
   Serial.println("Pump ON");  
  }  
    
  else  
  {  
     
   Serial.println("Pump OFF");    
  }
    
    
}  
     
   
   
   
   
//**********************//**********************//********************************   
     
//Function for digital clock display (in the SERIAL MONITOR  *** FOR ESP8266 ***  
     
//**********************//**********************//********************************   
     
/*   
     
     
void TimeDateDisplayOne() // digital clock display 24hr format // for ESP-8266 and HUM-an too :)  
   
{        
     
 Serial.print("Z");   
   
 PrintZD(hour());     // Print Hour Digit and add a zero before single digits   
     
 PrintCD(minute());    // Print a colon sign ":" and add zero before single digits  
     
 PrintCD(second());    
    
    
 Serial.print('W');  
 Serial.print(weekday());  // there are no double digits only 7 days in a week  
    
 Serial.print('D');  
 PrintZD(day());      // Print the Day of the month and add zero before single digits   
                 
    
 Serial.print('M');    // add zero before single digit month numbers   
 PrintZD(month());  
    
 Serial.print('Y');  
 Serial.print(year());   
   
}   
     
   
*/  
   
   
   
   
//**********************//**********************//**********************//*****  
   
//Function for digital clock display (in the SERIAL MONITOR  *** FOR HUMAN ***    
     
//**********************//**********************//**********************//*****   
     
     
   
   
void TimeDateDisplayTwo() // digital clock display of the time 24hr format // for HUM-an  
{  
    
 Serial.println("****>> 10 second timer<< ****");   
    
 Serial.println("TIME");                  
    
 PrintZD(hour());   
     
 PrintCD(minute());   
     
 PrintCD(second());   
     
 Serial.println();  
    
 Serial.println("DATE");   
     
 Serial.print(dayStr(weekday()));   
     
 Serial.print("-");   
   
     
 Serial.print(day());   
    
 Serial.print("-");   
    
 Serial.print(monthStr(month()));   
   
 Serial.print("-");   
   
 Serial.println(year());   
   
}   
   
   
   
//***********************************************************************  
//** Function for adding Zero before single digits before Serial print **  
//***********************************************************************  
   
void PrintZD(int D)    
   
{   
   if(D < 10)     // don't add brackets for this if statement it will not work  
    
     
    Serial.print('0');  
    
    Serial.print(D);   
     
   
}   
   
//*********************************************************************************  
//** Function for adding a Colon & Zero before single digits before Serial print **  
//*********************************************************************************  
    
 void PrintCD(int digits)   
 {   
  Serial.print(":");   
   
   if (digits < 10)  // don't add brackets for this if statement it will not work  
              
   Serial.print('0');   
   
   Serial.print(digits);   
    
   
}   
    
    
    
    
    
//******************************   
//    THE END   
//******************************