Arduino MEGA 2560 + ESP8266 (ESP-01) Home Automation
You can watch DHT11 data (Humidity and Temperature), IR Flame Sensor, MQ-4 Natural Gas Sensor, HC-SR501 PIR Motion Dedector and control 4 Channel Relay Module over internet/network with Android App. We use ESP8266-01 WiFi module for wireless comminication.
Required Main Parts
- Arduino MEGA 2560 (Rev3)
- ESP8266-01 WiFi module (If you need update your ESP8266 Firmware please check ESP8266 Firmware update page)
- DHT11 Humidity and Temperature sensor
- IR Flame Sensor
- MQ-4 Natural Gas Sensor
- HC-SR501 PIR Motion Dedector
- 4 Channel Relay Module
- Any Android device
Project Details
We use ESP8266-01 WiFi module for wireless comminication.
We need two libraries for read DHT11:
DHT Sensor Library: https://github.com/adafruit/DHT-sensor-library
Adafruit Unified Sensor Lib: https://github.com/adafruit/Adafruit_Sensor
We need WiFiEspAT library for ESP-01 module:
WiFiEspAT: https://github.com/jandrassy/WiFiEspAT
We need ArduinoJson library for serialize Json data:
ArduinoJson: https://arduinojson.org/
You can install all these libraries from Library Manager in your Arduino IDE
We use external DC power adaptor for Arduino and power circuit for sensors, 4 Channel Relay Module and ESP-01 module. We use Arduino mega 2560 r3 proto shield for power circuit and ESP-01 module.
Shopping List
Amount | Part Type |
---|---|
2 | 100nF/16V Ceramic Capacitor |
1 | 1000μF/16V Electrolytic Capacitor |
1 | 100μF/16V Electrolytic Capacitor |
1 | 7805 5V Voltage Regulator |
1 | LD1117 3.3V Voltage Regulator |
1 | Female Header |
Power Circuit
Shopping List
Amount | Part Type |
---|---|
1 | Arduino Mega 2560 (Rev3) |
1 | 4 Channel Relay Module |
1 | 1N4148 Diode |
1 | DHT11 Temperature & Humidity Sensor Module |
1 | HC-SR501 Motion Sensor Module |
1 | IR Flame Sensor Module |
1 | MQ-4 Natural Gas Sensor Module |
1 | ESP8266 (ESP-01) WiFi Module |
1 | 10kΩ Resistor |
1 | Pushbutton |
Circuit
Code (arduino_secrets.h)
#define SECRET_SSID "SSID" // Your SSID
#define SECRET_PASS "SSIDPASS" // Your SSID Password
Code (HomeAutomation.ino)
/**********************************************************************
* For projects details and circuit scheme please visit: *
* https://www.arduinoclub.net/arduinomega-2560-home-automation.html *
*********************************************************************/
// Include WiFiEspAT library
#include <WiFiEspAT.h>
// Include EEPROM library
#include <EEPROM.h>
// Include SSID information (arduino_secrets.h) file
#include "arduino_secrets.h"
// Include Adafruit DHT11 Sensor Library
#include "DHT.h"
// DHT11 pin
#define DHTPIN 6
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
// ArduinoJson
#include <ArduinoJson.h>
StaticJsonDocument<150> doc;
// Don't change from here. Please edit from arduino_secrets.h file
const char ssid[] = SECRET_SSID; // Your SSID (use arduino_secrets.h for change)
const char pass[] = SECRET_PASS; // Your SSID Password (use arduino_secrets.h for change)
// Password for connection requests. You can change your connection password from this variable.
char* password = "1234";
// Relay pins
int relays[] = {NULL, 2, 3, 4, 5};
// HC-SR501 PIR Sensor pin
int hcSr501 = 7;
int motionState = 0;
int EepromMotionState;
// Flame sensor pin
int flameSensor = A0;
int flameState = 0;
int EepromFlameState;
// The limit value that the FLAME sensor will define as flame (max value: 1023)
int flamethreshold = 200;
// MQ-4 gas sensor pin
int gasSensor = A1;
int gasValue = 0;
int EepromGasState;
// Limit value that the MQ-4 gas sensor will define as a gas leak (max value: 1023)
int gasthreshold = 390;
String answer = "";
int bodyFinder = 0;
char requestBody[100];
int count;
int rState;
boolean rlrequest = false;
boolean getallrequest = false;
#if defined(ARDUINO_ARCH_AVR) && !defined(HAVE_HWSERIAL1)
#include
SoftwareSerial Serial1(12, 13); // RX, TX
#define AT_BAUD_RATE 9600
#else
#define AT_BAUD_RATE 115200
#endif
WiFiServer server(80);
void setup() {
// The final position of the relays is adjusted by reading from the EEPROM.
for (count = 1; count <= 4; count++) {
rState = EEPROM.read(count);
pinMode(count+1, OUTPUT);
if (rState == 1) {
onOff(count, "ON", false);
} else {
onOff(count, "OFF", false);
}
}
pinMode(hcSr501, INPUT);
pinMode(flameSensor, INPUT);
pinMode(gasSensor, INPUT);
Serial.begin(115200);
while (!Serial);
// Serial for ESP8266 initializing
setEspBaudRate(AT_BAUD_RATE);
WiFi.init(Serial1);
dht.begin();
if (WiFi.status() == WL_NO_MODULE) {
Serial.println(F("ESP8266 not found"));
// Operation discontinued because ESP8266 could not be found
while (true);
}
// Connect / reconnect to WiFi network
int status = WiFi.begin(ssid, pass);
Serial.println(F("Trying to connect to SSID: "));
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print('.');
}
Serial.println();
// ESP8266 server starting
server.begin();
IPAddress ip = WiFi.localIP();
Serial.println();
Serial.println(F("WiFi network connected."));
Serial.print(F("To send a request to the server use \"http://"));
Serial.print(ip);
Serial.println(F("/\" Link."));
}
void loop() {
// Checking for an HTTP request
WiFiClient client = server.available();
if (client) {
IPAddress ip = client.remoteIP();
Serial.print(F("New client: "));
Serial.println(ip);
Serial.println(F("--> Request data"));
while (client.connected()) {
if (client.available()) {
// Set variables values to 0
memset(requestBody, 0, sizeof requestBody);
bodyFinder = 0;
while (client.available()) {
char c = client.read();
Serial.write(c);
if (bodyFinder != 4) {
if (c == '\r' || c == '\n') { // r or n
bodyFinder ++;
} else {
bodyFinder = 0;
}
}
if (bodyFinder == 4 && c != '\n') {
strncat(requestBody, &c, 1);
}
}
Serial.println();
Serial.println(F("--> POST data received:"));
Serial.println(requestBody);
// We divide our POST data received with the strtok() function from the first & character and load it into our token variable
char* token = strtok(requestBody, "&");
// Checking whether the first 5 characters are equal to the pass = expression (Parameter) in the received POST request.
if (strncmp(token, "pass=", 5) == 0) {
// It is the password in the POST request received after the first 5 characters in the token variable (ie after pass =) This password is transferred to the PWD variable
char* PWD = token + 5;
// Checking the correctness of the password received with the pass parameter in the request.
if (strcmp(PWD, password) == 0) {
Serial.println(F("--> PASSWORD CORRECT"));
while (token != NULL) {
token = strtok(NULL, "&");
// Röle
if (strncmp(token, "rl=", 3) == 0) {
rlrequest = true;
if (getallrequest == false) {
Serial.print(F("--> rl REQUEST Relay number: "));
int rlNumber = atol(token + 3);
Serial.print(rlNumber);
Serial.print(F(" Command: "));
char* rlCommand = token + 4;
Serial.println(rlCommand);
onOff(rlNumber, rlCommand, true);
answer = "";
doc["status"] = F("OK");
doc["rl"] = (String)rlNumber;
doc["rlcommand"] = (String)rlCommand;
serializeJson(doc, answer);
}
}
// getall
if (strncmp(token, "getall", 6) == 0) {
getallrequest == true;
if (rlrequest == false) {
Serial.println(F("--> getall REQUEST"));
answer = "";
// DHT11 sensor data reading
// Temperature in Celsius
float t = dht.readTemperature();
char str_t[6];
dtostrf(t, 4, 2, str_t);
// Nem
float h = dht.readHumidity();
char str_h[6];
dtostrf(h, 4, 2, str_h);
// HC-SR501 PIR sensor data is read from address 7 of EEPROM:
EepromMotionState = EEPROM.read(7);
// FLAME sensor data read from address 8 of EEPROM:
EepromFlameState = EEPROM.read(8);
// GAS sensor data is read from EEPROM at address 9:
EepromGasState = EEPROM.read(9);
doc["status"] = F("OK");
doc["temperature"] = (String)t;
doc["humidity"] = (String)h;
doc["gas"] = EepromGasState;
doc["flame"] = EepromFlameState;
doc["motion"] = EepromMotionState;
// Relays location 1.2.3.4 of the EEPROM. Reading from addresses:
// Creating Json array named relays
JsonArray relays = doc.createNestedArray("relays");
for (count = 1; count <= 4; count++) {
rState = EEPROM.read(count);
relays.add(rState);
}
serializeJson(doc, answer);
// If the last recorded MQ-4 gas sensor data at the 9th address of the EEPROM is 1, that is, gas is detected, this data is now converted to 0 because it is transmitted to the client..
if (EepromGasState == 1) {
EEPROM.update(9, 0);
}
// If the last recorded PIR sensor data to the 7th address of EEPROM is 1, that is, motion is detected, this data is converted to 0 because it is transmitted to the client.
if (EepromMotionState == 1) {
EEPROM.update(7, 0);
}
// If the last recorded FLAME sensor data at the 8th address of EEPROM is 1, that is, flame is detected, this data is converted to 0 because it is transmitted to the client.
if (EepromFlameState == 1) {
EEPROM.update(8, 0);
}
}
}
}
} else {
Serial.println(F("--> PASSWORD INCORRECT"));
answer = "";
doc["status"] = F("ERROR");
doc["message"] = F("Password Incorrect");
serializeJson(doc, answer);
}
} else {
Serial.println(F("--> pass parameter not sent"));
answer = "";
doc["status"] = F("ERROR");
doc["message"] = F("pass parameter not sent");
serializeJson(doc, answer);
}
// When the end of the HTTP header is reached (a blank line),
// It means that the HTTP request has reached the end, a response is sent to the request at this stage
Serial.println(F("--> Forwarded reply"));
Serial.println(answer);
// http answer headers
client.println(F("HTTP/1.1 200 OK"));
client.println(F("Content-Type: application/json; charset=UTF-8"));
client.println(F("Connection: close")); // Client is notified that the connection will be closed after the completion of the response
client.println();
client.print(answer);
client.flush();
rlrequest = false;
getallrequest == false;
doc.clear();
break;
}
}
// close connection:
client.stop();
Serial.println(F("--> Client connection closed"));
}
// HC-SR501 PIR sensor data reading
motionState = digitalRead(hcSr501);
// Reading the last record at address 7 of the EEPROM
EepromMotionState = EEPROM.read(7);
// If the sensor has not detected a motion
if (motionState == 0) {
// If the last record at the 7th address of the EEPROM is 1, the data in the EEPROM is not converted to 0 because this data has not yet been received by the client.
if (EepromMotionState != 1) {
EEPROM.update(7, motionState);
}
} else {
if (EepromMotionState != 1) {
EEPROM.update(7, motionState);
}
}
// FLAME sensor data reading
flameState = analogRead(flameSensor);
// Reading the last record at address 8 of the EEPROM
EepromFlameState = EEPROM.read(8);
// If the sensor did not detect a flame
if (flameState > flamethreshold) {
// If the last record in the 8th address of the EEPROM is 1, the data in the EEPROM is not converted to 0 because this data has not yet been received by the client.
if (EepromFlameState != 1) {
EEPROM.update(8, 0);
}
} else {
if (EepromFlameState != 1) {
EEPROM.update(8, 1);
}
}
// MQ-4 Gas sensor data reading
gasValue = analogRead(gasSensor);
// Reading the last record at address 9 of the EEPROM
EepromGasState = EEPROM.read(9);
// If the value read from the sensor is equal to or higher than the limit value
if (gasValue >= gasthreshold) {
if (EepromGasState != 1) {
EEPROM.update(9, 1);
}
} else { // If the reading is below the limit value
// If the last record at the 9th address of the EEPROM is 1, the data in the EEPROM is not converted to 0 because this data has not yet been received by the client.
if (EepromGasState != 1) {
EEPROM.update(9, 0);
}
}
}
// This function sets the Baudrate of ESP8266
// Serial1 is set to 115200 if available, and 9600 with SoftwareSerial if not available.
void setEspBaudRate(unsigned long baudrate) {
long rates[6] = {115200, 74880, 57600, 38400, 19200, 9600};
Serial.print(F("Set ESP8266 baudrate to: "));
Serial.print(baudrate);
Serial.println(F("..."));
for (int i = 0; i < 6; i++) {
Serial1.begin(rates[i]);
delay(100);
Serial1.print(F("AT+UART_DEF="));
Serial1.print(baudrate);
Serial1.print(F(",8,1,0,0\r\n"));
delay(100);
}
Serial1.begin(baudrate);
}
// Relay ON/OFF function
void onOff(int relayNumber, String position, boolean updateEeprom) {
if (position == "ON") {
digitalWrite(relays[relayNumber], LOW);
if (updateEeprom == true) {
EEPROM.update(relayNumber, 1);
}
}
if (position == "OFF") {
digitalWrite(relays[relayNumber], HIGH);
if (updateEeprom == true) {
EEPROM.update(relayNumber, 0);
}
}
}