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();
}
No comments:
Post a Comment