Seguimos con el tutorial anterior donde vimos cómo encender un LED en un ESP8266 y el ESP32 a través de un formulario web, ampliando el ejemplo para añadir el control PWM para variar la intensidad.
Haremos referencia al ESP8266, pero el mismo código es compatible para el ESP32, ajustando el nombre de las librerías. Al final tenéis el código tanto para el ESP8266 como para el ESP32.
Llevamos dos entradas, una sobre cómo recibir un texto, y otra sobre cómo interpretar el texto recibido para encender o apagar un LED, viendo cómo emplear un formulario web como forma sencilla de transmitir información entre la página web del cliente y el ESP8266 como backend.
En este tutorial vamos a actuar sobre un LED en el ESP8266 usando un PWM para variar la intensidad de un LED. Esto nos va a permitir mostrar cómo interpretar números y además, ¡vamos a añadir nuestro primer fragmento de JavaScript!
Estos ejemplos dedicados a formularios web son muy sencillos, pero nos permiten introducir progresivamente conceptos como Endpoint, Backend, html, JavaScript… que son la base de lo que, en próximas entradas, serán llamadas AJAX o Websockets.
Y ya vale de introducción. ¡Vamos al trabajo!
Nuestro programa principal queda exactamente igual que en el ejemplo anterior.
#include <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include <FS.h>
#include "config.h" // Sustituir con datos de vuestra red
#include "Server.hpp"
#include "ESP8266_Utils.hpp"
void setup(void)
{
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
SPIFFS.begin();
ConnectWiFi_STA();
InitServer();
}
void loop(void)
{
}
Por su parte, el fichero ‘Server.hpp’ también es muy parecido al anterior.
AsyncWebServer server(80);
void handleFormPWM(AsyncWebServerRequest *request)
{
String pwmValue = request->arg("pwmValue");
Serial.print("PWM:\t");
Serial.println(pwmValue);
// No invertido
//analogWrite(LED_BUILTIN, pwmValue.toInt());
// Invertido
analogWrite(LED_BUILTIN, 1023 - pwmValue.toInt());
request->redirect("/");
}
void InitServer()
{
server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.html");
server.on("/LED", HTTP_POST, handleFormPWM);
server.onNotFound([](AsyncWebServerRequest *request) {
request->send(400, "text/plain", "Not found");
});
server.begin();
Serial.println("HTTP server started");
}
Seguimos tenemos un Endpoint para ‘/LED’ bajo peticiones POST, asociado a la función de callback ‘handleFormPWM(…)‘. En esta función leemos el parámetro enviado por el formulario ‘pwmValue’ y lo convertimos a integer con el método ‘toInt()’ de la clase String.
En este ejemplo, invertimos el valor recibido ya que el LED integrado en la placa tiene salida invertida (HIGH es apagado, y LOW encendido). Si usáis otra salida PWM, usar el código comentado sin invertir.
Respecto a la página ‘index.html’ ubicada en ‘data’, que subirá al SPIFFS, queda de la siguiente manera
<!DOCTYPE html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>ESP8266 Forms</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>Form example</h1>
<form action="/LED" method="post">
Slider:<br>
<input type="range" id="pwmInput" name="pwmValue" min="0" max="1023" value="500" onchange="updateTextInput(this.value);" >
<input type="number" id="textInput" onchange="updateTextInput(this.value);" value="500" style="width:50px">
<label for="pwmInput">PWM</label><br>
<button type="submit" value="Submit">Send</button>
</form>
<script>
function updateTextInput(val) {
console.log(val);
document.getElementById('pwmInput').value = val;
document.getElementById('textInput').value = val;
}
</script>
</body>
</html>
Donde tenemos un slider ‘pwmInput’ que va entre 0 a 1023 (el rango de PWM en el ESP8266) y cuyo valor por defecto es 500. También tenemos un cuadro de texto ‘textInput’. El usuario puede cambiar el valor del PWM bien usando el slider o el cuadro de texto y ambos valores están ‘vinculados’.
Para esta ‘vinculación’ entre el slider y el cuadro de texto añadimos un poquito de JavaScript. En este caso es tan sencillo, que lo añadimos en el propio ‘.html’. Aunque lo normal es que el JavaScript lo tengamos como ficheros independientes, como veremos en próximas entradas.
En este script simplemente tenemos una función updateTextInput(…) donde mostramos el valor por la consola del navegador, y sincronizamos los valores del slider y el cuadro de texto.
Por otro lado, tenemos esta función asociada a los eventos ‘onchange(…)’ tanto del slider como del textbox. Ambas funciones envían el valor de su propio control.
Finalmente, al enviar al pulsar el botón “Send” se envía el formulario al Endpoint ‘/LED’ bajo el método POST que tenemos definido en el ESP8266, pasando el parámetro pwmValue asociado en el slider con ‘name=“pwmValue”‘.
Resultado
Si ahora accedemos a nuestra, (si, una vez más, feísima) página web, veremos nuestro slider y nuestro texbox. Podemos arrastrar el slider o escribir directamente el valor que queramos en el textbox, y vemos que el otro control se actualizar correctamente.
Si pulsamos el botón de enviar veremos el valor que hemos elegimos se muestra en la consola del navegador y en el puerto serie del ESP8266. Y, por supuesto, el LED integrado en la placa se ilumina con la intensidad que hemos elegido.
¿A que no ha sido tan difícil? Bueno, un ejemplo sencillo en el que ya vamos viendo todas las partes habituales en un proyecto con ESP8266 (métodos html, backend, endpoint, javascript… ¿se va viendo no?)
En la próxima entrada veremos cómo hacer lo mismo con un LED RGB, y será la última entrada que dedicaremos a los formularios Web, para después avanzar y meternos en mecanismos más sofisticados como Ajax. ¡Hasta pronto!
Descarga el código
Todo el código de esta entrada está disponible para su descarga en Github.
Versión para el ESP8266: https://github.com/luisllamasbinaburo/ESP8266-Examples
Versión para el ESP32: https://github.com/luisllamasbinaburo/ESP32-Examples