Overview
This project involves a Home Automation System using the ESP8266 Wi-Fi module. It allows the control of lights, the garage door, and other home appliances over a web interface that can be accessed via a Wi-Fi Access Point created by the system itself. The project also uses a DHT11 sensor to monitor temperature and humidity, sending the data to a server for display.
Key Features:
- Wi-Fi Access Point Creation: The system does not connect to a home router for safety reasons but instead creates its own Access Point to isolate the home network from potential security risks.
- Web-based Control Interface: Users can control lights and the garage door through a simple web interface. The interface includes buttons to turn individual lights on or off and control the garage door.
- Automatic Porch Light Control: Based on the light intensity outside, the porch light is turned on automatically at night or turned off during the day. DHT11 Sensor for Temperature and Humidity Monitoring: The system uses a DHT11 sensor to monitor temperature and humidity, and displays the current readings on the web page.
- Simple User Interface: The project incorporates the use of HTML and CSS to display an intuitive user interface, complete with icons representing different rooms, devices, and states of the home.
Hardware Components
- ESP8266 Wi-Fi Module: Central to the project, used for networking and web server capabilities.
- Servo Motor: Attached to the garage door for opening and closing it.
- DHT11 Sensor: Used to measure the humidity and temperature inside the house.
- Lights (LEDs): Used to simulate lights in various rooms.
- Relay (optional): Can be used to control high-power devices such as actual home lights and garage doors.
Software Components
Libraries Used:
- ESP8266WiFi.h: To enable Wi-Fi functionality and create an Access Point.
- ESP8266WebServer.h: To manage HTTP requests and serve web pages.
- Servo.h: To control the servo motor for the garage door.
- DHT.h: To interact with the DHT11 temperature and humidity sensor.
- ESP8266HTTPClient.h: To send HTTP requests with the sensor data.
Detailed Explanation of Code
Wi-Fi Access Point Setup
The ESP8266 creates its own Access Point with the following credentials:
const char *ssid = "Home-Automation-225";
const char *password = "Anjena225";
- SSID is the name of the network.
- Password ensures only authorized devices can connect to it.
A custom IP configuration is used for the server, ensuring the system can be accessed via a known IP address:
IPAddress ip(1, 2, 3, 4);
IPAddress gateway(1, 2, 3, 1);
IPAddress subnet(255, 255, 255, 0);
Web Server and Control Interface
The system uses two web servers:
- WiFiServer webServer(80): Handles the main control page.
- ESP8266WebServer webServerSensors(8080): Handles temperature and humidity readings sent from the DHT11 sensor. HTML Interface:
The web page includes icons and buttons for controlling different devices in the house. For example, the living room light can be toggled on/off using these commands:
if (header.indexOf("GET /living/light/on") >= 0) {
livingLightState = "on";
digitalWrite(livingLight, HIGH);
}
else if (header.indexOf("GET /living/light/off") >= 0) {
livingLightState = "off";
digitalWrite(livingLight, LOW);
}
Each room’s light and the garage door have similar commands, and a table is used to display the current state along with control buttons.
Servo Motor Control (Garage Door)
The garage door is controlled using a servo motor. The position of the door is adjusted to 0 degrees for closed and 90 degrees for open:
garageDoorMotor.write(0); // close
garageDoorMotor.write(90); // open
Light Dependent Resistor (LDR)
The LDR measures light intensity, controlling the porch light:
ldrValue = analogRead(A0); // read the LDR value
if (ldrValue < 50) {
// If it's dark, turn on the porch light
digitalWrite(porchLight, HIGH);
}
Temperature and Humidity Monitoring
The system uses a DHT11 sensor to monitor the temperature and humidity. It reads values from the sensor and sends them to the web server via an HTTP request:
float hTemp = dht.readHumidity();
float tTemp = dht.readTemperature(true);
This data is then displayed on the web page alongside control buttons.
Automation Logic for Air Conditioning (AC)
The project controls an air conditioner (simulated with a built-in LED), turning it on if the temperature exceeds 80°F:
if(tempf > 80) {
digitalWrite(ac, LOW); // AC ON
}
Overview of HTML UI
The HTML UI serves as the front-end for controlling and monitoring the home automation system. It is displayed in a web browser when a user connects to the ESP8266 access point. The page refreshes every 5 seconds to show the latest status of the devices.
Key Components of the HTML UI
HTML Structure:
- The UI starts with the
<!DOCTYPE html>
declaration, which defines it as an HTML5 document. - The
<html>
,<head>
, and<body>
tags organize the structure of the page.
Viewport Meta Tag:
<meta name="viewport" content="width=device-width, initial-scale=1">
- This tag ensures the page is responsive, adjusting to different screen sizes, which is essential for usability on mobile devices.
Auto-refresh:
<meta http-equiv="refresh" content="5; url=http://1.2.3.4">
- The page automatically refreshes every 5 seconds, allowing real-time updates without needing a manual refresh.
CSS Styling:
<style>
html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center; }
.button { background-color: #195B6A; border: none; color: white; padding: 4px 10px; width: 80px; text-decoration: none; font-size: 20px; margin: 2px; cursor: pointer; }
.button2 {background-color: #77878A;}
.bigbutton { background-color: #195B6A; border: none; color: white; padding: 4px 10px; width: 300px; text-decoration: none; font-size: 20px; margin: 2px; cursor: pointer; }
.bigbutton2 {background-color: #77878A;}
</style>
- The CSS styles define the appearance of the page, including font styles, button sizes, and colors, enhancing the user experience.
Page Title and Header:
client.println("<body>");
client.println(house);
client.println("<font size=\"6\">Home Automation</font>");
client.println("<br/>");
client.println("<font size=\"4\"><strong>by Anjena Raja, Grade 5</strong></font>");
client.println("<br/>");
client.println("<font size=\"4\"><strong>Room 225, Mrs. Carr</strong></font>");
- This section introduces the application with a title and some identification of the creator, making the UI more personalized and informative.
Device Status and Controls:
- The UI displays the status of various devices (lights and garage door) in a table format. Each device’s current state and control buttons (ON/OFF or OPEN/CLOSE) are included:
client.println("<table align=\"center\" cellpadding=\"3\">");
- The table structure organizes the information clearly, making it easy for users to view and interact with the controls.
- Dynamic Status Updates: Each device’s state is dynamically updated based on the conditions defined in the code. For example:
if (livingLightState=="off")
{
client.println("<td>" + lightOff + "</td>");
client.println("<td><a href=\"/living/light/on\"><button class=\"button\">ON</button></a></td>");
}
else
{
client.println("<td>"+ lightOn + "</td>");
client.println("<td><a href=\"/living/light/off\"><button class=\"button button2\">OFF</button></a></td>");
}
- This conditional structure allows for different buttons to be displayed based on the current state of each light.
Light Control Buttons:
- There are also buttons to control all lights at once:
client.println("<td colspan=\"5\"><a href=\"/all/light/on\"><button class=\"bigbutton\">ALL LIGHTS ON</button></a></td>");
client.println("<td colspan=\"5\"><a href=\"/all/light/off\"><button class=\"bigbutton bigbutton2\">ALL LIGHTS OFF</button></a></td>");
- These buttons provide a convenient way to control multiple devices with a single click.
Environmental Sensors:
- The UI also displays readings from the temperature and humidity sensors:
client.print("<p>Temp: " + temperature.substring(0,4) + "℉ Humidity: " + humidity.substring(0,2) + "% A/C: ");
- This information is crucial for monitoring the environment and managing the air conditioning system.
Home Automation System Code
/*
* Home Automation System
* by
* Anjena Raja, Grade 5, Room 225, Mrs. Carr
* This project is for my Genius Hour submission
*
*/
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <Servo.h>
// I am creating my own WiFi Access Point and so I do not not need to connect to my home router for safety
// - any security problem in my home automation project will not compromise our internet security
// Access Point's name or SSID (Service Set IDentifier)
const char *ssid = "Home-Automation-225";
// Access Point's password
const char *password = "Anjena225";
// This is my web server and it has to listen for connections from browsers on port 80 for HTTP (Hyper Text Transfer Protocol)
WiFiServer webServer(80);
ESP8266WebServer webServerSensors(8080);
// html header
String header;
// variables to store the current state of lights and doors
String livingLightState = "off";
String anjenaLightState = "off";
String parentsLightState = "off";
String garageDoorState = "close";
// variables for GPIO pins
const int livingLight = 5;
const int anjenaLight = 4;
const int parentsLight = 14;
const int garageDoor = 3;
const int porchLight = 1;
const int ac = BUILTIN_LED;
// icons
String house = "<font size=\"7\">🏡</font>";
String world = "<font size=\"5\">🌎</font>";
String sun = "<font size=\"5\">🌝</font>";
String moon = "<font size=\"5\">🌚</font>";
String cloud = "<font size=\"5\">🌗</font>";
String light = "<font size=\"5\">💡</font>";
String lightOn = "<font size=\"4\">🔵</font>";
String lightOff = "<font size=\"4\">⊗</font>"; //🔴
String door = "<font size=\"5\">🚪</font>";
String doorOpen = "<font size=\"5\">🔓</font>";
String doorLocked = "<font size=\"5\">🔒</font>";
String living = "<font size=\"6\">👪</font>";
String parents = "<font size=\"6\">👫</font>";
String anjena = "<font size=\"6\">🐈</font>";
String garage = "<font size=\"6\">🚗</font>";
String thermometer = "<font size=\"5\">🌡</font>";
String hygrometer = "<font size=\"5\">🌢</font>";
String acOn = "<font size=\"5\">🐧</font>";
String acOff = "<font size=\"5\">🐥</font>";
// this is used to measure the light intensity
// the value is used for displaying icons and to turn on the porch light
int ldrValue;
// this is used to open and close the garage door
Servo garageDoorMotor;
void setup()
{
// initialize pins of micro controller
pinMode(livingLight, OUTPUT);
pinMode(anjenaLight, OUTPUT);
pinMode(parentsLight, OUTPUT);
pinMode(porchLight, OUTPUT);
pinMode(ac, OUTPUT);
// turn off lights
digitalWrite(livingLight, LOW);
digitalWrite(anjenaLight, LOW);
digitalWrite(parentsLight, LOW);
digitalWrite(porchLight, LOW);
// keep door closed
garageDoorMotor.attach(garageDoor);
delay(500);
garageDoorMotor.write(0);
delay(500);
garageDoorMotor.detach();
//keep AC off
digitalWrite(ac, HIGH);
// this is the IP (Internet Protocol) address of my web server
IPAddress ip(1,2,3,4);
// this is the address of my gateway
// this is the end point and all communications stop at this address
IPAddress gateway(1,2,3,1);
IPAddress subnet(255,255,255,0);
// configure the access point's ip and gateway
WiFi.softAPConfig(ip, gateway, subnet);
// we need to secure the access point so that unauthorized users cannot connect to it
WiFi.softAP(ssid, password);
// start the web server
webServer.begin();
webServerSensors.on("/feed", handle_feed);
webServerSensors.begin();
}
// Handling the /feed page from my server
String temperature ="-";
String humidity ="-";
void handle_feed()
{
temperature = webServerSensors.arg("temp");
humidity = webServerSensors.arg("hum");
webServerSensors.send(200, "text/plain", "Home automation system: Message received.");
}
void loop()
{
// Listen for incoming clients
webServerSensors.handleClient();
WiFiClient client = webServer.available();
if (client)
{
// If a new client connects
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected())
{
// loop while the client's connected
if (client.available())
{
// if there's bytes to read from the client,
char c = client.read(); // read a byte, then
header += c;
if (c == '\n')
{
// if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0)
{
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
// turns the GPIOs on and off
if (header.indexOf("GET /living/light/on") >= 0)
{
livingLightState = "on";
digitalWrite(livingLight, HIGH);
}
else if (header.indexOf("GET /living/light/off") >= 0)
{
livingLightState = "off";
digitalWrite(livingLight, LOW);
}
else if (header.indexOf("GET /anjena/light/on") >= 0)
{
anjenaLightState = "on";
digitalWrite(anjenaLight, HIGH);
}
else if (header.indexOf("GET /anjena/light/off") >= 0)
{
anjenaLightState = "off";
digitalWrite(anjenaLight, LOW);
}
else if (header.indexOf("GET /parents/light/on") >= 0)
{
parentsLightState = "on";
digitalWrite(parentsLight, HIGH);
}
else if (header.indexOf("GET /parents/light/off") >= 0)
{
parentsLightState = "off";
digitalWrite(parentsLight, LOW);
}
if (header.indexOf("GET /all/light/on") >= 0)
{
livingLightState = "on";
anjenaLightState = "on";
parentsLightState = "on";
digitalWrite(livingLight, HIGH);
digitalWrite(anjenaLight, HIGH);
digitalWrite(parentsLight, HIGH);
}
else if (header.indexOf("GET /all/light/off") >= 0)
{
livingLightState = "off";
anjenaLightState = "off";
parentsLightState = "off";
digitalWrite(livingLight, LOW);
digitalWrite(anjenaLight, LOW);
digitalWrite(parentsLight, LOW);
}
else if (header.indexOf("GET /garage/door/close") >= 0)
{
garageDoorState = "close";
garageDoorMotor.attach(garageDoor);
delay(500);
garageDoorMotor.write(0);
delay(500);
garageDoorMotor.detach();
}
else if (header.indexOf("GET /garage/door/open") >= 0)
{
garageDoorState = "open";
garageDoorMotor.attach(garageDoor);
delay(500);
garageDoorMotor.write(90);
delay(500);
garageDoorMotor.detach();
}
// Display the HTML web page
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<meta http-equiv=\"refresh\" content=\"5; url=http://1.2.3.4\">");
//client.println("<link rel=\"icon\" href=\"data:,\">");
// CSS to style the on/off buttons
client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".button { background-color: #195B6A; border: none; color: white; padding: 4px 10px; width: 80px; ");
client.println("text-decoration: none; font-size: 20px; margin: 2px; cursor: pointer;}");
client.println(".button2 {background-color: #77878A;}");
client.println(".bigbutton { background-color: #195B6A; border: none; color: white; padding: 4px 10px; width: 300px; ");
client.println("text-decoration: none; font-size: 20px; margin: 2px; cursor: pointer;}");
client.println(".bigbutton2 {background-color: #77878A;}</style></head>");
// Web Page Heading
client.println("<body>");
client.println(house);
client.println("<font size=\"6\">Home Automation</font>");
client.println("<br/>");
client.println("<font size=\"4\"><strong>by Anjena Raja, Grade 5</strong></font>");
client.println("<br/>");
client.println("<font size=\"4\"><strong>Room 225, Mrs. Carr</strong></font>");
// Display the outside lighting condition
ldrValue = analogRead(A0); // read analog input pin 0
if (ldrValue > 150)
{
// sunny
client.println("<p>Sun Light: " + sun + " Porch Light: " + lightOff + "</p>");
digitalWrite(porchLight, LOW);
}
else if (ldrValue > 50)
{
// cloudy
client.println("<p>Sun Light: " + cloud + " Porch Light: " + lightOff + "</p>");
digitalWrite(porchLight, LOW);
}
else
{
// night
client.println("<p>Sun Light: " + moon + " Porch Light: " + lightOn + "</p>");
digitalWrite(porchLight, HIGH);
}
client.println("<table align=\"center\" cellpadding=\"3\">");
// Display current state, and ON/OFF buttons for livingLight
client.println("<tr>");
client.println("<td>" + light + "</td>");
client.println("<td>Living</td>");
client.println("<td>" + living + "</td>");
// If the livingLightState is off, it displays the ON button
if (livingLightState=="off")
{
client.println("<td>" + lightOff + "</td>");
client.println("<td><a href=\"/living/light/on\"><button class=\"button\">ON</button></a></td>");
}
else
{
client.println("<td>"+ lightOn + "</td>");
client.println("<td><a href=\"/living/light/off\"><button class=\"button button2\">OFF</button></a></td>");
}
client.println("</tr>");
// Display current state, and ON/OFF buttons for anjenaLight
client.println("<tr>");
client.println("<td>" + light + "</td>");
client.println("<td>Anjena</td>");
client.println("<td>" + anjena + "</td>");
// If the anjenaLightState is off, it displays the ON button
if (anjenaLightState=="off")
{
client.println("<td>" + lightOff + "</td>");
client.println("<td><a href=\"/anjena/light/on\"><button class=\"button\">ON</button></a></td>");
}
else
{
client.println("<td>"+ lightOn + "</td>");
client.println("<td><a href=\"/anjena/light/off\"><button class=\"button button2\">OFF</button></a></td>");
}
client.println("</tr>");
// Display current state, and ON/OFF buttons for parentsLight
client.println("<tr>");
client.println("<td>" + light + "</td>");
client.println("<td>Parents</td>");
client.println("<td>" + parents + "</td>");
// If the parentsLightState is off, it displays the ON button
if (parentsLightState=="off")
{
client.println("<td>" + lightOff + "</td>");
client.println("<td><a href=\"/parents/light/on\"><button class=\"button\">ON</button></a></td>");
}
else
{
client.println("<td>"+ lightOn + "</td>");
client.println("<td><a href=\"/parents/light/off\"><button class=\"button button2\">OFF</button></a></td>");
}
client.println("</tr>");
// Display current state, and CLOSE/OPEN buttons for garageDoor
client.println("<tr>");
client.println("<td>" + door + "</td>");
client.println("<td>Garage</td>");
client.println("<td>" + garage + "</td>");
// If the garageDoorState is off, it displays the CLOSE button
if (garageDoorState=="open")
{
client.println("<td>" + doorOpen + "</td>");
client.println("<td><a href=\"/garage/door/close\"><button class=\"button button2\">CLOSE</button></a></td>");
}
else
{
client.println("<td>"+ doorLocked + "</td>");
client.println("<td><a href=\"/garage/door/open\"><button class=\"button\">OPEN</button></a></td>");
}
client.println("</tr>");
// one easy button to turn on/off all lights inside the house
client.println("<tr>");
client.println("<td colspan=\"5\"><a href=\"/all/light/on\"><button class=\"bigbutton\">ALL LIGHTS ON</button></a></td>");
client.println("</tr>");
client.println("<tr>");
client.println("<td colspan=\"5\"><a href=\"/all/light/off\"><button class=\"bigbutton bigbutton2\">ALL LIGHTS OFF</button></a></td>");
client.println("</tr>");
client.println("</table>");
//Display the inside temperature
client.print("<p>Temp: " + temperature.substring(0,4) + "℉ Humidity: " + humidity.substring(0,2) + "% A/C: ");
float tempf = temperature.toFloat();
if (isnan(tempf))
{
client.print(acOff);
}
else
{
if(tempf > 80)
{
digitalWrite(ac, LOW);
client.print(acOn);
}
else
{
digitalWrite(ac, HIGH);
client.print(acOff);
}
}
client.println("</p>");
client.println("</body></html>");
// The HTTP response ends with another blank line
client.println();
// Break out of the while loop
break;
}
else
{ // if you got a newline, then clear currentLine
currentLine = "";
}
}
else if (c != '\r')
{ // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// Clear the header variable
header = "";
// Close the connection
client.stop();
}
}
Remote Temperature Sensor Code
// client
#include <DHT.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#define DHTTYPE DHT11
// DHT Sensor
const int DHTPin = 5;
// Initialize DHT sensor.
DHT dht(DHTPin, DHTTYPE);
// Access Point's name or SSID (Service Set IDentifier)
const char *ssid = "Home-Automation-225";
// Access Point's password
const char *password = "Anjena225";
// Local ESP web-server address
String serverHost = "http://1.2.3.4:8080/feed";
String data;
float h;
float t;
// Static network configuration
IPAddress ip(1, 2, 3, 201);
IPAddress gateway(1, 2, 3, 1);
IPAddress subnet(255, 255, 255, 0);
WiFiClient client;
void setup()
{
dht.begin();
WiFi.mode(WIFI_STA);
WiFi.config(ip, gateway, subnet);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
}
Serial.begin(115200);
}
void loop()
{
readDHTSensor();
buildDataStream();
sendHttpRequest();
// wait for 5 seconds
delay(5000);
}
void readDHTSensor()
{
float hTemp = dht.readHumidity();
float tTemp = dht.readTemperature(true);
if(!isnan(tTemp))
{
t = tTemp;
}
if (!isnan(hTemp))
{
h = hTemp;
}
}
void buildDataStream()
{
data = "temp=";
data += String(t);
data += "&hum=";
data += String(h);
}
void sendHttpRequest()
{
HTTPClient http;
http.begin(serverHost);
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
http.POST(data);
http.end();
Serial.println(data);
}