How To Make An IoT Web Server Using ESP32 WROOM With Arduino IDE

2,596 views

IoT or Internet of Things refers to the millions and millions of devices that are communicating with each other in real time through the internet, encrypting, decrypting, and sharing a heap ton of data at the same time. IoT promises to add a great influence and value to our daily lives, from the way we react to the way we behave. So, In today’s tutorial, we are going to go over a step by step process on How To Make An IoT Web Server Using ESP32 WROOM MCU With an Arduino IDE & to control LED outputs over it.

From HVAC systems that you can control by a touch of your smartphone’s screen to the Smart watches tracking your daily caloric intake & updating your Gym trainer about your fitness schedule. IoT has cemented itself as a giant network with many connected devices. All these devices use an array of sensors in order to communicate the nature of their use and the environment in which they are being operated.

What is an ESP32 IoT Web Server?

An ESP32 based IoT web server basically allows the exchange of data & control signals through wireless means. How this server communication works is actually pretty simple. The concept of an IoT based web server basically revolves around connecting devices to the Internet and letting them communicate with other devices or users, etc. The communication chain of any IoT web server is basically linked between three Key elements:

  1. The output transducer/sensor.
  2. The Gateway Device (ESP32-WROOM)
  3. The Cloud/Web Server over which the communication with the user takes place

All the devices communicating in an IoT network will cpommunicate to each other using the same TCP/IP protocol.

What is ESP32 WROOM MCU?

ESP32 WROOM is a powerful, Wi-Fi + BT + BLE MCU module that targets a wide variety of IoT applications, ranging from small power sensor networks to the most memory intensive tasks, such as speech encoding, music streaming, and MP3 decryption. At the heart of this MCU is the ESP32 D0WDQ6 chip. The chip embedded is designed to be scalable and adaptive. There are two CPU cores that can be individually controlled, and the clock frequency is adjustable from 80 MHz to 240 MHz You can also power off the CPU and make use of the low power co-processor to monitor the peripherals for changes or crossing of thresholds constantly. ESP32 WROOM integrates a rich set of compatible peripherals, ranging from capacitive touch sensors, Hall sensors, SD card interface, Ethernet, high-speed SPI, UART, I²S, and I²C.

Key Features & Specifications

  • 2 Low power Xtensa® 32-bit LX6 microprocessors
  • 448 KBytes ROM for booting and core functions
  • 520 KBytes on-chip SRAM
  • 8 KBytes SRAM in RTC SLOW
  • 8 KBytes SRAM in RTC FAST
  • 1 Kbit of EFUSE, 256 bits MAC
  • WiFi: 802.11 b/g/n/d/e/i/k/r (802.11n up to 150 Mbps)
  • Bluetooth v4.2 BR/EDR and BLE specification
  • Wi-Fi mode Station/softAP/SoftAP+station/P2P
  • Security WPA/WPA2/WPA2-Enterprise/WPS
  • Encryption AES/RSA/ECC/SHA
  • IPv4, IPv6, SSL, TCP/UDP/HTTP/FTP/MQTT
  • Interfaces: SD-card, UART, SPI, SDIO, I2C, LED PWM, Motor PWM, I2S , IR, GPIO, capacitive touch sensor, ADC, DAC, Hall sensor, temperature sensor
  • Operating temperature -40 + 85C
  • Operating voltage: 2.2-3.6V
  • Consumption: 80 mA typ
  • Dimensions: 18 mm x 20 mm x 3 mm

Hardware Component For IoT Web Server Using ESP32

You will need the following parts to build this project:

S.NoComponentValueQty
1)ESP WROOM 32 Dev Board2.4GHz Dual-Mode WiFi + Bluetooth1
2)ESP WROOM 32 CableUSB to Type B1
3)LEDs5mm, 3.5V2
4)Resistors330 Ohms2
5)Laptop/PC1
6)Arduino IDE1.8.131
7)Smartphone1
8)Breadboard1
9)Jumper WiresAs per need

ESP32 WROOM Pinout

Useful Steps

1) Make the connections as shown in the circuit diagram

2) Connect the ESP32 module with your PC using USB to type B cable and burn the code provided below.

3) Now power up the circuit and test it by remote acessing the web server.

Circuit Diagram For IoT Web Server Using ESP32

Installing The ESP32 Board in Arduino IDE

There is an add-on option in Arduino IDE that allows you to program an ESP32 Board using the Arduino IDE & it’s programming structure. Follow one of the following tutorials to ready your Arduino IDE.

Source Code

#include <WiFi.h>

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

WiFiServer server(80);

String header;

String output26State = "off";
String output27State = "off";

const int output26 = 26;
const int output27 = 27;

unsigned long currentTime = millis();
unsigned long previousTime = 0; 
const long timeoutTime = 2000;

void setup() {
  Serial.begin(115200);
  pinMode(output26, OUTPUT);
  pinMode(output27, OUTPUT);
  digitalWrite(output26, LOW);
  digitalWrite(output27, LOW);

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

void loop(){
  WiFiClient client = server.available();   

  if (client) {                             
    currentTime = millis();
    previousTime = currentTime;
    Serial.println("New Client.");          
    String currentLine = "";                
    while (client.connected() && currentTime - previousTime <= timeoutTime) {  
      currentTime = millis();
      if (client.available()) {             
        char c = client.read();            
        Serial.write(c);                    
        header += c;
        if (c == '\n') {                  
         
         
          if (currentLine.length() == 0) {
           
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();
            
           
            if (header.indexOf("GET /26/on") >= 0) {
              Serial.println("GPIO 26 on");
              output26State = "on";
              digitalWrite(output26, HIGH);
            } else if (header.indexOf("GET /26/off") >= 0) {
              Serial.println("GPIO 26 off");
              output26State = "off";
              digitalWrite(output26, LOW);
            } else if (header.indexOf("GET /27/on") >= 0) {
              Serial.println("GPIO 27 on");
              output27State = "on";
              digitalWrite(output27, HIGH);
            } else if (header.indexOf("GET /27/off") >= 0) {
              Serial.println("GPIO 27 off");
              output27State = "off";
              digitalWrite(output27, LOW);
            }
            
     
            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:,\">");
        

            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #555555;}</style></head>");

            client.println("<body><h1>ESP32 Web Server</h1>");
            client.println("<p>GPIO 26 - State " + output26State + "</p>");
               
            if (output26State=="off") {
              client.println("<p><a href=\"/26/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/26/off\"><button class=\"button button2\">OFF</button></a></p>");
            } 
               
            client.println("<p>GPIO 27 - State " + output27State + "</p>");
              
            if (output27State=="off") {
              client.println("<p><a href=\"/27/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/27/off\"><button class=\"button button2\">OFF</button></a></p>");
            }
            client.println("</body></html>");
            
       
            client.println();
    
            break;
          } else { 
            currentLine = "";
          }
        } else if (c != '\r') { 
          currentLine += c;     
        }
      }
    }
   
    header = "";
   
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

Working Explanation

Setting Up Your Network Profile

First of all, you need to get you network credentials up & running. For this you need to modify the following lines of code with you network profile: Your SSID & Password.

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Transferring The Code

After the step above, upload the code and the web server will work straight away. Follow the next steps to upload code to the ESP32:

  1. Plug your ESP32 board on your computer.
  2. In the Arduino IDE select your board in Tools > Board (in our case we’re using the ESP32 DEVKIT DOIT board);
  3. Select the COM port in Tools > Port.
  4. Press the Upload button in the Arduino IDE and wait a few seconds while the code compiles and uploads to your board.
  5. Wait for the “Done uploading” message.

Locating The ESP IP Address

  • After uploading the code, open the Serial Monitor at a baud rate of 115200.
  • Press the ESP32 EN button (reset). The ESP32 connects to Wi-Fi, and outputs the ESP IP address on the Serial Monitor. Copy that IP address, because you need it to access the ESP32 web server.

Acquiring Access to the Web Server

  • To access the webserver, open your browser, paste the ESP32 IP address, and you’ll see the following page. In the following case, it is 192.168.1.135.
  • On checking the Serial Monitor, you can understand what’s happening in the background. The ESP receives an HTTP request from a new client (your mobile browser)

Running The Web Server

  • To test if the web server is running properly, simply click the buttons to control the LED.
  • You’ll notice on the serial monitor that when you click either GPIO26 or GPIO27 ON, ESP32 receives on the /26/on or /27/on URL respectively.

Coding Explanation

Here we are going to take a closer look into the operation of the code itself

First of all, you need to include the Wi-Fi Library in the arduino IDE

#include <WiFi.h>

After that, you’ll be required to enter your SSID & Password in the following lines inside the double quotes.

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

Then the following line of code sets your web server to port 80.

WiFiServer server(80);

After that, the following line of code declares the string variable to store the header of the HTTP request.

String header;

Then, you create auxiliary variables to store the current state of your outputs. If you want to add more outputs and save their state, you need to create more variables.

String output26State = "off";
String output27State = "off";

Then you have to assign a GPIO to each of your outputs. Here we are using GPIO 26 and GPIO 27.

const int output26 = 26;
const int output27 = 27;

void setup()

Here, you first Start the serial communication at a baud rate of 115200 for debugging purposes.

Serial.begin(115200);

Then you have to label your GPIOs as OUTPUTs & set them to LOW.

pinMode(output26, OUTPUT);
pinMode(output27, OUTPUT);

digitalWrite(output26, LOW);
digitalWrite(output27, LOW);

After the above step, the following lines of code begin the Wi-Fi connection:

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

Wait for a successful connection and then print the ESP IP address in the Serial Monitor.

void loop()

In loop() segment of the code we establish what happens when a new client authorizes a connection with the web server:

The first line in loop() indicates that the ESP32 is always listening for incoming clients:

WiFiClient client = server.available();

On receiving a request from the client, the incoming data will be saved. The following while loop will continuously run as long as the client stays connected. Don’t make any changes in the following code unless you have comprehensive understanding of what you are doing.

if (client)
 { 
  Serial.println("New Client."); 
  String currentLine = ""; 
  while (client.connected())
 { 
    if (client.available())
  { 
      char c = client.read(); 
      Serial.write(c); 
      header += c;
      if (c == '\n') 
    { 
        if (currentLine.length() == 0)
      {
          client.println("HTTP/1.1 200 OK");
          client.println("Content-type:text/html");
          client.println("Connection: close");
          client.println();

The next block of IF & ELSE statements determine which option was pressed on the webpage & triggers the output in real time respectively. As seen above we make requests on different URLs depending on the buttons pressed.

if (header.indexOf("GET /26/on") >= 0) 
{
  Serial.println("GPIO 26 on");
  output26State = "on";
  digitalWrite(output26, HIGH);
}
else if (header.indexOf("GET /26/off") >= 0) 
{
  Serial.println("GPIO 26 off");
  output26State = "off";
  digitalWrite(output26, LOW);
}
else if (header.indexOf("GET /27/on") >= 0) 
{
  Serial.println("GPIO 27 on");
  output27State = "on";
  digitalWrite(output27, HIGH);
} 
else if (header.indexOf("GET /27/off") >= 0)
 {
  Serial.println("GPIO 27 off");
  output27State = "off";
  digitalWrite(output27, LOW);
}

for e.g. on pressing the GPIO 26 ON button, the ESP32 receives a request on the /26/ON URL (we can verify this info by checking the HTTP header on the serial monitor). Then, we can check whether the HTTP header contains the GET/26/on expression.  If it does, we change the output26state variable to ON, and the ESP32 turns the LED on.

Displaying & Styling The HTML Webpage

The next part that comes with the code is setting up the webpage itself. Here, the ESP32 sends a response to your web browser with some HTML code to build up the web page

The first thing we should always send is the following line, that indicates that we are sending HTML.

<!DOCTYPE HTML><html>

Then enter the following lines of code to make the target webpage responsive to any web browser. Also incorporate the following piece of code to prevent requests on the favicon.

client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");

client.println("<link rel=\"icon\" href=\"data:,\">");

Then incorporate some CSS text to style the buttons and the web page. Choose the Helvetica font, define the content to be displayed as a block and align it in the center. Set button style with the #4CAF50 color, without border, text in white color, and with this padding: 16px 40px. Then set the text decoration to none, set the font size, the margin, and the cursor to a pointer.

client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");

Similarly define the style for the 2nd button, using all the same properties of the first button defined above, just change the color to designate it as the OFF button.

client.println(".button2 {background-color: #555555;}</style></head>");

Setting The Web Page 1st Heading

Here you can decide the first heading on your webpage.

client.println("<h1>ESP32 Web Server</h1>");

Displaying The Buttons & their States

Here write following lines of code to display the current state of GPIO 26. Use the output26State variable, so that the state updates instantly when this variable changes.

client.println("<p>GPIO 26 - State " + output26State + "</p>");

Then, display the on/off button, depending on the current state of the GPIO. If the current state of the GPIO is off, show ON button, if not, show the OFF button.

if (output26State=="off") 
{
client.println("<p><a href=\"/26/on\"><button class=\"button\">ON</button></a></p>");
} 
else 
{
client.println("<p><a href=\"/26/off\"><button class=\"button button2\">OFF</button></a></p>");
}

Terminating the Connection

When the response ends, clear the header variable & stop the connection with the client.

header = "";

client.stop();

Applications

  • Serves as the basis for IoT based home automation and control.
  • Can be used to control various DC appliancs wirelessly

See Also: Ding Dong Sound Generator Circuit | LC Meter Circuit using 555 Timer | How to setup WiFi on Raspberry Pi 3?