Wednesday, November 11, 2020

Home Automation Step-3

 I  have successfully controlled four relays via WIFI using Node-Red Dashboard and got data from DHT11 sensor and display data on OLED as well as save data on  on Raspbery Pi.

 #include <WiFi.h>           //wifi library
  #include <Wire.h>
  #include <NTPClient.h>      //Network time protocl
  #include <PubSubClient.h>   //
  #include <Adafruit_GFX.h>
  #include <Adafruit_SSD1306.h>
  #include <Adafruit_Sensor.h>
  #include "DHT.h"            // DHT library
  #include "Time_a.h"  
  #include <TimeLib.h>        // unix time libray  
  #include <cppQueue.h>
    

//// Change the credentials below, so your ESP32 connects to your router
//const char* ssid = "Dialog 4G";
//const char* password = "YJNHQ102RD8";
//// Change the variable to your Raspberry Pi IP address, so it connects to your MQTT broker
//const char* mqtt_server = "192.168.0.105";
 
  const char* ssid = "AndroidAP";
  const char* password = "sema9444";
  const char* mqtt_server = "192.168.0.105";

// Initializes the espClient. You should change the espClient name if you have multiple ESPs running in your home automation system
  WiFiClient espClient;
  PubSubClient client(espClient);
 
/////////// Define NTP Client to get time///////////////////////////////////////
  WiFiUDP ntpUDP;
  NTPClient timeClient(ntpUDP);
  time_t et;

  #define DHTPIN 26         // DHT sensor connected to pin 26
  #define DHTTYPE DHT11     // there are two types DHT11 and DHT22
  #define timeSeconds 10    // dealy for PIR motion
  #define SCREEN_WIDTH 128  // OLED display width, in pixels
  #define SCREEN_HEIGHT 64  // OLED display height, in pixels
  #define IMPLEMENTATION  FIFO
  #define queue_size 3000
  #define OVERWRITE true


DHT       dht(DHTPIN, DHTTYPE);
float     dht11_hum, dht11_temp;
unsigned long  t;        //unix time
unsigned long  ts;        //unix time

uint32_t  count=0;

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
const int           lamp2 = 17; // lamp2 - LED - GPIO 17 on ESP32 board
const int           lamp3 = 5 ; // Lamp - Room
const int           lamp1 = 14; // lamp1==PIR out // Set GPIOs for lamp1 and PIR Motion Sensor
const int           fan   = 15; // fan GPIO2 for fan
const int mqttInterrupt   = 12; // Interrupt GPIO for PIR mtion sensor trigger input
const int mqttInterruptL2 = 13; // interrrupt GPIO for Lamp2
const int mqttInterruptL3 = 27; // interrrupt GPIO for Lamp2
const int mqttInterruptFan= 4;
boolean toggle            = false;
boolean toggle1           = false;
boolean toggle2           = false;
int status = WL_IDLE_STATUS;   // the Wifi radio's status
int len =0;
char mqtt_msg[35];
int counter =0;

// Timer: Auxiliary variables for pir
unsigned long now_delay = millis();
unsigned long lastTrigger = 0;
boolean startTimer = false;


//////////////////////////////////////////////////////////////////////////////////////////////////////////
       typedef struct strRec {
                  float  t;
                  float     dht11_temp;
                  float     dht11_hum;
                } Rec;

                //Rec = rec.dht11_temp;
                
                
       Queue q(sizeof(Rec), queue_size, IMPLEMENTATION,OVERWRITE); // Instantiate queue
   

/////////////////////QUEUE/////////////////////////////////////////////////////////////////
void subscribeToLamps(){
      client.subscribe("room/lamp1");
      client.subscribe("room/lamp2");
      client.subscribe("room/lamp3");
      client.subscribe("room/pir");
      client.subscribe("room/fan");
    }
    
////////////////put data in a queue if no wifi or server //////////////////////////////////   
void putInQueue (){
      
      for (int i=0; i<6; i++){
      
      dht11_hum  = dht.readHumidity();    // humidity         
      dht11_temp = dht.readTemperature(); // temp             
      t          = now();                 // time stamp   
      
      Rec rec;
      rec.t       = t;
      rec.dht11_temp = dht11_temp;
      rec.dht11_hum = dht11_hum;
      q.push(&rec);
 
      delay(10000);
      len=q.getCount();  // read the queue length
     
      Serial.print(len); //
      Serial.print(" ");}//
  }

/////////////////publish all queue data collected due to wifi or server unavalability///////
void pubQueue(){
 
      len=q.getCount();
      for(len ;len>0; len--){
      Rec rec;
      q.pop(&rec);
//      Serial.print(rec.t); Serial.print(" ");
//      Serial.print(rec.dht11_temp); Serial.print(" ");
//      Serial.print(rec.dht11_hum); Serial.print(" --> ");
//      Serial.println(len);

      sprintf(mqtt_msg,"%u %2.0f %2.1f",t,dht11_hum,dht11_temp);
      //client.connect("mel5405-2018AE03");
      client.publish("TopicName/dht11",mqtt_msg);
      Serial.print(mqtt_msg);Serial.print(" --> ");
      Serial.println(len);
      //delay(5000);
      delay(300);

    //////////////////// DHT11 HUM /////////////////  
      sprintf(mqtt_msg,"%u %2.4f",t,dht11_hum);
      client.connect("localhost"); // change here
      client.publish("TopicName/humidity", mqtt_msg);  // change here
      delay(500);
    
    /////////////////////// DHT11 TEMP /////////////////    
      sprintf(mqtt_msg,"%u %2.4f",t,dht11_temp);
      client.connect("localhost"); // change here
      client.publish("TopicName/temp", mqtt_msg);   // change here
      delay(500);
      
     }
     len=0;
 }

//////////////////////collect data and save in queue and then dend all at once ////////////
void putInQueuePubToMqtt(){
    for (int i=0; i<5; i++){
      
      dht11_hum  = dht.readHumidity();    // humidity         
      dht11_temp = dht.readTemperature(); // temp             
      t          = now();                 // time stamp   
      
      Rec rec;
      rec.t       = t;
      rec.dht11_temp = dht11_temp;
      rec.dht11_hum = dht11_hum;
      q.push(&rec);
      delay(10000);}
    
    len=q.getCount();
    if(len%5==0){
      for(len ;len>0; len--){
      Rec rec;
      q.pop(&rec);
      Serial.print(rec.t);
      Serial.print(" ");
      Serial.print(rec.dht11_temp);
      Serial.print(" ");
      Serial.print(rec.dht11_hum);
      Serial.print(" ");
      Serial.println(len);

      sprintf(mqtt_msg,"%u %2.2f %2.2f",rec.t,rec.dht11_temp,rec.dht11_hum);
      client.connect("mel5405-2018AE03");
      client.publish("TopicName/dht11",mqtt_msg);
      Serial.println(mqtt_msg);
      delay(500);
      
      sprintf(mqtt_msg," %2.2f",rec.dht11_temp);
      client.connect("mel5405-2018AE03");
      client.publish("TopicName/temp",mqtt_msg);
      Serial.println(mqtt_msg);
      delay(500);



//      sprintf(mqtt_msg," %2.2f",rec.dht11_hum);
//      client.connect("mel5405-2018AE03");
//      client.publish("TopicName/hum",mqtt_msg);
//      Serial.println(mqtt_msg);
//      delay(500);
  //  delay(5000);
      
  //  delay(300);
     }
     len=0;
    }
  }

///////////////////// try 20s to connect wifi /////////////////////////////////////////
void connect_wifi(){
            int count=0;
            Serial.print("Connecting to ");
            Serial.println(ssid);
            WiFi.begin(ssid, password);

            while (WiFi.status() != WL_CONNECTED) {
            delay(500);
            Serial.print(".");
            count ++;
            if (count>40)break;}

            if (count<40){
            Serial.println("");
            Serial.print("ESP32 is Connected to WiFi network with IP Address: ");
            Serial.println(WiFi.localIP());}
                       
            else {(Serial.print("No WiFi"));
               }
        }

/////////////////////set NTP time if internet is connected/////////////////////////////
void update_time(){
    
      ///////////////// time update///////////////////////////////////////////////////
       timeClient.begin();
       timeClient.setTimeOffset(19800); // GMT +5:30 = 19800
       while(!timeClient.update()) {
       timeClient.forceUpdate();
       delay(100);
       Serial.print("*");
       count ++;
       if (count>5)break;}
       if (count<5){
            Serial.println("");
            Serial.print("NTP time set: ");
            setTime(timeClient.getEpochTime());}  // update ESP32 time
       else {
            Serial.println(" ");
            Serial.println("Time not set");}
        if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
        Serial.println(F("SSD1306 allocation failed"));
        for(;;);}
        delay(100);
      }
      
///// Enable following interrupts //////////////////////////////////////////////////////
void IRAM_ATTR detectsMovement() {
  Serial.println("MOTION DETECTED!!!");
  digitalWrite(lamp1, LOW);
  startTimer = true;
  lastTrigger = millis();}
void IRAM_ATTR lamp2interrupt() {
  toggle=!toggle;
  Serial.println("Lamp2 interrupt");
  digitalWrite(lamp2, toggle );}
void IRAM_ATTR lamp3interrupt() {
  toggle1=!toggle1;
  Serial.println("Lamp3 interrupt");
  digitalWrite(lamp3, toggle1 );}
void IRAM_ATTR fanInterrupt() {
  toggle2=!toggle2;
  Serial.println("Fan interrupt");
  digitalWrite(fan, toggle2 );}

//////////////////////////////////////////////////////////////////////////////////////
void callback(String topic, byte* message, unsigned int length) {
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  String messageTemp;
 
  for (int i = 0; i < length; i++) {
    Serial.print((char)message[i]);
    messageTemp += (char)message[i];
  }
  Serial.println();
 
  // If a message is received on the topic room/lamp3, you check if the message is
  // either on or off. Turns the lamp GPIO according to the message
 
  if(topic=="room/lamp3"){
      Serial.print("Room center lamp is ");
      if(messageTemp == "on"){
        digitalWrite(lamp3, HIGH);
        Serial.print("On");
      }
      else if(messageTemp == "off"){
        digitalWrite(lamp3, LOW);
        Serial.print("Off");
      }
  }
  Serial.println();
 
  // If a message is received on the topic room/lamp2, you check if the message is
  // either on or off. Turns the lamp GPIO according to the message
 
  if(topic=="room/lamp2"){
      Serial.print("Room outside lamp is ");
      if(messageTemp == "on"){
        digitalWrite(lamp2, HIGH);
        Serial.print("On");
      }
      else if(messageTemp == "off"){
        digitalWrite(lamp2, LOW);
        Serial.print("Off");
      }
  }
  Serial.println();
 
  // If a message is received on the topic room/pir, you check if the message is
  // either on or off. Turns the lamp GPIO according to the message
 
  if(topic=="room/pir"){
      Serial.print("PIR DETECTED ");
      if(messageTemp == "on"){
        digitalWrite(lamp1, HIGH);
        Serial.print("PIR On");
      }
      else if(messageTemp == "off"){
        digitalWrite(lamp1, LOW);
        Serial.print("PIR Off");
      }
  }
  Serial.println();
 
  ////////////////////////////////////////////////////

    if(topic=="room/fan"){
      Serial.print("Room fan is ");
      if(messageTemp == "on"){
        digitalWrite(fan, HIGH);
        Serial.print("On");
      }
      else if(messageTemp == "off"){
        digitalWrite(fan, LOW);
        Serial.print("Off");
      }
  }
  Serial.println();
    
}

///////////////////////////////////////////////////////////////////////////////////////
void reconnect() {
  // Loop until we're reconnected; (while loop) removed
  while(!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    /*
     YOU MIGHT NEED TO CHANGE THIS LINE, IF YOU'RE HAVING PROBLEMS WITH MQTT MULTIPLE CONNECTIONS
     To change the ESP device ID, you will have to give a new name to the ESP8266.
     Here's how it looks:
       if (client.connect("ESP8266Client")) {
     You can do it like this:
       if (client.connect("ESP1_Office")) {
     Then, for the other ESP:
       if (client.connect("ESP2_Garage")) {
      That should solve your MQTT multiple connections problem
    */
    if (client.connect("ESP8266Client")) {
      Serial.println("connected");
      len=q.getCount();  // check the que lenght
       Serial.println(len);
      if(len>0){         // if queue length is graterthan 0 publish all
                Serial.println("QUEUE DATA DUE TO MQTT IS NOT AVALABLE ");
                pubQueue ();
                Serial.println("QUEUE DATA DUE TO MQTT IS NOT AVALABLE IS FINISHED");
             }
      // Subscribe or resubscribe to a topic
      // You can subscribe to more topics (to control more LEDs in this example)
      client.subscribe("room/pir");
      client.subscribe("room/lamp2");
      client.subscribe("room/lamp3");
      client.subscribe("room/fan");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(2000);
      Serial.println("DATA WILL WRITE TO QUEUE TILL MQTT SERVER IS CONNECTED");
      putInQueue();
    }
  }
}

///////////////////////////////Display data on OLED //////////////////////////////////
void display_oled(){
  display.clearDisplay();
 
 /////////// display temperature////////////////////////////////
  display.setTextSize(1);
  display.setCursor(0,0);
  display.print("Temperature: ");
  display.setTextSize(2);
  display.setCursor(0,10);
  display.print(dht11_temp);
  display.print(" ");
  display.setTextSize(1);
  display.cp437(true);
  display.write(167);
  display.setTextSize(2);
  display.print("C");
 
 /////// display humidity//////////////////////////////////////
  display.setTextSize(1);
  display.setCursor(0, 35);
  display.print("Humidity: ");
  display.setTextSize(2);
  display.setCursor(0, 45);
  display.print(dht11_hum);
  display.print(" %");
 
  display.display();
    }

/////////////////////SETUP////////////////////////////////////////////////////////////
void setup() {
   Serial.begin(115200);
//////////////////////////OLED SETUP ///////////////////////////////////////
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);}
    delay(2000);
    display.clearDisplay();
    display.setTextColor(WHITE);
//////////////////////////////////////////////////////////////////////////////////////
  connect_wifi();
 // setup_wifi();
  update_time ();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  dht.begin();          // Start the DHT11 sensor
 
////////////// PIR Motion Sensor mode INPUT_PULLUP//////////////////////////////////////
  pinMode(mqttInterrupt, INPUT_PULLUP);
  pinMode(mqttInterruptL2, INPUT_PULLUP);
  pinMode(mqttInterruptL3, INPUT_PULLUP);
  pinMode(mqttInterruptFan, INPUT_PULLUP);  
 
///////// Set mqttInterrupt pin as interrupt, assign interrupt function and set RISING mode
  attachInterrupt(digitalPinToInterrupt(mqttInterrupt), detectsMovement, RISING);
  attachInterrupt(digitalPinToInterrupt(mqttInterruptL2), lamp2interrupt, RISING);
  attachInterrupt(digitalPinToInterrupt(mqttInterruptL3), lamp3interrupt, RISING);
  attachInterrupt(digitalPinToInterrupt(mqttInterruptFan), fanInterrupt, RISING);
 
////////////// Set lamps to OFF at beginig //////////////////////////////////////////
  pinMode(lamp1, OUTPUT);
  digitalWrite(lamp1, HIGH);
  pinMode(lamp2, OUTPUT);
  digitalWrite(lamp2, HIGH);
  pinMode(lamp3, OUTPUT);
  digitalWrite(lamp3, HIGH);  
  pinMode(fan, OUTPUT);
  digitalWrite(fan, HIGH);
}

/////////////////////MQTT PUBLISH/////////////////////////////////////////////////////
void mqtt_publish(){
/////////////////////////send time stamp///////////////////////
  sprintf(mqtt_msg,"%u",t);
  client.connect("localhost"); // change here
  client.publish("TopicName/timestamp", mqtt_msg);  // change here
//  Serial.print(mqtt_msg);
//  Serial.print(" ");
  delay(500);

//////////////////// DHT11 HUM /////////////////  
  sprintf(mqtt_msg,"%u %2.4f",t,dht11_hum);
  client.connect("localhost"); // change here
  client.publish("TopicName/humidity", mqtt_msg);  // change here
  delay(500);
 
  sprintf(mqtt_msg,"%2.4f",dht11_hum);
  client.connect("localhost"); // change here
  client.publish("TopicName/humidityOnly", mqtt_msg);  // change here
  delay(500);

/////////////////////// DHT11 TEMP /////////////////    
  sprintf(mqtt_msg,"%u %2.4f",t,dht11_temp);
  client.connect("localhost"); // change here
  client.publish("TopicName/temp", mqtt_msg);   // change here
  delay(500);

  sprintf(mqtt_msg,"%2.4f",dht11_temp);
  client.connect("localhost"); // change here
  client.publish("TopicName/tempOnly", mqtt_msg);   // change here
  delay(500);
 
////////////////////////////all in one line///////////////////////////////////////////
  sprintf(mqtt_msg,"%u %2.4f %2.4f",t,dht11_temp,dht11_hum);
  //client.connect("mel5405-2018AE03"); // change here
  client.publish("TopicName/dht11", mqtt_msg);   // change here
  Serial.println(mqtt_msg);
  delay(2000);
}

//////////////////////////////////////////////////////////////////////////////////////
void loop() {
 
 if(WiFi.status()==WL_CONNECTION_LOST){
      Serial.println("wifi CONNECTION_LOST, Data Write to Queue");
      putInQueue();
      connect_wifi();
              if(WiFi.status()==WL_CONNECTED){
                Serial.println("Queue data due to CONNECTION_LOST");
                pubQueue ();
                Serial.println("Queue data due to CONNECTION_LOST is finished");}   
              }

    if(WiFi.status()==WL_NO_SSID_AVAIL){
      Serial.println("wifi NO_SSID_AVAIL, Data Write to Queue");
      putInQueue();
      connect_wifi();
              if(WiFi.status()==WL_CONNECTED){
                Serial.println("Queue data due to WL_NO_SSID_AVAIL");
                pubQueue ();
                Serial.println("Queue data due to WL_NO_SSID_AVAIL is finished");}   
              }

    if(WiFi.status()==WL_DISCONNECTED){
      Serial.println("wifi DISCONNECTED, Data Write to Queue");
      putInQueue();
      connect_wifi();
              if(WiFi.status()==WL_CONNECTED){
                Serial.println("Queue data due to WL_DISCONNECTED");
                pubQueue ();
                Serial.println("Queue data due to WL_DISCONNECTED is finished");
                }   
              }
 
 /////////////////////if WIFI connected /////////////////////////////////////////////
  if (!client.connected()){
        reconnect();}
  if(!client.loop())
    client.connect("");
    
///////////////////////////delay for data collection //////////////////////////////////////////////////////////
  counter=counter+1;
  if (counter>5000){
     dht11_hum  = dht.readHumidity();    // humidity         
     dht11_temp = dht.readTemperature(); // temp             
     t          = now();                 // time stamp   
    // t          =t*1000;
     mqtt_publish();
     //////////////////////////unix time convert and serial print  /////////////////
     // Serial.print(t);  // https://arduino.stackexchange.com/questions/38765/convert-to-and-from-unix-timestamp
     printf("DATA RECIVED AT : %4d-%02d-%02d %02d:%02d:%02d\n", year(t), month(t), day(t), hour(t), minute(t), second(t));
     counter=0;
    }

/////////////////////////////////////////////////////////////////////////////////////
   display_oled();
//////////////////////////For PIR///////////////////////////////////////////////////////
// Current time to calculate deyay for PIR
   now_delay = millis();
// Turn off the lamp1(PIRlamp) after the number of seconds defined in the timeSeconds variable
if(startTimer && (now_delay - lastTrigger > (timeSeconds*1000))) {
   Serial.println("Motion stopped...");
   digitalWrite(lamp1, HIGH);       // lamp off when out put set to high
   startTimer = false;
  }

////////During sleep switch interrupt can't use ///////////////////////////////////
//  esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 0);
//  esp_sleep_enable_timer_wakeup(20000000);  
//  esp_light_sleep_start();
}

 

 

 

 

 

Download Eagle file

Download NodeRed file 

No comments:

Search This Blog