Está en la página 1de 15

ESP32 Programación por aire (OTA) – Web

Updater Arduino IDE


Guía rápida que muestra cómo programar por aire (OTA) con el ESP32 utilizando el
actualizador web OTA en el IDE de Arduino. El Actualizador web OTA le permite
actualizar/cargar código nuevo a su ESP32 usando un navegador, sin necesidad de
realizar una conexión en serie entre el ESP32 y su computadora.

La programación OTA es útil cuando necesita actualizar el código de las placas ESP32 a
las que no se puede acceder fácilmente. El ejemplo que mostraremos aquí funciona
cuando el ESP32 y su navegador están en su red local.
La única desventaja de OTA Web Updater es que debe agregar el código para OTA en
cada boceto que cargue, para que pueda usar OTA en el futuro.

¿Cómo funciona el Actualizador web OTA?


 El primer boceto debe cargarse a través del puerto serie. Este boceto debe contener
el código para crear el actualizador web OTA, de modo que pueda cargar el código
más tarde con su navegador.
 El boceto de OTA Web Updater crea un servidor web al que puede acceder para
cargar un nuevo boceto a través del navegador web.
 Luego, debe implementar rutinas OTA en cada boceto que cargue, de modo que
pueda realizar las próximas actualizaciones/cargas por aire.
 Si carga un código sin una rutina OTA, ya no podrá acceder al servidor web y cargar
un nuevo boceto por aire.
Requisitos previos
Antes de continuar con este tutorial, debe tener instalado el complemento ESP32 en su
IDE de Arduino. Siga uno de los siguientes tutoriales para instalar el ESP32 en el IDE de
Arduino, si aún no lo ha hecho.

 Instalación de la placa ESP32 en Arduino IDE (instrucciones de Windows)


 Instalación de la placa ESP32 en Arduino IDE (instrucciones para Mac y Linux)

Actualizador web ESP32 OTA


Cuando instala el complemento ESP32 para Arduino IDE, instalará automáticamente la
biblioteca ArduinoOTA. Vaya a Archivo > Ejemplos > ArduinoOTA > OTAWebUpdater .
Debería cargarse el siguiente código.
/*
* OTAWebUpdater.ino Example from ArduinoOTA Library
* Rui Santos
* Complete Project Details https://randomnerdtutorials.com
*/

#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <Update.h>

const char* host = "esp32";


const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

WebServer server(80);

/*
* Login page
*/
const char* loginIndex =
"<form name='loginForm'>"
"<table width='20%' bgcolor='A09F9F' align='center'>"
"<tr>"
"<td colspan=2>"
"<center><font size=4><b>ESP32 Login
Page</b></font></center>"
"<br>"
"</td>"
"<br>"
"<br>"
"</tr>"
"<td>Username:</td>"
"<td><input type='text' size=25 name='userid'><br></td>"
"</tr>"
"<br>"
"<br>"
"<tr>"
"<td>Password:</td>"
"<td><input type='Password' size=25 name='pwd'><br></td>"
"<br>"
"<br>"
"</tr>"
"<tr>"
"<td><input type='submit' onclick='check(this.form)'
value='Login'></td>"
"</tr>"
"</table>"
"</form>"
"<script>"
"function check(form)"
"{"
"if(form.userid.value=='admin' && form.pwd.value=='admin')"
"{"
"window.open('/serverIndex')"
"}"
"else"
"{"
" alert('Error Password or Username')/*displays error message*/"
"}"
"}"
"</script>";

/*
* Server Index Page
*/

const char* serverIndex =


"<script
src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></
script>"
"<form method='POST' action='#' enctype='multipart/form-data'
id='upload_form'>"
"<input type='file' name='update'>"
"<input type='submit' value='Update'>"
"</form>"
"<div id='prg'>progress: 0%</div>"
"<script>"
"$('form').submit(function(e){"
"e.preventDefault();"
"var form = $('#upload_form')[0];"
"var data = new FormData(form);"
" $.ajax({"
"url: '/update',"
"type: 'POST',"
"data: data,"
"contentType: false,"
"processData:false,"
"xhr: function() {"
"var xhr = new window.XMLHttpRequest();"
"xhr.upload.addEventListener('progress', function(evt) {"
"if (evt.lengthComputable) {"
"var per = evt.loaded / evt.total;"
"$('#prg').html('progress: ' + Math.round(per*100) + '%');"
"}"
"}, false);"
"return xhr;"
"},"
"success:function(d, s) {"
"console.log('success!')"
"},"
"error: function (a, b, c) {"
"}"
"});"
"});"
"</script>";

/*
* setup function
*/
void setup(void) {
Serial.begin(115200);

// Connect to WiFi network


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());
/*use mdns for host name resolution*/
if (!MDNS.begin(host)) { //http://esp32.local
Serial.println("Error setting up MDNS responder!");
while (1) {
delay(1000);
}
}
Serial.println("mDNS responder started");
/*return index page which is stored in serverIndex */
server.on("/", HTTP_GET, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/html", loginIndex);
});
server.on("/serverIndex", HTTP_GET, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/html", serverIndex);
});
/*handling uploading firmware file */
server.on("/update", HTTP_POST, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
ESP.restart();
}, []() {
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START) {
Serial.printf("Update: %s\n", upload.filename.c_str());
if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max
available size
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_WRITE) {
/* flashing firmware to ESP*/
if (Update.write(upload.buf, upload.currentSize) !=
upload.currentSize) {
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_END) {
if (Update.end(true)) { //true to set the size to the current
progress
Serial.printf("Update Success: %u\nRebooting...\n",
upload.totalSize);
} else {
Update.printError(Serial);
}
}
});
server.begin();
}

void loop(void) {
server.handleClient();
delay(1);
}
Ver código sin procesar

Debe cambiar las siguientes líneas en el código para incluir sus propias credenciales de
red:
const char* ssid = "";
const char* contraseña = "";
El ejemplo de OTAWebUpdater para ESP32 crea un servidor web asíncrono donde puede
cargar código nuevo en su placa sin necesidad de una conexión en serie.
Sube el código anterior a tu placa ESP32. No olvide ingresar sus credenciales de red y
seleccionar la placa y el puerto serial correctos.

Después de cargar el código, abra el monitor serie a una velocidad de transmisión de


115200, presione el botón de activación de ESP32 y obtendrá la dirección IP de ESP32:

Ahora, puede cargar el código a su ESP32 por aire usando un navegador en su red local.
Para probar el Actualizador web OTA, puede desconectar el ESP32 de su computadora y
alimentarlo con un banco de energía, por ejemplo (esto es opcional, lo sugerimos para
imitar una situación en la que el ESP32 no está conectado a su computadora).

Actualizar código nuevo usando el actualizador


web OTA
Abra un navegador en su red e ingrese la dirección IP ESP32. Deberías obtener lo
siguiente:

Introduzca el nombre de usuario y la contraseña:


 Nombre de usuario : administrador
 contraseña : administrador
Puede cambiar el nombre de usuario y la contraseña en el código.
Nota:  Después de ingresar el nombre de usuario y la contraseña, será redirigido a la
URL /serverIndex . No necesita ingresar el nombre de usuario y la contraseña para
acceder a la URL /serverIndex . Por lo tanto, si alguien conoce la URL para cargar el
nuevo código, el nombre de usuario y la contraseña no protegen la página web para que
otros no puedan acceder a ella.
Debería abrirse una nueva pestaña en la URL /serverIndex . Esta página le permite cargar
un nuevo código a su ESP32. Debería cargar archivos .bin (veremos cómo hacerlo en un
momento).
Preparando el nuevo boceto
Al cargar un nuevo boceto por aire, debe tener en cuenta que debe agregar código para
OTA en su nuevo boceto, de modo que siempre pueda sobrescribir cualquier boceto con
uno nuevo en el futuro. Por lo tanto, le recomendamos que modifique el boceto de
OTAWebUpdater para incluir su propio código.
Con fines de aprendizaje, subamos un nuevo código que parpadee un LED (sin
demora). Copie el siguiente código en su IDE de Arduino.
/*
* Rui Santos
* Complete Project Details https://randomnerdtutorials.com
*/

#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <Update.h>

const char* host = "esp32";


const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

//variabls to blink without delay:


const int led = 2;
unsigned long previousMillis = 0; // will store last time LED was
updated
const long interval = 1000; // interval at which to blink
(milliseconds)
int ledState = LOW; // ledState used to set the LED

WebServer server(80);

/*
* Login page
*/

const char* loginIndex =


"<form name='loginForm'>"
"<table width='20%' bgcolor='A09F9F' align='center'>"
"<tr>"
"<td colspan=2>"
"<center><font size=4><b>ESP32 Login
Page</b></font></center>"
"<br>"
"</td>"
"<br>"
"<br>"
"</tr>"
"<td>Username:</td>"
"<td><input type='text' size=25 name='userid'><br></td>"
"</tr>"
"<br>"
"<br>"
"<tr>"
"<td>Password:</td>"
"<td><input type='Password' size=25 name='pwd'><br></td>"
"<br>"
"<br>"
"</tr>"
"<tr>"
"<td><input type='submit' onclick='check(this.form)'
value='Login'></td>"
"</tr>"
"</table>"
"</form>"
"<script>"
"function check(form)"
"{"
"if(form.userid.value=='admin' && form.pwd.value=='admin')"
"{"
"window.open('/serverIndex')"
"}"
"else"
"{"
" alert('Error Password or Username')/*displays error message*/"
"}"
"}"
"</script>";

/*
* Server Index Page
*/

const char* serverIndex =


"<script
src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></
script>"
"<form method='POST' action='#' enctype='multipart/form-data'
id='upload_form'>"
"<input type='file' name='update'>"
"<input type='submit' value='Update'>"
"</form>"
"<div id='prg'>progress: 0%</div>"
"<script>"
"$('form').submit(function(e){"
"e.preventDefault();"
"var form = $('#upload_form')[0];"
"var data = new FormData(form);"
" $.ajax({"
"url: '/update',"
"type: 'POST',"
"data: data,"
"contentType: false,"
"processData:false,"
"xhr: function() {"
"var xhr = new window.XMLHttpRequest();"
"xhr.upload.addEventListener('progress', function(evt) {"
"if (evt.lengthComputable) {"
"var per = evt.loaded / evt.total;"
"$('#prg').html('progress: ' + Math.round(per*100) + '%');"
"}"
"}, false);"
"return xhr;"
"},"
"success:function(d, s) {"
"console.log('success!')"
"},"
"error: function (a, b, c) {"
"}"
"});"
"});"
"</script>";

/*
* setup function
*/
void setup(void) {
pinMode(led, OUTPUT);

Serial.begin(115200);

// Connect to WiFi network


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());

/*use mdns for host name resolution*/


if (!MDNS.begin(host)) { //http://esp32.local
Serial.println("Error setting up MDNS responder!");
while (1) {
delay(1000);
}
}
Serial.println("mDNS responder started");
/*return index page which is stored in serverIndex */
server.on("/", HTTP_GET, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/html", loginIndex);
});
server.on("/serverIndex", HTTP_GET, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/html", serverIndex);
});
/*handling uploading firmware file */
server.on("/update", HTTP_POST, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
ESP.restart();
}, []() {
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START) {
Serial.printf("Update: %s\n", upload.filename.c_str());
if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max
available size
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_WRITE) {
/* flashing firmware to ESP*/
if (Update.write(upload.buf, upload.currentSize) !=
upload.currentSize) {
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_END) {
if (Update.end(true)) { //true to set the size to the current
progress
Serial.printf("Update Success: %u\nRebooting...\n",
upload.totalSize);
} else {
Update.printError(Serial);
}
}
});
server.begin();
}

void loop(void) {
server.handleClient();
delay(1);
//loop to blink without delay
unsigned long currentMillis = millis();

if (currentMillis - previousMillis >= interval) {


// save the last time you blinked the LED
previousMillis = currentMillis;

// if the LED is off turn it on and vice-versa:


ledState = not(ledState);

// set the LED with the ledState of the variable:


digitalWrite(led, ledState);
}
}
Ver código sin procesar

Como puede ver, hemos agregado el código "parpadeo sin demora" al código
OTAWebUpdater, para que podamos realizar actualizaciones más adelante.
Después de copiar el código en su IDE de Arduino, debe generar un archivo .bin .

Genere un archivo .bin en Arduino IDE


Guarde su boceto como LED_Web_Updater .
Para generar un archivo .bin a partir de su boceto, vaya a Boceto > Exportar binario
compilado

Se debe crear un nuevo archivo en el boceto de la carpeta. Vaya


a Bosquejo > Mostrar carpeta de bosquejo . Debe tener dos archivos en su carpeta
Sketch: el archivo .ino y el archivo .bin . Debe cargar el archivo .bin mediante el
actualizador web de OTA.
Cargue un nuevo boceto por aire al ESP32
En su navegador, en la página ESP32 OTA Web Updater, haga clic en el botón Elegir
archivo . Seleccione el archivo .bin generado anteriormente y luego haga clic
en Actualizar .
Después de unos segundos, el código debería cargarse correctamente.

El LED incorporado ESP32 debe estar parpadeando.

¡Felicidades! Has subido un nuevo código a tu ESP32 por aire.

Terminando
Las actualizaciones inalámbricas son útiles para cargar un nuevo código en su tablero
ESP32 cuando no es fácilmente accesible. El código OTA Web Updater crea un servidor
web al que puede acceder para cargar un nuevo código en su placa ESP32 utilizando un
navegador web en su red local.

También podría gustarte