Una de las características más interesantes que tienen los ESP8266 es la capacidad de cargar remotamente un firmware concreto, es decir, programación via OTA (Over The Air). Analicemos brevemente como utilizar este mecanismo.

sku_385646_1

Descripción General

La forma más básica que disponemos para programar un ESP8266 (en adelante, ESP) pasa por emplear el puerto serie que trae el módulo. Sin embargo, no es la única. También es posible utilizar la red WiFi para esta tarea.

El proceso, a grandes rasgos, consiste en iniciar un servidor en el nodo que acepte el bytestream y lo escriba en la memoria del dispositivo.

Este proceso reemplaza el anterior firmware que tuviera el nodo, y lo reinicia. Para que esto sea posible, el nuevo software a desplegar debe acomodarse en el espacio libre que dejó el software anterior (de otro modo, el nuevo firmware reemplazaría parte del actual y dejaría el sistema inconsistente). El siguiente diagrama muestra claramente el proceso:

Para una información más detallada, véase Update process – memory view

Requisitos Hardware

Dado que el proceso implica disponer de suficiente memoria para alojar al mismo tiempo el firmware que tiene el nodo y el nuevo que se desea desplegar, es recomendable emplear un ESP que tenga la mayor capacidad posible. El nodo más empleado es el ESP-12, que cuenta con 32 Mib (4 MiB) de flash. Generalmente, se deja 1 MiB para el sistema de ficheros SPIFFS, por lo que se dispone de, como mucho, 1.5 MiB de memoria de programa. Esto es más que suficiente para la mayoría de aplicaciones.

Procedimiento Básico

NOTA: La primera vez que se programa el nodo (que generalmente viene con un firmware AT), no suele estar disponible la opción de programar vía OTA, por lo que necesitaremos usar el puerto serie. Utilizaremos la versión 1.7.8 del IDE de Arduino, junto con la librería ArduinoOTA.

El procedimiento más básico es sencillo de implementar. El siguiente sketch contiene lo mínimo necesario (la configuración de la red WiFi no se detalla, pues es algo común al uso del ESP en general):

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <ArduinoOTA.h>
void setup() {
  WiFi.mode(WIFI_STA);
  WiFi.begin("ssid", "password");
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    ESP.restart();
  }

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

Básicamente, como en muchos otros módulos, se configura el sistema en el setup() usando el método ArduinoOTA.begin() y en cada iteración del bucle de eventos, se comprueba si hay algún programador intentando cargar un nuevo sketch, con el método ArduinoOTA.handle(). La librería se encarga de todos los detalles relacionados con la programación, por lo que no será necesario hacer nada más.

La librería incluye varios métodos para establecer callbacks, que serán invocados en diferentes partes del proceso: al iniciar (onStart), durante el progreso de carga (onProgress), al finalizar (onEnd) y en caso de ocurrir algún error (onError).  Un ejemplo de su uso:

ArduinoOTA.onStart([]() {
  Serial.println("Start");
});

ArduinoOTA.onEnd([]() {
  Serial.println("\nEnd");
});

ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
  Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});

ArduinoOTA.onError([](ota_error_t error) {
  // error could be: OTA_AUTH_ERROR, 
  //                 OTA_BEGIN_ERROR, 
  //                 OTA_CONNECT_ERROR, 
  //                 OTA_RECEIVE_ERROR, 
  //                 OTA_END_ERROR
  Serial.printf("Error[%u]: ", error);
});

Programando el Nodo

Para hacer la carga de un nuevo firmware, es necesario saber la IP del nodo, y el puerto en el que escucha el cargador (por defecto, 8266). Además, obviamente, será necesario que estemos conectados de alguna forma a la misma red que el nodo (no es necesario que estemos en el mismo segmento de red).

Generalmente, si estamos en la misma red, el IDE de Arduino descubrirá automáticamente el host y el puerto, y dispondremos de esa opción en el menú Herramientas > Puerto, en la sección Network ports.

network ports

Puerto OTA en el IDE

También es posible programar utilizando directamente la herramienta espota.py (muy conveniente si no usas el IDE) incluida en el SDK de Arduino para el ESP. Solo necesitas especificar el host, el puerto y el firmware (.bin) que quieres cargar, por ejemplo:

$ espota.py -i 192.168.4.1 -p 8266 -f sketch.cpp.bin

Opciones Avanzadas

La configuración arriba indicada es la más sencilla. Sin embargo, existen varias opciones que se pueden tener en cuenta:

Seguridad. Es posible establecer algunos mecanismos básicos de seguridad, como cambiar el puerto por defecto donde escuchará el servicio, y establecer una contraseña, para reducir los riesgos de acceso no autorizado.

Web updates. También es posible crear un servidor web dentro del nodo, y servir una página específica para realizar la carga del binario. De esta forma, se evita la necesidad de emplear la herramienta espota.py, pues directamente desde el navegador (u otras herramientas CLI como curlwget) es posible iniciar la actualización.

Referencias