Tutorial del Internet de las Cosas y Bluetooth con el ESP32
Juan Antonio Villalpando
Volver al índice del tutorial
____________________________
230.- Wemos D1 R32 ESP32. OTA (Over The Air). Carga de programa por WiFi.
- Esto trata de cargar un programa en el ESP32 por WiFi, es decir sin estar conectado por cable USB al ordenador.
- Se suele utilizar cuando queremos modificar un programa ya cargado y no tenemos acceso a la tarjeta por cable USB.
- Necesitamos que el ordenador y la tarjeta del ESP32 estén en la misma red.
- También necesitamos tener Python en nuestro ordenador.
______________________________________________________
1.- Instalamos Python en nuestro ordenador.
- Vamos a: https://www.python.org/downloads/release/python-368/
- y bajamos el archivo: python-3.6.8-embed-amd64.zip

- Lo descomprimimos en C:\Archivos de Programa (x86)\Python

- Vamos a Propiedades del sistema / Variables de entorno...
- Editamos PATH
- Agregamos al principio C:\Program Files (x86)\Python\;
- Fíjate que termina en punto y coma;

________________________________
2.- Creación del Puerto de Red esp32- at 192.168.1.4
- https://github.com/espressif/arduino-esp32/tree/master/libraries/ArduinoOTA
- Veamos este ejemplo, se trata simplemente de cargar y modificar la aplicación de parpadeo Blink.
- En principio lo cargamos con el cable USB conectado a nuestro ordenador y a la tarjeta.

|
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
const char* ssid = "Nombre_de_tu_red_Wifi";
const char* password = "La_clave_de_tu_Wifi";
void setup() {
pinMode(2, OUTPUT); // El LED azul.
Serial.begin(115200);
Serial.println("Booting");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Connection Failed! Rebooting...");
delay(5000);
ESP.restart();
}
ArduinoOTA
.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH)
type = "sketch";
else
type = "filesystem";
Serial.println("Start updating " + type);
})
.onEnd([]() {
Serial.println("\nEnd");
})
.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
})
.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});
ArduinoOTA.begin();
Serial.print("IP: ");
Serial.println(WiFi.localIP());
}
void loop() {
ArduinoOTA.handle();
digitalWrite(2, HIGH);
delay(1000);
digitalWrite(2, LOW);
delay(1000);
}
|
- Le echamos un vistazo al Monitor serie y a Herramientas.
- Observamos que en Herramientas se ha creado Puerto de Red: esp32-b4e62f62b1 at 192.168.1.4
- Si no te sale ese puerto, reinicia el IDE de Arduino.
- Es decir, que ahora podemos cargar los programas por WiFi (o por el COM22)

________________________________
3.- Modificación de la aplicación por WiFi.
- Ahora quitamos el cable USB de la tarjeta.
- Pero evidentemente la debemos alimentar con una pila, batería,...

- Aunque este tipo de pilas de 9V, si está un poco gastada no dará la suficiente potencia para que funcione bien el WiFi.
- Es mejor alimentarlo con una fuente de alimentación de más potencia para que el WiFi funcione con más fuerza.

- Ahora modificamos el programa, por ejemplo ponemos otra cantidad en los delay.
digitalWrite(2, HIGH);
delay(500);
digitalWrite(2, LOW);
delay(200);
- Y subimos el código estando marcado Puerto: esp32- at 192.168.1.4
- Observamos que el código ha subido al ESP32 por WiFi y ha modificado el delay del código anterior.
________________________________
- Comentarios.
- La primera vez que subas el código debes hacerlo mediante el cable USB.
- Las siguientes veces, puedes quitar el cable USB y subirlo por WiFi.
- El código siempre debe llevar todas las instrucciones correspondiente a ArduinoOTA
- Cuando la conexión es por Puerto de Red, no funciona el Monitor Serie.
- Si reinicias la tarjeta pulsando el botón de Reset, espera como 1 minutos para que pueda conectar con el Wifi antes de subir el código.
- Aunque existen protecciones, intenta no alimentar a la vez al módulo con el cable USB y con el conector de la batería.
- Si te sale este error, es que no está bien establecido el PATH de "python.exe"

________________________________
________________________________
________________________________
________________________________
4.- Otro ejemplo.
- Cuando se ejecuta la aplicación, conecta con nuestra red WiFi.
- Entra un servidor web y presenta una página web solicitando nombre y contraseña, son admin y admin.

- Saldrá un navegador de archivos para poder localizar un archivo de programa de Arduino, localizamos por ejemplo el:
C:\Program Files (x86)\Arduino\examples\01.Basics\Blink\Blink.ino
- Lo subimos y lo cargamos en la placa.

- Empezará a parpadear.
|
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <Update.h>
const char* host = "esp32";
const char* ssid = "Nombre_de_tu_red_Wifi";
const char* password = "La_clave_de_tu_Wifi";
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);
}
|
- Una vez cargado el Blink.ino, sobreescribirá a la aplicación anterior, es decir no podemos volver a utilizar este procedimiento para subir otro archivo.
- Si queremos seguir subiendo archivos mediante este método, lo códigos de esos archivos deberán llevar el código de subida OTA.
- O mejor aún, volviendo a subir el codigo_subida_web.ino y Seleccionando otro archivo .ino.
_______________________________________________________________
2.- Otro ejemplo de OTA.
https://lastminuteengineers.com/esp32-ota-web-updater-arduino-ide/
- Creamos el archivo .bin y lo subimos.
- Consulta el tutorial 9130f.htm
_______________________________
|