/*****
_____ _ _ _
/ ____| (_) | (_)
| (___ _ __ _ _ __ _ _| |_ _ __ ___
\___ \| '_ \| | '__| | | | | | '_ \ / _ \
____) | |_) | | | | |_| | | | | | | (_) |
|_____/| .__/|_|_| \__,_|_|_|_| |_|\___/
| |
|_|
v 1.1 4-8-2021
Emilio Roscini
*****/
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include <EEPROM.h>
// GPIO where the DS18B20 is connected to
const int oneWireBus = 4;
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);
// Pass our oneWire reference to Dallas Temperature sensor
DallasTemperature sensors(&oneWire);
// Temperature value
float temp;
// Uncomment one of the lines bellow for whatever DHT sensor type you're using!
#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
//#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
// Change the credentials below, so your ESP8266 connects to your router
const char* ssid = "ami";
const char* password = "chokurei";
// Change the variable to your Raspberry Pi IP address, so it connects to your MQTT broker
const char* mqtt_server = "192.168.43.24";
// 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);
// DHT Sensor - GPIO 5 = D1 on ESP-12E NodeMCU board
const int DHTPin = 5;
// Lamp - LED - GPIO 4 = D2 on ESP-12E NodeMCU board
const int pump = 12;
const int espled1 = 16;
const int espled2 = 2;
const int rele2 = 13;
const int rele3 = 14;
// Initialize DHT sensor.
DHT dht(DHTPin, DHTTYPE);
// Variables timers
int aCceso = 0;
int sPento = 0;
int naCceso = 0;
int nsPento = 0;
int tEmpo = 60000;
// Timers auxiliar variables
long now = millis();
long Measure = 0;
long lastMeasure = 0;
long ultimaMeasure = 0;
long lampo = 0;
long lampino = 0;
// Variables pump
char* pOmpa = "Spenta";
int Pompa = 0;
int sTato = 0;
int vrele2 = 0;
int vrele3 = 0;
// Variables light
char* cIelo = "Notte";
int cOndizione = 0;
float voltage;
bool pIng = LOW;
bool tras = LOW;
// Don't change the function below. This functions connects your ESP8266 to your router
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("WiFi connected - ESP IP address: ");
Serial.println(WiFi.localIP());
}
// This functions is executed when some device publishes a message to a topic that your ESP8266 is subscribed to
// Change the function below to add logic to your program, so when a device publishes a message to a topic that
// your ESP8266 is subscribed you can actually do something
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();
lampino = millis();
digitalWrite(espled2, LOW);
tras = LOW;
// Convert on off mqtt command to boolean variable
if(topic=="room/pump"){
Serial.print("La pompa é ");
if(messageTemp == "on"){
EEPROM.put(10, 1);
EEPROM.commit();
sTato = 1;
Serial.print("On");
}
else if(messageTemp == "off"){
EEPROM.put(10, 0);
EEPROM.commit();
sTato = 0;
Serial.print("Off");
}
}
if(topic=="room/rele2"){
if(messageTemp == "on"){
EEPROM.put(2, 1);
EEPROM.commit();
vrele2 = 1;
}
else if(messageTemp == "off"){
EEPROM.put(2, 0);
EEPROM.commit();
vrele2 = 0;
}
}
if(topic=="room/rele3"){
if(messageTemp == "on"){
EEPROM.put(6, 1);
EEPROM.commit();
vrele3 = 1;
}
else if(messageTemp == "off"){
EEPROM.put(6, 0);
EEPROM.commit();
vrele3 = 0;
}
}
// Convert mqtt slide value to integer
if(topic=="room/timeron"){
aCceso = messageTemp.toInt();
EEPROM.put(14, aCceso);
EEPROM.commit();
Serial.print(aCceso);
}
if(topic=="room/timeroff"){
sPento = messageTemp.toInt();
EEPROM.put(18, sPento);
EEPROM.commit();
Serial.print(sPento);
}
if(topic=="room/ntimeron"){
naCceso = messageTemp.toInt();
EEPROM.put(22, naCceso);
EEPROM.commit();
Serial.print(naCceso);
}
if(topic=="room/ntimeroff"){
nsPento = messageTemp.toInt();
EEPROM.put(26, nsPento);
EEPROM.commit();
Serial.print(nsPento);
}
// Convert mqtt light level slide to integer
if(topic=="room/condizione"){
cOndizione = messageTemp.toInt();
EEPROM.put(30, cOndizione);
EEPROM.commit();
Serial.print(cOndizione);
}
Serial.println();
}
// This functions reconnects your ESP8266 to your MQTT broker
// Change the function below if you want to subscribe to more topics with your ESP8266
void reconnect() {
// Loop until we're reconnected
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");
digitalWrite(espled1, LOW);
// Subscribe or resubscribe to a topic
client.subscribe("room/pump");
client.subscribe("room/rele2");
client.subscribe("room/rele3");
client.subscribe("room/timeron");
client.subscribe("room/timeroff");
client.subscribe("room/ntimeron");
client.subscribe("room/ntimeroff");
client.subscribe("room/condizione");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
// The setup function sets your ESP GPIOs to Outputs, starts the serial communication at a baud rate of 115200
// Sets your mqtt broker and sets the callback function
// The callback function is what receives messages and actually controls the outputs
void setup() {
sensors.begin();
EEPROM.begin(256);
pinMode(pump, OUTPUT);
pinMode(rele2, OUTPUT);
pinMode(rele3, OUTPUT);
pinMode(espled1, OUTPUT);
pinMode(espled2, OUTPUT);
digitalWrite(espled1, HIGH);
digitalWrite(espled2, HIGH);
dht.begin();
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
vrele3 = EEPROM.read(6);
if (vrele3 == 1){
digitalWrite(rele3,HIGH);
}
if (vrele3 == 0){
digitalWrite(rele3,LOW);
}
vrele2 = EEPROM.read(2);
if (vrele2 == 1){
digitalWrite(rele2,HIGH);
}
if (vrele2 == 0){
digitalWrite(rele2,LOW);
}
sTato = EEPROM.read(10);
aCceso = EEPROM.read(14);
sPento = EEPROM.read(18);
naCceso = EEPROM.read(22);
nsPento = EEPROM.read(26);
cOndizione = EEPROM.read(30);
}
// For this project, you don't need to change anything in the loop function. Basically it ensures that you ESP is connected to your broker
void loop() {
if (!client.connected()) {
reconnect();
}
if(!client.loop())
client.connect("ESP8266Client");
vrele3 = EEPROM.read(6);
if (vrele3 == 1){
digitalWrite(rele3,HIGH);
}
if (vrele3 == 0){
digitalWrite(rele3,LOW);
}
vrele2 = EEPROM.read(2);
if (vrele2 == 1){
digitalWrite(rele2,HIGH);
}
if (vrele2 == 0){
digitalWrite(rele2,LOW);
}
now = millis();
if (tras == HIGH){
if (millis() - lampino > 300) {
pIng = LOW;
digitalWrite(espled2,HIGH);
}
}
if (pIng == HIGH){
if (millis() - lampo > 1000) {
pIng = LOW;
digitalWrite(espled2,HIGH);
}
}
// Night an day timers
sTato = EEPROM.read(10);
aCceso = EEPROM.read(14);
sPento = EEPROM.read(18);
naCceso = EEPROM.read(22);
nsPento = EEPROM.read(26);
if (sTato == 1){
if (cIelo == "Giorno") {
if ((millis() - ultimaMeasure) > (sPento*tEmpo)){
digitalWrite(pump,HIGH);
pOmpa = "Accesa";
Pompa = 1;
if ((millis() - ultimaMeasure - (sPento*tEmpo)) > (aCceso*tEmpo)) {
ultimaMeasure = millis();
digitalWrite(pump,LOW);
pOmpa = "Spenta";
Pompa = 0;
}
}
}
if (cIelo == "Notte") {
if ((millis() - Measure) > (nsPento*tEmpo)){
digitalWrite(pump,HIGH);
pOmpa = "Accesa";
Pompa = 1;
if ((millis() - Measure - (nsPento*tEmpo)) > (naCceso*tEmpo)) {
Measure = millis();
digitalWrite(pump,LOW);
pOmpa = "Spenta";
Pompa = 0;
}
}
}
}
// Publishes new temperature and humidity every 30 seconds
if (now - lastMeasure > 10000) {
lastMeasure = now;
pIng = HIGH;
lampo = millis();
digitalWrite(espled2,LOW);
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h = dht.readHumidity();
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
float f = dht.readTemperature(true);
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t) || isnan(f)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
// Read light level and decide if its night or day
int sensorValue = analogRead(A0); // read the input on analog pin 0
float voltage = sensorValue * (100.0 / 1023.0); // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V)
cOndizione = EEPROM.read(30);
if (voltage >= cOndizione) {
cIelo = "Giorno";
}
if (voltage < cOndizione) {
cIelo = "Notte";
}
// Computes temperature values in Celsius
float hic = dht.computeHeatIndex(t, h, false);
static char temperatureTemp[7];
dtostrf(hic, 6, 2, temperatureTemp);
// Uncomment to compute temperature values in Fahrenheit
// float hif = dht.computeHeatIndex(f, h);
// static char temperatureTemp[7];
// dtostrf(hif, 6, 2, temperatureTemp);
static char humidityTemp[7];
dtostrf(h, 6, 2, humidityTemp);
// New temperature readings
sensors.requestTemperatures();
// Temperature in Celsius degrees
temp = sensors.getTempCByIndex(0);
// Convert integer to string
static char inTemp[7];
dtostrf(temp, 6, 2, inTemp);
static char diLux[7];
dtostrf(voltage, 6, 2, diLux);
static char poMpin[7];
dtostrf(Pompa, 6, 2, poMpin);
static char ACceso[7];
dtostrf(aCceso, 6, 2, ACceso);
static char SPento[7];
dtostrf(sPento, 6, 2, SPento);
static char NACceso[7];
dtostrf(naCceso, 6, 2, NACceso);
static char NSPento[7];
dtostrf(nsPento, 6, 2, NSPento);
static char COndizione[7];
dtostrf(cOndizione, 6, 2, COndizione);
// Publishes values
client.publish("room/temperature", temperatureTemp);
client.publish("room/humidity", humidityTemp);
client.publish("room/intemp", inTemp);
client.publish("room/lux", diLux);
client.publish("room/stato", pOmpa);
client.publish("room/cielo", cIelo);
client.publish("room/pompa", poMpin);
if (vrele2 == 1){
client.publish("room/ferele2", "on");
}
if (vrele2 == 0){
client.publish("room/ferele2", "off");
}
if (vrele3 == 1){
client.publish("room/ferele3", "on");
}
if (vrele3 == 0){
client.publish("room/ferele3", "off");
}
if (sTato == 1){
client.publish("room/festato", "on");
}
if (sTato == 0){
client.publish("room/festato", "off");
}
client.publish("room/feacceso", ACceso);
client.publish("room/fespento", SPento);
client.publish("room/fenacceso", NACceso);
client.publish("room/fenspento", NSPento);
client.publish("room/fecondizione", COndizione);
Serial.print("Humidity: ");
Serial.print(h);
Serial.print(" %\t Temperature: ");
Serial.print(t);
Serial.print(" *C ");
Serial.print(f);
Serial.print(" *F\t Heat index: ");
Serial.print(hic);
Serial.print(" *C ");
Serial.print(temp);
Serial.print(" *C in");
Serial.print(" Luminositá:");
Serial.print(voltage);
Serial.print(" la pompa é ");
Serial.print(pOmpa);
Serial.print(" é di ");
Serial.println(cIelo);
Serial.println(ACceso);
Serial.println(aCceso);
}
}