ESP32 WROOM-32 are powerfull ARM Core Processors. They can run at 240MHz without any problems and they can be programmed via Arduino IDE. This is a huge opportunity to put aside Arduino and try to discover this fantastic chip!
ESP32 integrates a dual core ARM processor and has a built-in WiFi and Bluetooth modules, with also BLE. The advantage of using this chip is that it is very powerfull, rich of functions and at the same time it is cheap. You can buy one at this link: https://amzn.to/3mFyaLr
For this project we will use this kind of ESP32, a pair of led each one connected to one 330ohm resistor (watch schematics) and an LM35 for reading temperature (in Celsius). We want to turn on and off the led with two buttons that will be showed on the web page. Then we also want to see the read temperature on the same page. How can we do that?
Well, before that, since we are going to build a web page, this web page mustn't be ugly :), so let's use Bootstrap! Here's the reference: https://getbootstrap.com/
So now, let's start to code!
CODE EXPLANATIONFirst of all, we need to use a library to make it easier to build our webserver!
#include <WiFi.h>
Then let's create some macros for defining the pins, and CONNECT_TIME referes to the time to wait for connecting to wifi router, and TIMETOUTTIME referes to the max wait time for answering to a client.
#define LED1 26
#define LED2 27
#define LM35 33
#define CONNECT_TIME 10000
#define TIMEOUTTIME 5000
Now we need to insert wifi's SSID and Password
const char* ssid = "your_ssid";
const char* password = "your_password";
Then let's create the WiFiServer Object:
WiFiServer server(80);
We need a header for managing the client request and response and two string which will show the led state on the web page
String header;
String LED1State = "off";
String LED2State = "off";
these two variables help us to keep track of the web page response time
size_t currentTime = millis();
size_t previousTime = 0;
LET'S MOVE TO VOID SETUP (uppercase because someone might not see that is void setup)
void setup() {
Serial.begin(115200);
We initialize the pins
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(LM35, INPUT);
Then we turn off the LEDs
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
Here's the connection, for starting it we use.begin() of WiFi object and pass to it the ssid and password. Then we monitor wifi status until it is connected, but if 10 seconds are past and wifi is still not connected, it will abort.
P.S. every 250ms we print a dot because we want to make it look more professional
Serial.print("Attempting to connect to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
size_t start_time = millis();
size_t dot_time = millis();
while ((WiFi.status() != WL_CONNECTED) && (start_time + CONNECT_TIME) > millis()) {
if (dot_time + 250 < millis()) {
Serial.print(".");
dot_time = millis();
}
Well, when wifi is connected we inform the user through serial communication (initialized at 115200 baud), and we show the server IP Address with WiFi.localIP()
}
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("ESP32 IP address: ");
Serial.println(WiFi.localIP());
server.begin();
}
LET'S MOVE TO VOID LOOP
First of all we create a WiFiClient object which is returned by server.available(). We need to use it later
void loop() {
WiFiClient client = server.available();
In fact we first check if client is not null, it's a waste of resources to run code in this case. If it is not null we set the two Time variables at the same start time and we create an empty string current line which will be use for process the request
if (client) {
currentTime = millis();
previousTime = currentTime;
Serial.println("New Client.");
String currentLine = "";
All the code before the row: header =""; will be inside the while loop. So while the client is connected and the request/response time is not elapsed:
while (client.connected() && currentTime - previousTime <= TIMEOUTTIME) {
We save the current time and after that, we read a character using the client object and then we send it to the serial monitor. We also concat this character to the header string.
currentTime = millis();
if (client.available()) {
char c = client.read();
Serial.write(c);
header += c;
If the new character (c) is a "\n" and the current line is empty it means that the request is terminated (this is how HTTP headers terminate). So we start to print the response http header
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();
Here we define commands, for example: if the request header contains a " GET /LED1/on" it means that the user has pushed the LED 1 button on the web page for turning it on. So we set the LED1State to "on" and we send a digitalWrite command to the real LED. Same thing for the other statements!
if (header.indexOf("GET /LED1/on") >= 0) {
Serial.println("LED 1 on");
LED1State = "on";
digitalWrite(LED1, HIGH);
} else if (header.indexOf("GET /LED1/off") >= 0) {
Serial.println("LED1 off");
LED1State = "off";
digitalWrite(LED1, LOW);
} else if (header.indexOf("GET /LED2/on") >= 0) {
Serial.println("LED2 on");
LED2State = "on";
digitalWrite(LED2, HIGH);
} else if (header.indexOf("GET /LED2/off") >= 0) {
Serial.println("LED2 off");
LED2State = "off";
digitalWrite(LED2, LOW);
}
After controlling the hardware, we need to show something to the user, inform him on what just happened. Here starts the HTML for the HTTP Response
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
This is usefull for not having issues with character on web page (use UTF-8)
client.println("<meta charset=\"UTF-8\">");
Here we refresh the page every 5 seconds (this for updating the temperature value)
client.println("<meta http-equiv=\"refresh\" content=\"5\" >");
client.println("<link rel=\"icon\" href=\"data:,\">");
Then we import Bootstrap framework and icons (fontawesome)
client.println("<link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css\" integrity=\"sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T\" crossorigin=\"anonymous\">");
client.println("<link rel=\"stylesheet\" href=\"https://use.fontawesome.com/releases/v5.6.3/css/all.css\" integrity=\"sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/\" crossorigin=\"anonymous\">");
client.println("<script src=\"https://code.jquery.com/jquery-3.3.1.slim.min.js\" integrity=\"sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo\" crossorigin=\"anonymous\"></script>");
client.println("<script src=\"https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js\" integrity=\"sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1\" crossorigin=\"anonymous\"></script>");
client.println("<script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js\" integrity=\"sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM\" crossorigin=\"anonymous\"></script>");
Here we define the web page object's style
client.println("<style>");
client.println("html {font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".mybtn {padding: 16px 40px; font-size: 30px;} ");
client.println(".par { font-size: 16px;}");
client.println("p {text-align: center;}");
client.println(".lm35 {text-align: center; border: none; margin: 2px; padding: 16px 40px; font-size: 30px;}");
client.println("</style></head>");
Then body starts, this is what will be showed to the user
client.println("<body class=\"bg-light\">");
client.println("<h1 style=\"text-align:center; \" class=\"display-4\">ESP32 Web Server </h1> ");
client.println("<br />");
This is the structure of one of the two buttons. If led is off we show the "ON Button", otherwise the "OFF Button". As you can seem, the button referes to a link that we checked before for changing led state! (e.g. href="/LED1/off")
client.println("<p class=\"par\">GPIO 26 - State " + LED1State + " </p> ");
if (LED1State == "off") {
client.println("<p><a href =\"/LED1/on\" role=\"button\" class=\"btn btn-success mybtn\" >ON</a></p>");
} else {
client.println("<p><a href=\"/LED1/off\" role=\"button\" class=\"btn btn-danger mybtn\">OFF</a></p>");
}
client.println("<br />");
client.println("<p class=\"par\">LED2 - State " + LED2State + "</p>");
if (LED2State == "off") {
client.println("<p><a href=\"/LED2/on\" role=\"button\" class=\" mybtn btn btn-success mybtn\" >ON</a></p>");
} else {
client.println("<p><a href=\"/LED2/off\" role=\"button\" class=\" mybtn btn btn-danger mybtn\">OFF</a></p>");
}
client.println("<br />");
Then is time to show the temperature. We "define" three state with an "if" statement. In this case, if temperature is less than 21, the temperature container will be green, if it is more than 24 degrees celsius the container will be red, otherwise (in range values) it will be yellow
double temp = analogRead(LM35) / 9.31;
String celsius = String(temp );
client.println("<p class=\"par\">LM35 - Temperature </p>");
if ( temp < 21)
client.println("<p> <span class=\"lm35\" style=\"background-color: #198754!important; color:#f8f9fa!important;\"> " + celsius + "°C </span></p>");
else if ( temp > 24)
client.println("<p> <span class=\"lm35\" style=\"background-color: #dc3545!important; color:#f8f9fa!important;\"> " + celsius + "°C </span></p>");
else
client.println("<p> <span class=\"lm35\" style=\"background-color: #ffc107!important; color:#212529!important;\"> " + celsius + "°C </span></p>");
client.println("<br />");
Finally I added a footer with references and social links, eventually you can discard it
client.println("<footer class=\"bg-dark text-center text-white\">");
client.println("<div class=\"container pt-4 \">");
client.println("<section class=\"mb-4\">");
client.println("<a class=\"btn btn-outline-light btn-floating m-1\" href=\"https://www.facebook.com/MiniProjectsOfficial\" target=\"_blank\" rel=\"noopener noreferrer\" role=\"button\">");
client.println("<i class=\"fab fa-facebook-f\"></i>");
client.println("</a>");
client.println("<a class=\"btn btn-outline-light btn-floating m-1\" href=\"https://www.instagram.com/officialprojecto\" target=\"_blank\" rel=\"noopener noreferrer\" role=\"button\">");
client.println("<i class=\"fab fa-instagram\"></i>");
client.println("</a>");
client.println("<a class=\"btn btn-outline-light btn-floating m-1\" href=\"https://youtube.com/c/ProjectoOfficial\" target=\"_blank\" rel=\"noopener noreferrer\" role=\"button\">");
client.println("<i class=\"fab fa-youtube\"></i>");
client.println("</a>");
client.println("<a class=\"btn btn-outline-light btn-floating m-1\" href=\"https://github.com/ProjectoOfficial\" target=\"_blank\" rel=\"noopener noreferrer\" role=\"button\">");
client.println("<i class=\"fab fa-github\"></i>");
client.println("</a>");
client.println("</section>");
client.println("</div>");
client.println("<div class=\"text-center p-3\" style=\"background-color: rgba(0, 0, 0, 0.2);\"> © 2021 Copyright: <a class=\"text-white\" href=\"https://officialprojecto.wordpress.com\">Projecto</a></div>");
client.println("</footer>");
client.println("</body></html>");
client.println();
break;
If currentline length is not zero, we reset currentline string (inside of "if (c=='\n')")
} else {
currentLine = "";
}
if c is not '\n', if it is not '\r' too, we concat c to the current line
} else if (c != '\r') {
currentLine += c;
}
}
}
End of while loop, we reset the header and disconnect the client
header = "";
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
outside of "if(client)", at the end of the file, we add a 1ms delay
delay(1);
}
And that's all! Now you can implement your own web server with an ESP32. Check my youtube channel, I will soon publish a video about this!
Https://youtube.com/c/ProjectoOfficial/
FINAL RESULTThis is what you will see on your serial monitor, these information are about the HTTP connection with the client:
Here's the ESP32 Hardware configuration:
Here you can see the web page once you've uploaded the sketch on your ESP32:
This page shows a button turned on and the temperature which is risen to, changing the background temperature color to yellow:
Thanks for watching, I leave to you these links:
Facebook: https://www.facebook.com/MiniProjectsOfficial\
Instagram: https://www.instagram.com/officialprojecto
Youtube: https://youtube.com/c/ProjectoOfficial
GitHub: https://github.com/ProjectoOfficial
Comments