Crear un servidor web con ESP32 PLC

¿Cómo configurar tu propio servidor web con ESP32 PLC, para el control y la automatización industrial?
5 de diciembre de 2023 por
Crear un servidor web con ESP32 PLC
Boot & Work Corp. S.L., Queralt del Águila Munté

Configurando el servidor web con ESP32 PLC:
Guía paso a paso

En esta entrada de blog, se explora cómo utilizar un ESP32 PLC para crear un servidor web robusto. Se comienza con los fundamentos, guiándote a través de la programación del ESP32 con Arduino IDE y destacando la integración del ESP32 WiFi Manager para una conectividad a internet eficiente. Este método simplifica el desarrollo del servidor web, aprovechando las significativas capacidades del ESP32, incluyendo su amplia memoria flash, lo que lo hace ideal para usos industriales. 


Explorando el servidor web con ESP32:
Mejora tus proyectos IoT

This code demonstrates how to create a web server using an ESP32 PLC. It relies on two libraries, WiFi.h and WebServer.h, which are provided by the Arduino IDE.

When you run this code, it sets up a web server on the ESP32. This server hosts a web page that you can access from a computer or smartphone. There is a button on this web page. By clicking this button, you can switch a digital output (in this case is Q0.0) on the ESP32 PLC on and off. This interaction is made possible by the HTML and CSS code embedded in the web page, which provides a user-friendly interface.

When running the code in the Arduino IDE, make sure that you have selected the correct model of ESP32 PLC to ensure compatibility and correct operation.

In summary, this code provides a practical example of how to create a web-based interface to control a specific function (Q0.0) of an ESP32 PLC over a Wi-Fi network.

#include <WiFi.h>
#include <WebServer.h>

/* Make sure to write your SSID and Password to access to your Wifi */
const char* ssid = "SSID";
const char* password = "PASSWORD";


WebServer server(80);

bool ledStatus = LOW;

void handle_OnConnect() {
  ledStatus = LOW;
  Serial.println("Q0_0: OFF");
  server.send(200, "text/html", SendHTML(ledStatus));
}

void handle_ledOn() {
  ledStatus = HIGH;
  Serial.println("Q0_0: ON");
  server.send(200, "text/html", SendHTML(ledStatus));
}

void handle_ledOff() {
  ledStatus = LOW;
  Serial.println("Q0_0: OFF");
  server.send(200, "text/html", SendHTML(ledStatus));
}

void handle_NotFound() {
  server.send(404, "text/plain", "La pagina no existeix");
}

/* HTML and CSS of the Web Server */

String SendHTML(uint8_t ledStatus) {
  String ptr = "<!DOCTYPE html> <html>\n";
 
  ptr += "<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr += "<title>Control LED</title>\n";

  ptr += "<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
  ptr += "body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n";
  ptr += ".button {display: block;width: 80px;background-color: #3498db;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n";
  ptr += ".button-on {background-color: #3498db;}\n";
  ptr += ".button-on:active {background-color: #2980b9;}\n";
  ptr += ".button-off {background-color: #34495e;}\n";
  ptr += ".button-off:active {background-color: #2c3e50;}\n";
  ptr += "p {font-size: 14px;color: #888;margin-bottom: 10px;}\n";
  ptr += "</style>\n";
  ptr += "</head>\n";
  ptr += "<body>\n";

  ptr += "<h1>ESP32 Web Server</h1>\n";
  ptr += "<h3>Using Station Mode</h3>\n";

  if (ledStatus) {
    ptr += "<p>Estat LED: ON</p><a class=\"button button-off\" href=\"/ledOff\">OFF</a>\n";
  }
  else {
    ptr += "<p>Estat LED: OFF</p><a class=\"button button-on\" href=\"/ledOn\">ON</a>\n";
  }

  ptr += "</body>\n";
  ptr += "</html>\n";
  return ptr;
}

void setup() {
  Serial.begin(115200);
  pinMode(Q0_0, OUTPUT);

  /* Station Mode */
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");

  /* Wait for connection */
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

/* http://ip_esp32/ */

  server.on("/", handle_OnConnect);
  server.on("/ledOn", handle_ledOn);
  server.on("/ledOff", handle_ledOff);
  server.onNotFound(handle_NotFound);

  server.begin();
  Serial.println("Server HTTP initiated");
}

void loop() {
  server.handleClient();
  if (ledStatus) {
    digitalWrite(Q0_0, HIGH);
  }
  else
  {
    digitalWrite(Q0_0, LOW);
  }
}

After running the previous code, you will obtain an IP address. To access your ESP32 PLC, simply type "http://[ip address]" in your web browser, making sure you are on the same subnet to which it is connected. This will establish a connection between your computer and the webserver hosted on your ESP32, enabling you to interact with the HTTP code you have implemented and control the on/off status of a LED on your ESP32 PLC.

If everything is configured correctly, you should be able to see this webpage:
ESP32 web server webpage

Optimizing ESP32 WiFi web server connectivity: 

SSID​ scanning essentials

If you're unable to connect to the same subnet, it's possible that your ESP32 doesn't recognize the Wi-Fi SSID you're trying to connect to. To verify if this is the issue, you can print the Wi-Fi status. If the print shows a value of 1, it indicates "WL_NO_SSID_AVAIL," meaning no SSID is available.

To ensure that your ESP32 is correctly detecting the Wi-Fi networks with its antenna, you can use the following code to scan and list all the SSIDs it detects:

#include <WiFi.h>

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

  // Start Wi-Fi scanning
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);

  Serial.println("Scanning Wi-Fi networks...");
  int numNetworks = WiFi.scanNetworks();

  if (numNetworks == 0) {
    Serial.println("No Wi-Fi networks found.");
  } else {
    Serial.print("Found ");
    Serial.print(numNetworks);
    Serial.println(" Wi-Fi networks:");

    for (int i = 0; i < numNetworks; i++) {
      Serial.print("Network SSID: ");
      Serial.println(WiFi.SSID(i));
    }
  }
}

void loop() {
  // Your main code here
}

Once you see the list of available networks on the screen, you can choose one from the list to connect your ESP32 to. This connection is necessary to set up a web server on your ESP32 PLC.

Enhancing ESP32 webserver performance with SD card storage


The ESP32 PLCs are equipped with a micro SD card reader to facilitate external storage and retrieval of data. Therefore, you can use a micro SD card to load all the files of the web page, saving flash memory on the ESP32, and allowing the creation of a larger web page. From the code of the previous example, below is how to do it using the SD.h library of the Arduino IDE.


Create a function to get the appropiate HTML code depending of the LED status and call it from the handlers instead of calling the SendHTML() function:

String get_html(uint8_t ledStatus){
  String ptr="";
  if (ledStatus){
    html1=SD.open("/led_on.html", FILE_READ);
    if (!html1) { 
    Serial.println("Card failed, or not present");
    }
    else {
      for (int n = 0 ; n < html1.size() ; n++){
ptr += (char)html1.read();
}
html1.close();
}
}
else{
    html2=SD.open("/led_off.html", FILE_READ);
    if (!html2) { 
        Serial.println("Card failed, or not present");
    }
    else {
      for (int n = 0 ; n < html2.size() ; n++){
        ptr += (char)html2.read();
      }
      html2.close();
}
}
return ptr;
}

Write the needed handlers for the different files of the webpage, in this case we will use a CSS file, an image and the bootstrap framework:

void handle_styleCSS() {
  File file = SD.open("/style.css");
  if (file) {
    server.streamFile(file, "text/css");
    file.close();
  }
}

void handle_img1() {
  File file = SD.open("/img1.jpg");
  if (file) {
    server.streamFile(file, "image/jpeg");
    file.close();
  }
}

void handle_bootstrapCSS() {
  File file = SD.open("/bootstrap-5.0.2-dist/css/bootstrap.min.css");
  if (file) {
    server.streamFile(file, "text/css");
    file.close();
  }
}

void handle_bootstrapJS() {
  File file = SD.open("/bootstrap-5.0.2-dist/js/bootstrap.bundle.min.js");
  if (file) {
    server.streamFile(file, "application/javascript");
    file.close();
  }
}

Initialize the SD inside the setup() function, where the chip select (CS) is the 13:

pinMode(chipSelect, OUTPUT);

if (!SD.begin(chipSelect)) {
  Serial.println("initialization failed");
  while (true);
}

Serial.println("initialization done.");

Using the server.on() statement associate some URL paths with its corresponding handling function created above:

server.on("/style.css", HTTP_GET, handle_styleCSS);
server.on("/img1.jpg", HTTP_GET, handle_img1);
server.on("/bootstrap-5.0.2-dist/css/bootstrap.min.css", HTTP_GET, handle_bootstrapCSS);
server.on("/bootstrap-5.0.2-dist/js/bootstrap.bundle.min.js", HTTP_GET, handle_bootstrapJS);

Note that this example uses the framework bootstrap which must first be downloaded previously to the SD card.


Remember that in the first example no micro SD card was used to store the files, and they were loaded directly from the program. Now, the files need to be written inside the micro SD card before executing the code. We recommend doing this manually by moving the files to the SD card from your PC. However, you can also write them from the code. For instance:

html1=SD.open("/led_on.html", FILE_WRITE);
html1.println(SendHTML(HIGH));
html1.close();
 
html2=SD.open("/led_off.html", FILE_WRITE);
html2.println(SendHTML(LOW));
html2.close();

Implementing user registration on ESP32 web servers. ​Secure data handling

To enhance the previous code for saving variables on the web server, we'll introduce a new webpage accessible through the IP address, specifically at "ip.address/signin." On this page, users will encounter a registration form prompting them for their name and password. It is crucial to assign names to all input elements in the HTML file. Below is an example of how the HTML file might look:


<form action="/signin" method="POST">
	​​<label for="user">User: </label>
	​​<input type="text" id="user" name="user">
  	​​<label for="pwd">Password: </label>
  	​<input type="password" id="pwd" name="pwd">
  	​​<input type="submit" value="Submit">
</form>


To incorporate the changes in the main code, we'll first introduce a new function named get_index() to retrieve the HTML code for the registration page:


String get_index(){
  String ptr="";
  File html = SD.open("/index.html", FILE_READ);
  if (!html) { 
    Serial.println("Card failed, or not present");
  }
  else {
    for (int n = 0 ; n < html.size() ; n++){
      ptr += (char)(html.read());
    }
    html.close();
  }
  return ptr;
}


Additionally, a handler function needs to be implemented. This handler function will take user inputs from the webpage and save them to a "file.txt":


void handle_SignedIn() {
  String username = server.arg("user");
  String password = server.arg("pwd");

  String response = "Name: " + username + " Password: " + password;

  File users = SD.open("/users.txt", FILE_APPEND);
  if(!users) {
    Serial.println("Could not open the file");
  }
  else {
    users.println(response);
    users.close();
  }

  server.send(200, "text/html", get_index());
}


Inside the setup() function needs to be written the function to call the handler:


server.on("/signin", handle_SignedIn);


Leveraging ESP32 PLC for efficient web server solutions in Industrial Automation

The guide from Industrial Shields demonstrates setting up an ESP32 PLC as a web server, emphasizing connectivity, digital IO handling, and SD card use for web content manegement. This showcases the ESP32's potential in industrial applications, offering a practical example of integrating web-based control.

Buscar en nuestro blog

Crear un servidor web con ESP32 PLC
Boot & Work Corp. S.L., Queralt del Águila Munté 5 de diciembre de 2023
Compartir

¿Estás buscando tu Controlador Lógico Programable ideal?

Echa un vistazo a esta comparativa de producto de varios controladores industriales basados en Arduino.

Comparamos entradas, salidas, comunicaciones y otras especificaciones con las de los equipos de otras marcas destacadas.


Industrial PLC comparison >>>