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
Este código muestra cómo configurar un servidor web utilizando ESP32 PLC. Se basa en dos bibliotecas, WiFi.h y WebServer.h, proporcionadas por el IDE de Arduino.
Al ejecutar este código, se establece un servidor web en el ESP32. Este servidor ofrece una página web accesible desde un ordenador o un teléfono inteligente. En dicha página hay un botón que, al pulsarlo, permite activar y desactivar una salida digital (en este caso, Q0.0) del ESP32 PLC. Esta interacción se facilita mediante el código HTML y CSS integrado en la página, que ofrece una interfaz sencilla y eficaz.
Asegúrate de seleccionar el modelo adecuado de ESP32 PLC en el IDE de Arduino para garantizar la compatibilidad y el funcionamiento correcto.
En resumen, este código es un ejemplo práctico de cómo crear una interfaz web para manejar una función específica (Q0.0) de un ESP32 PLC mediante una red Wi-Fi.
#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);
}
}
Después de ejecutar el código anterior, obtendrás una dirección IP. Para acceder a tu ESP32 PLC, simplemente escribe "http://[dirección ip]" en tu navegador web, asegurándote de estar en la misma subred a la que está conectado. Esto establecerá una conexión entre tu ordenador y el servidor web alojado en tu ESP32. De este modo, te perimte interactuar con el código HTTP que has implementado y controlar el estado de encendido/apagado de un LED, en tu ESP32 PLC.
Si todo está configurado correctamente, deberías poder ver esta página web:

Optimizing ESP32 WiFi web server connectivity:
SSID scanning essentials
Si enfrentas problemas para conectar tu ESP32 a la misma subred, puede que el dispositivo no esté reconociendo el SSID de la red Wi-Fi a la que intentas acceder. Para confirmar si este es el problema, es muy útil imprimir el estado de la conexión Wi-Fi. Si el resultado muestra un valor de 1, esto señala "WL_NO_SSID_AVAIL", indicando que no se encuentra disponible ningún SSID.
Para garantizar que tu ESP32 detecta adecuadamente las redes Wi-Fi utilizando su antena, puedes implementar el siguiente código. Este script te permite escanear y enumerar todos los SSIDs que el dispositivo logra detectar, asegurando una configuración óptima y eficiente de tu servidor web WiFi:
#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
}
Una vez que veas la lista de redes disponibles en la pantalla, puedes elegir una de la lista para conectar tu ESP32. Esta conexión es necesaria para configurar un servidor web en tu ESP32 PLC.
Mejorando el rendimiento del servidor web de ESP32 con almacenamiento en tarjeta SD
Los ESP32 PLC están equipados con un lector de tarjetas micro SD. Para facilitar el almacenamiento externo y la recuperación de datos. Por lo tanto, puedes utilizar una tarjeta micro SD para cargar todos los archivos de la página web. Ahorrando así, memoria flash en el ESP32 y permitiendo la creación de una página web más grande. A continuación, se muestra cómo hacerlo utilizando la biblioteca SD.h del IDE de Arduino, a partir del código del ejemplo anterior.
Crea una función para obtener el código HTML apropiado. Dependiendo del estado del LED y llámala desde los controladores, en lugar de llamar a la función SendHTML():
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;
}
Escribe los controladores necesarios para los diferentes archivos de la página web. En este caso utilizaremos un archivo CSS, una imagen y el framework de Bootstrap:
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();
}
}
Inicializa la tarjeta SD dentro de la función setup(), donde el chip select (CS) es el 13:
pinMode(chipSelect, OUTPUT);
if (!SD.begin(chipSelect)) {
Serial.println("initialization failed");
while (true);
}
Serial.println("initialization done.");
Utilizando la instrucción server.on(), vincula algunas rutas de URL con su correspondiente función de gestión creada anteriormente:
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);
Ten en cuenta que este ejemplo utiliza el framework Bootstrap, que debe descargarse previamente en la tarjeta SD.
Recuerda que en el primer ejemplo, no se utilizó una tarjeta micro SD para almacenar los archivos. Estos se cargaban directamente desde el programa. Ahora, es necesario escribir los archivos dentro de la tarjeta micro SD, antes de ejecutar el código. Recomendamos hacer esta tarea de forma manual, moviendo los archivos a la tarjeta SD desde tu PC. No obstante, también puedes escribirlos desde el código. Por ejemplo:
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();
Implementación de registro de usuarios en servidores web ESP32. Gestión segura de datos
Para mejorar el código anterior de guardar variables en el servidor web, se introduce una nueva página web accesible, a través de la dirección IP, específicamente en "ip.address/signin". En esta página, los usuarios encontrarán un formulario de registro que les solicitará su nombre y contraseña. Es crucial asignar nombres a todos los elementos de entrada en el archivo HTML. A continuación, se muestra un ejemplo de cómo podría verse el archivo HTML:
<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>
Para incorporar los cambios en el código principal, primero se introduce una nueva función llamada get_index(), para recuperar el código HTML de la página de registro:
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;
}
Además, se necesita implementar una función de control. Esta función recogerá las entradas de los usuarios, desde la página web y las guardará en un 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());
}
Dentro de la función setup(), se debe escribir la función para llamar al controlador:
server.on("/signin", handle_SignedIn);
Aprovechando ESP32 PLC para soluciones eficientes de servidores web en automatización industrial
Esta guía de Industrial Shields explica cómo establecer un ESP32 PLC como un servidor web. Poniendo énfasis en la conectividad, la gestión de entradas y salidas digitales, y el uso de tarjetas SD, para administrar el contenido web. De esta forma, se muestra la utilidad del ESP32 en el sector industrial, mostrando de manera concreta cómo se puede implementar el control remoto, mediante interfaces web en dichas aplicaciones.

Crear un servidor web con ESP32 PLC