ESP32 Async Web Server – Control Outputs with Arduino IDE (ESPAsyncWebServer library)
Learn how to build an asynchronous web server with the ESP32 board to control outputs remotely. Program the ESP boards with ESPAsyncWebServer and Arduino IDE.
- Suitable forB.Tech/Diploma IoT/ESP32 students
- Build time1-2 weeks
- LevelBeginner
- Available atAjvika Labs, Kakinada
About this project
In this tutorial you’ll learn how to build an asynchronous web server with the ESP32 board to control its outputs. The board will be programmed using Arduino IDE, and we’ll use the ESPAsyncWebServer library.
You might also like:
ESP8266 NodeMCU Async Web Server – Control Outputs with Arduino IDE (ESPAsyncWebServer library)
Asynchronous Web Server
To build the web server we’ll use the
ESPAsyncWebServer library
that provides an easy way to build an asynchronous web server. Building an asynchronous web server has several advantages as mentioned in the library GitHub page, such as:
“Handle more than one connection at the same time”;
“When you send the response, you are immediately ready to handle other connections while the server is taking care of sending the response in the background”;
“Simple template processing engine to handle templates”;
And much more.
Take a look at the
library documentation
on its GitHub page.
Parts Required
In this tutorial, we’ll control three outputs. As an example, we’ll control LEDs. So, you need the following parts:
ESP32
(read
Best ESP32 Development Board
)
3x
LEDs
3x
220 Ohm Resistor
Breadboard
Jumper wires
You can use the preceding links or go directly to
MakerAdvisor.com/tools
to find all the parts for your projects at the best price!
Schematic
Before proceeding to the code, wire 3 LEDs to the ESP32. We’re connecting the LEDs to GPIOs 2, 4 and 33, but you can use any other GPIOs (read
ESP32 GPIO Reference Guide
).
Installing Libraries – ESP Async Web Server
We’ll build the web server using the following libraries:
ESPAsyncWebServer
by ESP32Async
AsyncTCP
by ESP32Async
You can install these libraries in the Arduino Library Manager. Open the Library Manager by clicking the Library icon at the left sidebar.
Search for
ESPAsyncWebServer
and install the
ESPAsyncWebServer by ESP32Async
Then, install the AsyncTCP library. Search for
AsyncTCP
and install the
AsyncTCP by ESP32Async
Project Overview
To better understand the code, let’s see how the web server works.
The web server contains one heading “ESP Web Server” and three buttons (toggle switches) to control three outputs. Each slider button has a label indicating the GPIO output pin. You can easily remove/add more outputs.
When the slider is red, it means the output is on (its state is HIGH). If you toggle the slider, it turns off the output (change the state to LOW).
When the slider is gray, it means the output is off (its state is LOW). If you toggle the slider, it turns on the output (change the state to HIGH).
How it Works?
Let’s see what happens when you toggle the buttons. We’ll see the example for GPIO 2. It works similarly for the other buttons.
In the first scenario, you toggle the button to turn GPIO 2 on. When that happens, the browser makes an HTTP GET request on the
/update?output=
&state=
URL. Based on that URL, the ESP changes the state of GPIO 2 to 1 (
HIGH
) and turns the LED on.
In the second example, you toggle the button to turn GPIO 2 off. When that happens, the browser makes an HTTP GET request on the
/update?output=
&state=
URL. Based on that URL, we change the state of GPIO 2 to 0 (
LOW
) and turn the LED off.
Code for ESP Async Web Server
Copy the following code to your Arduino IDE.
/*********
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*********/
// Import required libraries
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
const char* PARAM_INPUT_1 = "output";
const char* PARAM_INPUT_2 = "state";
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>ESP Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
<style>
html {font-family: Arial; display: inline-block; text-align: center;}
h2 {font-size: 3.0rem;}
p {font-size: 3.0rem;}
body {max-width: 600px; margin:0px auto; padding-bottom: 25px;}
.switch {position: relative; display: inline-block; width: 120px; height: 68px}
.switch input {display: none}
.slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 6px}
.slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 3px}
input:checked+.slider {background-color: #b30000}
input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}
</style>
</head>
<body>
<h2>ESP Web Server</h2>
%BUTTONPLACEHOLDER%
<script>function toggleCheckbox(element) {
var xhr = new XMLHttpRequest();
if(element.checked){ xhr.open("GET", "/update?output="+element.id+"&state=1", true); }
else { xhr.open("GET", "/update?output="+element.id+"&state=0", true); }
xhr.send();
}
</script>
</body>
</html>
)rawliteral";
// Replaces placeholder with button section in your web page
String processor(const String& var){
//Serial.println(var);
if(var == "BUTTONPLACEHOLDER"){
String buttons = "";
buttons += "<h4>Output - GPIO 2</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"2\" " + outputState(2) + "><span class=\"slider\"></span></label>";
buttons += "<h4>Output - GPIO 4</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"4\" " + outputState(4) + "><span class=\"slider\"></span></label>";
buttons += "<h4>Output - GPIO 33</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"33\" " + outputState(33) + "><span class=\"slider\"></span></label>";
return buttons;
}
return String();
}
String outputState(int output){
if(digitalRead(output)){
return "checked";
}
else {
return "";
}
}
void setup(){
// Serial port for debugging purposes
Serial.begin(115200);
pinMode(2, OUTPUT);
digitalWrite(2, LOW);
pinMode(4, OUTPUT);
digitalWrite(4, LOW);
pinMode(33, OUTPUT);
digitalWrite(33, LOW);
// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
// Print ESP Local IP Address
Serial.println(WiFi.localIP());
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/html", index_html, processor);
});
// Send a GET request to <ESP_IP>/update?output=<inputMessage1>&state=<inputMessage2>
server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) {
String inputMessage1;
String inputMessage2;
// GET input1 value on <ESP_IP>/update?output=<inputMessage1>&state=<inputMessage2>
if (request->hasParam(PARAM_INPUT_1) && request->hasParam(PARAM_INPUT_2)) {
inputMessage1 = request->getParam(PARAM_INPUT_1)->value();
inputMessage2 = request->getParam(PARAM_INPUT_2)->value();
digitalWrite(inputMessage1.toInt(), inputMessage2.toInt());
}
else {
inputMessage1 = "No message sent";
inputMessage2 = "No message sent";
}
Serial.print("GPIO: ");
Serial.print(inputMessage1);
Serial.print(" - Set to: ");
Serial.println(inputMessage2);
request->send(200, "text/plain", "OK");
});
// Start server
server.begin();
}
void loop() {
}
How the Code Works
In this section we’ll explain how the code works
You might also like:
ESP8266 NodeMCU Async Web Server – Control Outputs with Arduino IDE (ESPAsyncWebServer library)
Asynchronous Web Server
To build the web server we’ll use the
ESPAsyncWebServer library
that provides an easy way to build an asynchronous web server. Building an asynchronous web server has several advantages as mentioned in the library GitHub page, such as:
“Handle more than one connection at the same time”;
“When you send the response, you are immediately ready to handle other connections while the server is taking care of sending the response in the background”;
“Simple template processing engine to handle templates”;
And much more.
Take a look at the
library documentation
on its GitHub page.
Parts Required
In this tutorial, we’ll control three outputs. As an example, we’ll control LEDs. So, you need the following parts:
ESP32
(read
Best ESP32 Development Board
)
3x
LEDs
3x
220 Ohm Resistor
Breadboard
Jumper wires
You can use the preceding links or go directly to
MakerAdvisor.com/tools
to find all the parts for your projects at the best price!
Schematic
Before proceeding to the code, wire 3 LEDs to the ESP32. We’re connecting the LEDs to GPIOs 2, 4 and 33, but you can use any other GPIOs (read
ESP32 GPIO Reference Guide
).
Installing Libraries – ESP Async Web Server
We’ll build the web server using the following libraries:
ESPAsyncWebServer
by ESP32Async
AsyncTCP
by ESP32Async
You can install these libraries in the Arduino Library Manager. Open the Library Manager by clicking the Library icon at the left sidebar.
Search for
ESPAsyncWebServer
and install the
ESPAsyncWebServer by ESP32Async
Then, install the AsyncTCP library. Search for
AsyncTCP
and install the
AsyncTCP by ESP32Async
Project Overview
To better understand the code, let’s see how the web server works.
The web server contains one heading “ESP Web Server” and three buttons (toggle switches) to control three outputs. Each slider button has a label indicating the GPIO output pin. You can easily remove/add more outputs.
When the slider is red, it means the output is on (its state is HIGH). If you toggle the slider, it turns off the output (change the state to LOW).
When the slider is gray, it means the output is off (its state is LOW). If you toggle the slider, it turns on the output (change the state to HIGH).
How it Works?
Let’s see what happens when you toggle the buttons. We’ll see the example for GPIO 2. It works similarly for the other buttons.
In the first scenario, you toggle the button to turn GPIO 2 on. When that happens, the browser makes an HTTP GET request on the
/update?output=
&state=
URL. Based on that URL, the ESP changes the state of GPIO 2 to 1 (
HIGH
) and turns the LED on.
In the second example, you toggle the button to turn GPIO 2 off. When that happens, the browser makes an HTTP GET request on the
/update?output=
&state=
URL. Based on that URL, we change the state of GPIO 2 to 0 (
LOW
) and turn the LED off.
Code for ESP Async Web Server
Copy the following code to your Arduino IDE.
/*********
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*********/
// Import required libraries
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
const char* PARAM_INPUT_1 = "output";
const char* PARAM_INPUT_2 = "state";
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>ESP Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
<style>
html {font-family: Arial; display: inline-block; text-align: center;}
h2 {font-size: 3.0rem;}
p {font-size: 3.0rem;}
body {max-width: 600px; margin:0px auto; padding-bottom: 25px;}
.switch {position: relative; display: inline-block; width: 120px; height: 68px}
.switch input {display: none}
.slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 6px}
.slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 3px}
input:checked+.slider {background-color: #b30000}
input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}
</style>
</head>
<body>
<h2>ESP Web Server</h2>
%BUTTONPLACEHOLDER%
<script>function toggleCheckbox(element) {
var xhr = new XMLHttpRequest();
if(element.checked){ xhr.open("GET", "/update?output="+element.id+"&state=1", true); }
else { xhr.open("GET", "/update?output="+element.id+"&state=0", true); }
xhr.send();
}
</script>
</body>
</html>
)rawliteral";
// Replaces placeholder with button section in your web page
String processor(const String& var){
//Serial.println(var);
if(var == "BUTTONPLACEHOLDER"){
String buttons = "";
buttons += "<h4>Output - GPIO 2</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"2\" " + outputState(2) + "><span class=\"slider\"></span></label>";
buttons += "<h4>Output - GPIO 4</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"4\" " + outputState(4) + "><span class=\"slider\"></span></label>";
buttons += "<h4>Output - GPIO 33</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"33\" " + outputState(33) + "><span class=\"slider\"></span></label>";
return buttons;
}
return String();
}
String outputState(int output){
if(digitalRead(output)){
return "checked";
}
else {
return "";
}
}
void setup(){
// Serial port for debugging purposes
Serial.begin(115200);
pinMode(2, OUTPUT);
digitalWrite(2, LOW);
pinMode(4, OUTPUT);
digitalWrite(4, LOW);
pinMode(33, OUTPUT);
digitalWrite(33, LOW);
// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
// Print ESP Local IP Address
Serial.println(WiFi.localIP());
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/html", index_html, processor);
});
// Send a GET request to <ESP_IP>/update?output=<inputMessage1>&state=<inputMessage2>
server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) {
String inputMessage1;
String inputMessage2;
// GET input1 value on <ESP_IP>/update?output=<inputMessage1>&state=<inputMessage2>
if (request->hasParam(PARAM_INPUT_1) && request->hasParam(PARAM_INPUT_2)) {
inputMessage1 = request->getParam(PARAM_INPUT_1)->value();
inputMessage2 = request->getParam(PARAM_INPUT_2)->value();
digitalWrite(inputMessage1.toInt(), inputMessage2.toInt());
}
else {
inputMessage1 = "No message sent";
inputMessage2 = "No message sent";
}
Serial.print("GPIO: ");
Serial.print(inputMessage1);
Serial.print(" - Set to: ");
Serial.println(inputMessage2);
request->send(200, "text/plain", "OK");
});
// Start server
server.begin();
}
void loop() {
}
How the Code Works
In this section we’ll explain how the code works
Technologies used
Hardware components
- ESP32
- ESP8266
- Arduino
Software & tools
- Arduino IDE
What you get
- Working project / hardware kit, tested before delivery
- Complete source code with explanation
- Project demo and guidance for your viva
- Project report, PPT and IEEE paper support (on request)
Delivery & Payment
Delivery takes a minimum of two weeks from the date your inquiry is confirmed.
Payment is in two parts:
• 50% advance to start the project
• Remaining 50% before delivery
Note:
• Documentation and PPT are not included by default
• If you need documentation/PPT, it can be arranged for extra time and cost
We'll confirm the exact timeline and cost with you after reviewing your requirements.