Icono del sitio AranaCorp

Programación de un ESP32 a través de WiFi con el IDE de Arduino (OTA)

Una característica muy práctica en el campo del IoT es la posibilidad de programar un microcontrolador conectado, como un ESP32, a través de WiFi. Esta técnica se denomina programación Over-The-Air (OTA).

 

Hardware

 

Principio de funcionamiento

En principe, un programme est téléversé sur le NodoMCU ESP32 par une connexion série avec le port USB. L’ordinateur communique le programme au microcontrôleur. Lorsque deux appareils sont connectés au même réseau Wifi, ils peuvent communiquer ensemble. On peut donc téléverser un code grâce au réseau Wifi sans avoir à se connecter à chaque microcontrôleur.

También es posible cargar un código al NodeMCU cuando está configurado como un Punto de Acceso WiFi. En este caso, la computadora utilizada para la programación debe estar conectada a la red de NodeMCU. El código completo se encuentra al final de este tutorial.

 

Añadir firmware ArduinoOTA

La biblioteca ArduinoOTA está disponible cuando se instala el gestor de ESP32. Para configurar la programación OTA, es necesario instalar el firmware. Para ello, puede utilizar el ejemplo BasicOTA.ino disponible en el IDE de Arduino.

Asegúrate de sustituir ssid y password por los identificadores de tu red WiFi.

#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

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

unsigned long previousMillis;

void setup() {
  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();
  }
  
    // Port defaults to 3232
  // ArduinoOTA.setPort(3232);

  // Hostname defaults to esp3232-[MAC]
  //ArduinoOTA.setHostname("esp3232");

  // No authentication by default
  // ArduinoOTA.setPassword("admin");

  // Password can be set with it's md5 value as well
  // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
  // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");

  ArduinoOTA
    .onStart([]() {
      String type;
      if (ArduinoOTA.getCommand() == U_FLASH)
        type = "sketch";
      else // U_SPIFFS
        type = "filesystem";

      // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
      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.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  ArduinoOTA.handle();
}

Anote la dirección IP local del dispositivo (aquí: 192.168.1.33).

Una vez que este código se ha cargado a través de la comunicación serie, usted será capaz de cargar un código a través de Wifi. Pulse el botón RST o EN en su ESP y reinicie el IDE Arduino.

 

Modifique su programa antes de subirlo

Colocamos el código de inicialización en la función initOTA(). Así será fácil copiarlo para otros proyectos. Y añadiremos una pantalla en el puerto serie para comprobar que el código ha sido modificado.

ATENCIÓN: El código de inicialización ArduinoOTA debe estar presente en todos los códigos que subas o perderás la capacidad de realizar transmisiones aéreas.

#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

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

unsigned long previousMillis;

void setup() {
  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();
  }

  initOTA();

  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  ArduinoOTA.handle();

  if (millis() - previousMillis >= 500) {
    previousMillis = millis();
    Serial.println(F("Code has been update"));
  }
}


void initOTA() {
  // Port defaults to 3232
  // ArduinoOTA.setPort(3232);

  // Hostname defaults to esp3232-[MAC]
  ArduinoOTA.setHostname("ESP32");

  // No authentication by default
  // ArduinoOTA.setPassword("admin");

  // Password can be set with it's md5 value as well
  // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
  // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");

  ArduinoOTA
  .onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH)
      type = "sketch";
    else // U_SPIFFS
      type = "filesystem";

    // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
    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();
}

Once you have modified your code, under «Tool> Port», select your card from the network ports. (if the network port is not displayed, see the next chapter below)

A continuación, puede cargar su código como lo haría con la comunicación serie.

Seleccione de nuevo el puerto serie y abra el monitor serie para comprobar que el código se ha modificado.

 

Si el puerto de red no se muestra en el IDE de Arduino

Si el puerto de red no está presente en las opciones del IDE Arduino, tendrás que hacer un poco de trabajo. Tienes que ir al Centro de redes y recursos compartidos

A continuación, vaya a «Modificar los parámetros de la tarjeta».

Haga clic con el botón derecho en su red y vaya a propiedades

A continuación, puede desmarcar la opción «Protocolo de Internet versión 6 (TCP)».

Si vuelves al IDE de Arduino después de reiniciarlo, en «Herramienta > Puerto» deberías ver que aparece la opción de puerto de red.

Puede volver a comprobar IPv6 una vez que se haya reconocido su puerto de red.

 

Bonificación: visualización de mensajes de serie OTA

La possibilité de téléverser un programme par Wifi est très appréciable mais, il est bon de noter, que l’on perd la capacité de debugger avec le moniteur série. Il est possible de créer une interface Web sur laquelle on peut afficher des informations provenant du NodoMCU ESP32.

Aquí veremos cómo usar la librería RemoteDebug para conectarse al microcontrolador vía telnet y recuperar los mensajes enviados.

#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <RemoteDebug.h>

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

RemoteDebug Debug;

unsigned long previousMillis;

void setup() {
  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();
  }

  // init remote debug
  Debug.begin("ESP32");  
  
  initOTA();

  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  ArduinoOTA.handle();
  Debug.handle();
  
  if (millis() - previousMillis >= 500) {
    previousMillis = millis();
    Debug.println(F("Code has been update"));
  }
}


void initOTA() {
  // Port defaults to 3232
  // ArduinoOTA.setPort(3232);

  // Hostname defaults to esp3232-[MAC]
  ArduinoOTA.setHostname("ESP32");

  // No authentication by default
  // ArduinoOTA.setPassword("admin");

  // Password can be set with it's md5 value as well
  // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
  // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");

  ArduinoOTA
  .onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH)
      type = "sketch";
    else // U_SPIFFS
      type = "filesystem";

    // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
    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();
}

Para ver los mensajes enviados a través de RemoteDebug, vamos a utilizar el software PuTTy que ya hemos visto varias veces. Para esta aplicación, vamos a configurar PuTTy en telnet utilizando la dirección IP recuperada del monitor serie.

 

Bono 2: Programación OTA en modo Punto de Acceso

Il est possible d’utiliser le réseau créer par le NodoMCU ESP32 en mode Access Point. Pour cela vous pouvez télecharger le code suivant via le port série. Vous devrez ensuite connecter votre ordinateur au réseau du NodeMCU pour pouvoir téleverser un nouveau code par Wifi.

#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

const char *ssid = "AC-ESP32";
const char *passphrase = "123456789";

IPAddress local_IP(192,168,4,22);
IPAddress gateway(192,168,4,9);
IPAddress subnet(255,255,255,0);

unsigned long previousMillis;
void setup() {
 Serial.begin(115200);
 Serial.println("Booting");

 //AP config
 Serial.print("Setting soft-AP configuration ... ");
 Serial.println(WiFi.softAPConfig(local_IP, gateway, subnet) ? "Ready" : "Failed!");
 Serial.print("Setting soft-AP ... ");
 Serial.println(WiFi.softAP(ssid,passphrase) ? "Ready" : "Failed!");
   
 initOTA();
 Serial.println("Ready");
 Serial.print("IP address: ");
 Serial.println(WiFi.localIP());
}
void loop() {
 ArduinoOTA.handle();
 if (millis() - previousMillis >= 500) {
   previousMillis = millis();
   Serial.println(F("Code has been update via Wifi"));
 }
}
void initOTA() {
 // Port defaults to 3232
 // ArduinoOTA.setPort(3232);
 // Hostname defaults to esp3232-[MAC]
 ArduinoOTA.setHostname("ESP32");
 // No authentication by default
 // ArduinoOTA.setPassword("admin");
 // Password can be set with it's md5 value as well
 // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
 // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");
 ArduinoOTA
 .onStart([]() {
   String type;
   if (ArduinoOTA.getCommand() == U_FLASH)
     type = "sketch";
   else // U_SPIFFS
     type = "filesystem";
   // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
   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();
}

Fuentes

Salir de la versión móvil