Blog
SuperKitz.com Project Manual
Wifi Controlled Web-switch for lights,fan,appliances. DIY Kit
ESP8266 Web Server that controls two outputs (two LEDs)
This project is to build a standalone ESP8266 Web Server that controls two outputs (two LEDs). This ESP8266 NodeMCU Web Server is mobile responsive and it can be accessed with any device with a browser in your local network.
Requirements :
● Computer with an internet connection
● Download and install Arduino IDE
Components
NodeMCU ESp8266
Breadboard
Single channel relay Module
Jumper wires
9v battery and clip
Hardware
Getting
Started with
Web Switch ESP8266
NodeMCU ESP8266
NodeMCU is an open-source Lua based firmware and development board specially targeted for IoT based applications.It includes firmware that runs on the ESP8266 Wi-Fi SoC from Espressif Systems and hardware which is based on the ESP-12 module.
Pin out diagram
ESP8266
Single-channel Relay Module
The Single Channel Relay The module is a convenient board which can be used to control high voltage, a high current load such as motor, solenoid valves, lamps, and AC load. It is designed to interface with microcontrollers such as Arduino, PIC and etc. … It also comes with a LED to indicate the status of the relay.
Circuit Diagram
Wire up the Relay Module
With ESP8266
Wire up the Relay Module
- Relay VCC -> NodeMCU Vcc
- Relay GND -> NodeMCU GND
- Relay Signal -> (GPIO5) or D1 of NodeMCU
PROGRAMMING
Getting started with Arduino
Before starting any project, you need to get your Arduino talking to your computer. This allows you to write and compile code for the Arduino to execute, as well as providing a way for your Arduino to work alongside your computer.
Installing The Arduino Software Package On Windows
Head over to the Arduino website / superkitzs.com and download a version of the Arduino software suitable for your version of Windows. Once downloaded, follow the instructions to install the Arduino Integrated Development Environment (IDE).
In order to upload code to the ESP8266 and use the serial console, connect any data-capable micro USB cable to ESP8266 IOT Board and the other side to your computer’s USB port.
The new version NodeMCUv1.0 comes with the CP2102 serial chip, you can download (also provided with the kit) and install the driver from https://www.silabs.com/products/development-tools/…. The NodeMCUv0.9 comes with the CH340 serial chip, you can download and install the driver from: https://github.com/nodemcu/nodemcu-devkit/tree/mas…
Install NodeMCU Package for Arduino IDE (Online)
Copy the .json link with the latest stable release of NodeMCU package from Superkits.com.
The link should look something like this:
http://arduino.esp8266.com/stable/package_esp8266com_index.json
Paste the copied link and insert it in Arduino IDE using the following sequence->File menu -> Preferences-> Paste copied link into the area shown in the black box in the above image. Close and restart the Arduino IDE.
Tools -> Boards manager and search for ESP8266 and install the libraries/files given under the heading ESP8266 by ESP community.
Restart the Arduino IDE once again.
Scroll down, select the ESP8266 board menu and install “esp8266 by ESP8266 Community”, as shown in the figure below.
If you used the Installer, Windows – from XP up to 10 –
- Delete the Documents -> Arduino -> Libraries to remove all your libraries.
- Delete the User -> AppData -> Local -> Arduino15 folder to remove all the preferences.
- Uninstall Arduino IDE.
- Install a fresh one.
If you used the -Mac OX from –
First of all, make sure to log into your Mac with an administrator account, or you will be asked for a password when you try to delete something.
Open the Applications folder in the Finder (if it doesn’t appear in the sidebar, go to the Menu Bar, open the “Go” menu, and select Applications in the list), search for Arduino 1.6.4 application by typing its name in the search field, and then drag it to the Trash (in the dock) to begin the uninstall process. Alternatively you can also click on the Arduino 1.6.4 icon/folder and move it to the Trash by pressing Cmd + Del or choosing the File and Move to Trash commands.
Remove all components related to Arduino 1.6.4 in Finder
Though Arduino 1.6.4 has been deleted to the Trash, its lingering files, logs, caches and other miscellaneous contents may stay on the hard disk. For complete removal of Arduino 1.6.4, you can manually detect and clean out all components associated with this application. You can search for the relevant names using Spotlight. Those preference files of Arduino 1.6.4 can be found in the Preferences folder within your user’s library folder (~/Library/Preferences) or the system-wide Library located at the root of the system volume (/Library/Preferences/), while the support files are located in “~/Library/Application Support/” or “/Library/Application Support/”.
Open the Finder, go to the Menu Bar, open the “Go” menu, select the entry:|Go to Folder… and then enter the path of the Application Support folder:~/Library
Search for any files or folders with the program’s name or developer’s name in the ~/Library/Preferences/, ~/Library/Application Support/ and ~/Library/Caches/ folders. Right click on those items and click Move to Trash to delete them.
Scroll down, select the ESP8266 board menu and install “esp8266 by ESP8266 Community”, as shown in the figure below.
Go to Tools – Boards (scroll down the list of boards) – Select NodeMCU 1.0 (ESP-12EModule)
Select the Port number at which you have connected nodeMCU. The rest of the settings can be left to default values.
You need to modify the following two variables with your network credentials so that your ESP8266 can establish a connection with your router.
// Replace with your network credentials
const char* ssid = "";
const char* password = "";
Press CNTRL + A & press DELETE to clear the Arduino IDE page
Copy paste the code and click upload
Sketch Code
// Load Wi-Fi library
#include <ESP8266WiFi.h> /* library download link : https://www.superkitz.com/libraries/Arduino-master.zip */
// Replace with your network credentials
const char* ssid = "Your wifi ssid";
const char* password = "Your wifi password";
// Set webserver port number to 80
WiFiServer server(80);
// Variable to store the HTTP request
String header;
// Auxiliar variables to store the current output state
String output5State = "off";
String output4State = "off";
// Assign output variables to GPIO pins
const int output5 = D1;
const int output4 = D2;
// 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(output5, OUTPUT);
pinMode(output4, OUTPUT);
// Set outputs to LOW
digitalWrite(output5, LOW);
digitalWrite(output4, 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 /5/on") >= 0) {
Serial.println("GPIO 5 on");
output5State = "on";
digitalWrite(output5, HIGH);
} else if (header.indexOf("GET /5/off") >= 0) {
Serial.println("GPIO 5 off");
output5State = "off";
digitalWrite(output5, LOW);
} else if (header.indexOf("GET /4/on") >= 0) {
Serial.println("GPIO 4 on");
output4State = "on";
digitalWrite(output4, HIGH);
} else if (header.indexOf("GET /4/off") >= 0) {
Serial.println("GPIO 4 off");
output4State = "off";
digitalWrite(output4, 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
// Feel free to change the background-color and font-size attributes to fit your preferences
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: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".button2 {background-color: #77878A;}</style></head>");
// Web Page Heading
client.println("<body><h1>ESP8266 Web Server(SuperKits.com)</h1>");
// Display current state, and ON/OFF buttons for GPIO 5
client.println("<p>GPIO 5 - State " + output5State + "</p>");
// If the output5State is off, it displays the ON button
if (output5State=="off") {
client.println("<p><a href=\"/5/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/5/off\"><button class=\"button button2\">OFF</button></a></p>");
}
// Display current state, and ON/OFF buttons for GPIO 4
client.println("<p>GPIO 4 - State " + output4State + "</p>");
// If the output4State is off, it displays the ON button
if (output4State=="off") {
client.println("<p><a href=\"/4/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/4/off\"><button class=\"button button2\">OFF</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("");
}
}
Upload the program
Then, click the Upload button in the Arduino IDE and wait a few seconds until you see the message “Done uploading.” in the bottom left corner.
Testing the Web Server
Now, you can upload the code, and it will work straight away. Don’t forget to check if you have the right board and COM port selected, otherwise, you’ll get an error when trying to upload. Open the Serial Monitor at a baud rate of 115200.
Finding the ESP IP Address
Press the ESP8266 RESET button, and it will output the ESP IP address on the Serial Monitor
Copy that IP address, because you need it to access the webserver.
Accessing the Web Server
Open your browser, type the ESP IP address, and you’ll see the following page. This page is sent by the ESP8266 when you make a request on the ESP IP address.
If take a look at the serial monitor, you can see what’s going on in the background. The ESP receives an HTTP request from a new client – in this case, your browser.
You can also see other information about the HTTP request – these fields are called HTTP header fields and they define the operating parameters of an HTTP transaction.
Testing the Web Server
Let’s test the webserver. Click the button to turn GPIO 5 ON. The ESP receives a request on the /5/on URL and turns LED 5 ON.
The LED state is also updated on the web page.
Test GPIO 4 button and check that it works in a similar way.
How the Code Works
Now, let’s take a closer look at the code to see how it works, so that you are able to modify it to fulfill your needs. The first thing you need to do is to include the ESP8266WiFi library.
// Load Wi-Fi library
#include <ESP8266WiFi.h>
As mentioned previously, you need to insert your SSID and password in the following lines inside the double-quotes.
const char* ssid = "";
const char* password = "";
// Set web server port number to 80
WiFiServer server(80);
The following line creates a variable to store the header of the HTTP request:
String header;
Next, you create auxiliary variables to store the current state of your outputs. If you want to add more outputs and save its state, you need to create more variables.
// Auxiliar variables to store the current output state
String output5State = "off";
String output4State = "off";
You also need to assign a GPIO to each of your outputs. Here we are using GPIO 4 and GPIO 5 You can use any other suitable GPIOs.
// Assign output variables to GPIO pins
const int output5 = 5;
const int output4 = 4;
Setup()
Now, let’s go into the setup(). The setup() function only runs once when your ESP first boots.
First, we start a serial communication at a baud rate of 115200 for debugging purposes.
Serial.begin(115200);
You also define your GPIOs as OUTPUTs and set them to LOW.
// Initialize the output variables as outputs
pinMode(output5, OUTPUT);
pinMode(output4, OUTPUT);
// Set outputs to LOW
digitalWrite(output5, LOW);
digitalWrite(output4, LOW);
The following lines begin the Wi-Fi connection with WiFi.begin(SSID, password), wait for a successful connection, and prints the ESP IP address in the Serial Monitor
// 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();
loop()
In the loop() we program what happens when a new client establishes a connection with the webserver.
The ESP is always listening for incoming clients with this line:
WiFiClient client = server.available(); // Listen for incoming clients
When a request is received from a client, we’ll save the incoming data. The while loop that follows will be running as long as the client stays connected. We don’t recommend changing the following part of the code unless you know exactly what you are doing
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
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
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();
The next section of if and else statements checks which button was pressed on your web page and controls the outputs accordingly.
As we’ve seen previously, we make a request on different URLs depending on the button we press.
// turns the GPIOs on and off
if (header.indexOf("GET /5/on") >= 0) {
Serial.println("GPIO 5 on");
output5State = "on";
digitalWrite(output5, HIGH);
} else if (header.indexOf("GET /5/off") >= 0) {
Serial.println("GPIO 5 off");
output5State = "off";
digitalWrite(output5, LOW);
} else if (header.indexOf("GET /4/on") >= 0) {
Serial.println("GPIO 4 on");
output4State = "on";
digitalWrite(output4, HIGH);
} else if (header.indexOf("GET /4/off") >= 0) {
Serial.println("GPIO 4 off");
output4State = "off";
digitalWrite(output4, LOW);
}
For example, if you’ve pressed the GPIO 5 ON button, the URL changes to the ESP IP address followed by /5/ON, and we receive that information on the HTTP header. So, we can check if the header contains the expression GET /5/on.
If it contains, the code prints a message on the serial monitor changes the output5State variable to on and turns the LED on.
This works similarly to the other buttons. So, if you want to add more outputs, you should modify this part of the code to include them.
Displaying the HTML Web Page
The next thing you need to do generates the web page. The ESP8266 will be sending a response to your browser with some HTML text to display the web page.
The web page is sent to the client using the client.println() function. You should enter what you want to send to the client as an argument.
The first text you should always send is the following line, which indicates that we’re sending HTML.
<!DOCTYPE html><html>
Then, the following line makes the web page responsive in any web browser.
client.println("<head><meta name=\"viewport\"
content=\"width=device-width, initial-scale=1\">");
The next one is used to prevent requests related to the favicon – You don’t need to worry about this line.
client.println("<link rel=\"icon\" href=\"data:,\">");
Styling the Web Page
Next, we have some CSS to style the buttons and the web page appearance. We choose the Helvetica font, define the content to be displayed as a block, and aligned at the center.
client.println("<style>html { font-family: Helvetica; display: inline-block;
margin: 0px auto; text-align: center;}");
We style our buttons with some properties to define color, size, border, etc…
client.println(".button { background-color: #195B6A; border: none; color:
white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor:
pointer;}");
Then, we define the style for a second button, with all the properties of the button we’ve defined earlier, but with a different color. This will be the style for the off button.
client.println(".button2 {background-color: #77878A;}</style></head>");
Setting the Web Page First Heading
In the next line you set the first heading of your web page, you can change this text to whatever you like
// Web Page Title
client.println("<h1>ESP8266 Web Server</h1>");
Displaying the Buttons and Corresponding State
Then, you write a paragraph to display the GPIO 5 current state. As you can see we use the output5State variable, so that the state updates instantly when this variable changes.
client.println("<p>GPIO 5 - State " + output5State + "</p>");
Then, we display the on or the off button, depending on the current state of the GPIO.
if (output5State=="off") {
client.println("<p><a href=\"/5/on\"><button
class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/5/off\"><button class=\"button
button2\">OFF</button></a></p>");
}
Closing the Connection
Finally, when the response ends, we clear the header variable and stop the connection with the client with client.stop().
// Clear the header variable
header = "";
// Close the connection
client.stop();