Day by day IoT devices are increasing. Because it gives you comfort, You can literally control any device from anywhere. You just need an internet connection or at least you should be on same Wi-Fi network. It is very convenient to do simple task like turn ON light or OFF light with our smart phone. You can build your own IoT home automation with this tutorial. You may want to build a IoT project for college, school or university. In this tutorial we will see how to make ESP8266 web server which will control LED. We can control LED from any web browser on laptop, PC or Mobile phone by using same WiFi network. Once you learned this you will not only able to control LED you can literally control anything from light, fan, AC to big machines in factory. So lets get started.

For making this project you will need,

  1. NodeMCU ESP8266 12E,
  2. 220 ohms Resistor,
  3. LED,
  4. Breadboard,
  5. Jumper Wire.

If you haven’t setup your Arduino IDE for ESP8266. Please go to tutorial: How to setup NodeMCU ESP8266 for first time in Arduino IDE. Then come back to this tutorial.

Control LED with ESP8266 web server

Do connection as shown in diagram for controlling LED from ESP8266 Web Server.

Code:

Don’t upload the to Arduino IDE. You have to make some changes, so it will works for you. First you need to insert your SSID and Password. i.e Wi-Fi network name and Password. After uploading code go to serial monitor to see IP Address so that you can control your LED. If in serial monitor you can’t see anything. Press reset button on NodeMCU ESP8266. Now you can see IP Address.

#include <ESP8266WiFi.h>

// Enter your wifi network name and Wifi Password
const char* ssid = "Your SSID";
const char* password = "Your Password";

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

// These variables store current output state of LED
String outputRedState = "off";
String outputGreenState = "off";
String outputYellowState = "off";

// Assign output variables to GPIO pins
const int redLED = 2;
const int greenLED = 4;
const int yellowLED = 5;

// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0; 
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;

void setup() {
Serial.begin(115200);
// Initialize the output variables as outputs
pinMode(redLED, OUTPUT);
pinMode(greenLED, OUTPUT);
pinMode(yellowLED,OUTPUT);
// Set outputs to LOW
digitalWrite(redLED, LOW);
digitalWrite(greenLED, LOW);
digitalWrite(yellowLED, LOW);

// Connect to Wi-Fi network with SSID and password
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Print local IP address and start web server
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
}

void loop(){
WiFiClient client = server.available(); // Listen for incoming clients

if (client) { // If a new client connects,
Serial.println("New Client."); // print a message out in the serial port
String currentLine = ""; // make a String to hold incoming data from the client
currentTime = millis();
previousTime = currentTime;
while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected
currentTime = millis(); 
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
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 /2/on") >= 0) {
Serial.println("RED LED is on");
outputRedState = "on";
digitalWrite(redLED, HIGH);
} else if (header.indexOf("GET /2/off") >= 0) {
Serial.println("RED LED is off");
outputRedState = "off";
digitalWrite(redLED, LOW);
} else if (header.indexOf("GET /4/on") >= 0) {
Serial.println("Green LED is on");
outputGreenState = "on";
digitalWrite(greenLED, HIGH);
} else if (header.indexOf("GET /4/off") >= 0) {
Serial.println("Green LED is off");
outputGreenState = "off";
digitalWrite(greenLED, LOW);
} else if (header.indexOf("GET /5/on") >= 0) {
Serial.println("Yellow LED is on");
outputYellowState = "on";
digitalWrite(yellowLED, HIGH);
} else if (header.indexOf("GET /5/off") >= 0) {
Serial.println("Yellow LED is off");
outputYellowState = "off";
digitalWrite(yellowLED, LOW);
}

// 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("<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(".buttonRed { background-color: #ff0000; border: none; color: white; padding: 16px 40px; border-radius: 60%;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".buttonGreen { background-color: #00ff00; border: none; color: white; padding: 16px 40px; border-radius: 60%;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".buttonYellow { background-color: #feeb36; border: none; color: white; padding: 16px 40px; border-radius: 60%;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".buttonOff { background-color: #77878A; border: none; color: white; padding: 16px 40px; border-radius: 70%;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}</style></head>");

// Web Page Heading
client.println("<body><h1>My LED Control Server</h1>");

// Display current state, and ON/OFF buttons for GPIO 2 Red LED 
client.println("<p>Red LED is " + outputRedState + "</p>");
// If the outputRedState is off, it displays the OFF button 
if (outputRedState=="off") {
client.println("<p><a href=\"/2/on\"><button class=\"button buttonOff\">OFF</button></a></p>");
} else {
client.println("<p><a href=\"/2/off\"><button class=\"button buttonRed\">ON</button></a></p>");
} 

// Display current state, and ON/OFF buttons for GPIO 4 Green LED 
client.println("<p>Green LED is " + outputGreenState + "</p>");
// If the outputGreenState is off, it displays the OFF button 
if (outputGreenState =="off") {
client.println("<p><a href=\"/4/on\"><button class=\"button buttonOff\">OFF</button></a></p>");
} else {
client.println("<p><a href=\"/4/off\"><button class=\"button buttonGreen\">ON</button></a></p>");
}
client.println("</body></html>");

// Display current state, and ON/OFF buttons for GPIO 5 Yellow LED 
client.println("<p>Yellow LED is " + outputYellowState + "</p>");
// If the outputYellowState is off, it displays the OFF button 
if (outputYellowState =="off") {
client.println("<p><a href=\"/5/on\"><button class=\"button buttonOff\">OFF</button></a></p>");
} else {
client.println("<p><a href=\"/5/off\"><button class=\"button buttonYellow\">ON</button></a></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();
Serial.println("Client disconnected.");
Serial.println("");
}
}
Code Explanation:

First thing add ESP8266WiFi library.

#include <ESP8266WiFi.h>

Modify this with your WiFi name and Password.

const char* ssid = "Your SSID";
const char* password = "Your Password";

Now we want to store current output state of LEDs. If you want to add more output you can add more variable.

String outputRedState = "off";
String outputGreenState = "off";
String outputYellowState = "off";

Assigning LED pins to GPIOs.

const int redLED = 2;
const int greenLED = 4;
const int yellowLED = 5;

Initializing LED as a OUTPUT and set them LOW. When code uploaded, LED will be off by default.

pinMode(redLED, OUTPUT);
pinMode(greenLED, OUTPUT);
pinMode(yellowLED,OUTPUT);
digitalWrite(redLED, LOW);
digitalWrite(greenLED, LOW);
digitalWrite(yellowLED, LOW);

These lines will try to connect on provided SSID and password, in every 500 millisecond.

Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

When it gets connected, it will print IP address in serial monitor. From this IP address we can control LED. We just need to type this IP address in any web browser and we can see our ESP8266 web server page.

Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();

ESP8266 is always listening incoming clients in loop

WiFiClient client = server.available();

When request receive from client, it will store data from client and print that to serial monitor. Don’t edit this part of code.

if (client) { // If a new client connects,
Serial.println("New Client."); // print a message out in the serial port
String currentLine = ""; // make a String to hold incoming data from the client
currentTime = millis();
previousTime = currentTime;
while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected
currentTime = millis();
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
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();

This section of code will check which button is pressed on your web page and turn LED ON or OFF. For example if you press on RED LED button, URL changes to IP address followed by 2/on, it will also print “RED LED is on” in serial monitor. If you want to add more button, you can add code here.

if (header.indexOf("GET /2/on") >= 0) {
Serial.println("RED LED is on");
outputRedState = "on";
digitalWrite(redLED, HIGH);
} else if (header.indexOf("GET /2/off") >= 0) {
Serial.println("RED LED is off");
outputRedState = "off";
digitalWrite(redLED, LOW);
} else if (header.indexOf("GET /4/on") >= 0) {
Serial.println("Green LED is on");
outputGreenState = "on";
digitalWrite(greenLED, HIGH);
} else if (header.indexOf("GET /4/off") >= 0) {
Serial.println("Green LED is off");
outputGreenState = "off";
digitalWrite(greenLED, LOW);
} else if (header.indexOf("GET /5/on") >= 0) {
Serial.println("Yellow LED is on");
outputYellowState = "on";
digitalWrite(yellowLED, HIGH);
} else if (header.indexOf("GET /5/off") >= 0) {
Serial.println("Yellow LED is off");
outputYellowState = "off";
digitalWrite(yellowLED, LOW);
}

Displaying web page, which is responsive in any browser either you are on desktop or on mobile.

client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");

Now we are using CSS to style the buttons, you can change here fonts, colors, size etc.

client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".buttonRed { background-color: #ff0000; border: none; color: white; padding: 16px 40px; border-radius: 60%;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".buttonGreen { background-color: #00ff00; border: none; color: white; padding: 16px 40px; border-radius: 60%;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".buttonYellow { background-color: #feeb36; border: none; color: white; padding: 16px 40px; border-radius: 60%;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".buttonOff { background-color: #77878A; border: none; color: white; padding: 16px 40px; border-radius: 70%;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}</style></head>");

This line is just heading in web page

client.println("<body><h1>My LED Control Server</h1>");

Current state of LED will be printed in web server page.

client.println("<p>Red LED is " + outputRedState + "</p>");

if Red LED state is ON it will change button color and print “OFF” inside button.

if (outputRedState=="off") {
client.println("<p><a href=\"/2/on\"><button class=\"button buttonOff\">OFF</button></a></p>");
} else {
client.println("<p><a href=\"/2/off\"><button class=\"button buttonRed\">ON</button></a></p>");
}

header variable will be cleared and stop connection with client.

// Clear the header variable
header = "";
// Close the connection
client.stop();
Serial.println("Client disconnected.");
Serial.println("");

Till then Keep Learning Keep Making.