In a previous article called How to Set Up a Web Server Using the Arduino and an ESP8266-01, we tackled the fundamentals of an Arduino web server. Now, let’s advance to learning how to control GPIO Pins. In this tutorial, we are going to toggle LEDs with a web page that can be accessed from anywhere in the world.

But before anything, let’s have a short review of some essential terms from the previous tutorial.

  • Web server – a software, hardware, or combination of both that contains files needed to process and deliver web pages.
  • Web client – any device that can send an HTTP/web request to a web server.
  • Local server – a web server that can only be visited inside your LAN (Local Area Network).
  • Global server – a web server that can be accessed anywhere via the internet.
  • HTTP POST – a web request that transmits data into the server.
  • HTTP GET – a web request that retrieves data from a web browser.
  • Port forwarding – a router setting that directs traffic from a WAN port to a particular device inside your LAN.

Preparing the Hardware

For our sample project, you will need the following parts:

Using jumper wires, connect the parts as shown below:

Just like before, we are going to use an Arduino UNO to program the ESP-01 module. To do so, we will disable the UNO’s onboard chip by connecting the RESET pin to GND. Then, set the Generic ESP8266 module as your board in the Arduino IDE.

To set the ESP-01 module to program mode, connect the GPIO0 pin to GND. Similarly, connect and disconnect the RESET pin of the ESP-01 to the GND before uploading. 

Troubleshooting Tips:

  • Never forget to connect the Arduino RESET pin to GND.
  • Make sure the upload speed is 115200.
  • Check the voltage reading of your voltage divider circuit. It must give 3.3V to your RX pin.
  • If you get constant errors uploading a sketch into the ESP-01, downgrade your ESP8266 board library in the Boards Manager to version 2.5.0.
  • If the program doesn’t run after the upload, briefly connect then disconnect the ESP-01 reset pin to GND.

The Code

Copy the following sketch in the Arduino IDE.

#include <ESP8266WiFi.h>

const char* ssid = "WiFi name";
const char* password = "WiFi password";

int ledPin = 2; 
WiFiServer server(80);

void setup() 
{
  Serial.begin(115200);

  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(100);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("Connected to WiFi");
  Serial.print("IP: ");  Serial.println(WiFi.localIP());

  server.begin();
}

void loop() 
{
  WiFiClient client = server.available();
  if (!client) {
  return;
  }

  while(!client.available()){
  }
  
  String request = client.readStringUntil('\r');
  Serial.println(request);
  client.flush();

  int value = LOW;
  if (request.indexOf("/LED=ON") != -1) 
  {
    digitalWrite(ledPin, HIGH);
    value = HIGH;
  } 
  if (request.indexOf("/LED=OFF") != -1)
  {
    digitalWrite(ledPin, LOW);
    value = LOW;
  }

  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println(""); //  do not forget this one

  client.println("<!DOCTYPE HTML>");
  client.println("<html>");
  client.print("LED status: "); 

  if(value == HIGH) 
  {
    client.print("ON");  
  } 
  else 
  {
    client.print("OFF");
  }
  client.println("<br><br>");
  client.println("Turn <a href=\"/LED=ON\">ON</a><br>");
  client.println("Turn <a href=\"/LED=OFF\">OFF</a><br>");
  client.println("</html>");

  Serial.println("");
}

Code Explanation

We only need the ESP8266WiFI.h this time. This comes with the ESP8266 board library so no need to install it.

#include <ESP8266WiFi.h>

Enter your home network credentials here.

const char* ssid = "WiFi name";
const char* password = "WiFi password";

Set the webserver port number to 80.

WiFiServer server(80);

In the setup section, set the LED pin as an output and initialize it to LOW.

Interestingly, the built-in LED of the ESP-01 is connected to GPIO2 but is active LOW. If you set the GPIO2 pin to LOW, the LED connected to GPIO2 turns off while the built-in LED lights up.

The setup also initializes the serial monitor. The serial monitor is used to display information like the ESP-01’s IP address. It also helps in identifying errors.

Lastly, the setup starts the webserver using server.begin().

void setup() 
{
  Serial.begin(115200);

  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(100);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("Connected to WiFi");
  Serial.print("IP: ");  Serial.println(WiFi.localIP());

server.begin();
}

Next, in the loop section, we have server.available(). This function detects new web clients. It constantly returns false when there’s none. Conversely, the code proceeds to the next line if it detects a new client.

WiFiClient client = server.available();
  if (!client) {
  return;
  }

It waits until the client sends a request.

  while(!client.available()){
  }

And reads the request then prints it on the serial monitor. The client.flush() function makes sure all outgoing characters have been sent.

  String request = client.readStringUntil('\r');
  Serial.println(request);
  client.flush();

/LED=ON and /LED=OFF are the names of the requests that we are going to use to toggle the LED on and off. We will see them later in the HTML code. Basically, if the previous line reads /LED=ON, the program sends a HIGH to the LED pin and vice versa.

  int value = LOW;
  if (request.indexOf("/LED=ON") != -1) {
  digitalWrite(ledPin, HIGH);
  value = HIGH;
  } 
  if (request.indexOf("/LED=OFF") != -1){
  digitalWrite(ledPin, LOW);
  value = LOW;
  }

Finally, we create a web page using client.println().

  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println(""); 

  client.println("<!DOCTYPE HTML>");
  client.println("<html>");
  client.print("LED status: "); 

  if(value == HIGH) 
  {
    client.print("ON");  
  } 
  else 
  {
    client.print("OFF");
  }
  client.println("<br><br>");
  client.println("Turn <a href=\"/LED=ON\">ON</a><br>");
  client.println("Turn <a href=\"/LED=OFF\">OFF</a><br>");
  client.println("</html>");

  Serial.println("");

Here, we see how we named the requests /LED=ON and /LED=OFF.

  client.println("Turn <a href=\"/LED=ON\">ON</a><br>");
  client.println("Turn <a href=\"/LED=OFF\">OFF</a><br>");

Demonstration

1. Upload the sketch, then open the serial monitor. There will be instances when the serial monitor displays garbage data and the ESP-01 refuses to connect. An easy fix would be briefly connecting and disconnecting the ESP-01 RESET pin to the ground.

2. Enter the given IP address from the serial monitor to any web browser. The first line indicates whether the LED is currently turned ON or OFF. To change it, simply click the links.

How to Control GPIO Pins Using an Arduino Web Server - Web Server Interface