Benvenuti ad un’altra puntata della nostra serie sulla gestione del firmware per il microcontrollore ESP32. In questo articolo, esploreremo un metodo non standard ma altamente efficace per aggiornare sia il firmware che il filesystem sul tuo ESP32. Questa tecnica utilizza una scheda SD per archiviare e trasferire i file di aggiornamento, fornendo una soluzione robusta e facilmente accessibile sia per gli sviluppatori che per gli appassionati.
Ci addentriamo in questo argomento, svilupperemo le conoscenze acquisite dai precedenti articoli della serie, che coprivano vari metodi per eseguire il flashing di file firmware compilati (.bin), aggiornamenti OTA con Arduino IDE, aggiornamenti basati su browser Web e auto- Aggiornamenti OTA dai server HTTP. In questo articolo, delineeremo i passaggi necessari per preparare il tuo ESP32 per gli aggiornamenti basati su scheda SD, discuteremo i vantaggi e gli svantaggi di questo approccio e forniremo una procedura dettagliata per configurare l’hardware e il software richiesti.
Alla fine di questo articolo, avrai una comprensione completa di come eseguire gli aggiornamenti del firmware e del filesystem ESP32 utilizzando una scheda SD e sarai in grado di prendere una decisione informata sull’idoneità di questo metodo per i requisiti specifici del tuo progetto.
Qui una selezione di esp32 ESP32 Dev Kit v1 - TTGO T-Display 1.14 ESP32 - NodeMCU V3 V2 ESP8266 Lolin32 - NodeMCU ESP-32S - WeMos Lolin32 - WeMos Lolin32 mini - ESP32-CAM programmer - ESP32-CAM bundle - ESP32-WROOM-32 - ESP32-S
Aggiornare il firmware con la classe Update
Un altro sistema interessante per aggiornare il firmware è utilizzare una scheda SD o un filesystem locale, per farlo possiamo usare la classe Update
.
Un metodo, in particolare, può gestire gli aggiornamenti tramite stream
Update.begin(firmwareSizeInBytes);
Update.writeStream(streamVar);
Update.end();
Usare la scheda SD per l’aggiornamento
sistema ampiamente utilizzato per aggiornare il firmware consiste nell’aggiungere un file all’interno di una memoria esterna come una SD rimovibile e all’avvio del dispositivo, aggiornare con esso.
In questo caso, seguiremo questi passaggi:
- Inserire un firmware denominato
firmware.bin
nella SD; - All’avvio controlla se
firmware.bin
esiste; - Se esiste, avvia lo stream/aggiornamento del file;
- Alla fine rinominiamo firmware.bin in
firmware.bak
, così interrompiamo il ciclo di aggiornamenti; - Ripristina e riavvia il microcontrollore.
Cablaggio adattatore SD
Innanzitutto, dobbiamo collegare la SD e puoi seguire questo tutorial, “Come usare la scheda SD con l’esp32“.
Sketch di aggiornamento del firmware tramite scheda SD
Lo Sketch è abbastanza semplice e lo spiegherò in dettaglio.
/*
* Update ESP32 firmware with external SD
* Check firmware.bin, if present start update then rename in firmware.bak
*
* Renzo Mischianti <www.mischianti.org>
*
* https://mischianti.org/
*/
// include the SD library:
#include <SPI.h>
#include <Update.h>
#include <SD.h>
const int chipSelect = SS;
void progressCallBack(size_t currSize, size_t totalSize) {
Serial.printf("CALLBACK: Update process at %d of %d bytes...\n", currSize, totalSize);
}
#define FIRMWARE_VERSION 0.2
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("\nInitializing SD card...");
// we'll use the initialization code from the utility libraries
// since we're just testing if the card is working!
if (!SD.begin(SS)) {
Serial.println("initialization failed. Things to check:");
Serial.println("* is a card inserted?");
Serial.println("* is your wiring correct?");
Serial.println("* did you change the chipSelect pin to match your shield or module?");
while (1);
} else {
Serial.println("Wiring is correct and a card is present.");
}
Serial.print("Card size: ");
Serial.println((float)SD.cardSize()/1000);
Serial.print("Total bytes: ");
Serial.println(SD.totalBytes());
Serial.print("Used bytes: ");
Serial.println(SD.usedBytes());
Serial.print(F("\nCurrent firmware version: "));
Serial.println(FIRMWARE_VERSION);
Serial.print(F("\nSearch for firmware.."));
File firmware = SD.open("/firmware.bin");
if (firmware) {
Serial.println(F("found!"));
Serial.println(F("Try to update!"));
Update.onProgress(progressCallBack);
Update.begin(firmware.size(), U_FLASH);
Update.writeStream(firmware);
if (Update.end()){
Serial.println(F("Update finished!"));
}else{
Serial.println(F("Update error!"));
Serial.println(Update.getError());
}
firmware.close();
if (SD.rename("/firmware.bin", "/firmware.bak")){
Serial.println(F("Firmware rename succesfully!"));
}else{
Serial.println(F("Firmware rename error!"));
}
delay(2000);
ESP.restart();
}else{
Serial.println(F("not found!"));
}
Serial.print(F("Firmware version "));
Serial.println(FIRMWARE_VERSION);
}
void loop(void) {
}
Per prima cosa, proviamo ad aprire firmware.bin
File firmware = SD.open("/firmware.bin");
if (firmware) {
Se il file esiste, avvia lo stream del file nella partizione OTA
Update.begin(firmware.size(), U_FLASH);
Update.writeStream(firmware);
if (Update.end()){
E seguire l’avanzamento con la relativa richiamata
Update.onProgress(progressCallBack);
Alla fine, rinomino firmware.bin per impedire un altro aggiornamento al riavvio.
if (SD.rename("/firmware.bin", "/firmware.bak")){
Serial.println(F("Firmware rename succesfully!"));
}else{
Serial.println(F("Firmware rename error!"));
}
Infine ho riavviato l’esp per consentire la copia del firmware dalla partizione OTA nella flash.
Eseguire il test
Per il test, rimuoveremo la SD e caricheremo lo sketch con questa versione del firmware.
#define FIRMWARE_VERSION 0.1
Quindi modificare la versione in 0.2
#define FIRMWARE_VERSION 0.2
E generare binario compilato fa riferimento all’articolo “ESP32: flash del firmware binario compilato (.bin)“
Ora puoi ottenere il file bin dalla cartella dello schizzo (Sketch -> Show Sketch Folder
), copiarlo sulla SD e rinominarlo come firmware.bin
.
Ora, quando reinserisci la SD e fai clic sul ripristino, puoi ottenere questo output seriale.
Initializing SD card...Wiring is correct and a card is present.
Card size: 3972006.00
Total bytes: 3967680512
Used bytes: 458752
Current firmware version: 0.10
Search for firmware..found!
Try to update!
CALLBACK: Update process at 0 of 308272 bytes...
CALLBACK: Update process at 4096 of 308272 bytes...
CALLBACK: Update process at 8192 of 308272 bytes...
CALLBACK: Update process at 12288 of 308272 bytes...
CALLBACK: Update process at 16384 of 308272 bytes...
CALLBACK: Update process at 20480 of 308272 bytes...
[...]
CALLBACK: Update process at 294912 of 308272 bytes...
CALLBACK: Update process at 299008 of 308272 bytes...
CALLBACK: Update process at 303104 of 308272 bytes...
CALLBACK: Update process at 307200 of 308272 bytes...
CALLBACK: Update process at 308272 of 308272 bytes...
Update finished!
Firmware rename succesfully!
ets Jun 8 2016 00:22:57
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6388
entry 0x400806b4
Initializing SD card...Wiring is correct and a card is present.
Card size: 3972006.00
Total bytes: 3967680512
Used bytes: 458752
Current firmware version: 0.20
Search for firmware..not found!
Firmware version 0.20
Generare il file system (SPIFFS, LittleFS e FFat)
Una caratteristica interessante è la gestione dei File System come il firmware compilato.
Aggiungere un output dettagliato all’IDE di Arduino
Per comprendere meglio tutti i processi, abiliteremo l’output dettagliato sul nostro IDE di Arduino. Puoi trovare queste opzioni su File -> Preferences
e controllare i controlli Show verbose output
.
Ora possiamo prendere e riutilizzare il comando della console.
Generare il file system binario
Per gestire il filesystem, possiamo utilizzare la stessa modalità, ma prima devi leggere una delle seguenti guide:
- ESP32: fileSystem integrato SPIFFS
- ESP32: filesystem integrato LittleFS
- ESP32: filesystem integrato FFat (FAT/exFAT)
Dopo tale operazione, puoi utilizzare il plug-in come al solito.
Puoi controllare l’output della console IDE per verificare cosa è successo.
Chip : esp32
Using partition scheme from Arduino IDE.
Start: 0x290000
Size : 0x170000
mkspiffs : C:\Users\renzo\AppData\Local\Arduino15\packages\esp32\tools\mkspiffs\0.2.3\mkspiffs.exe
espota : C:\Users\renzo\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.0\tools\espota.exe
[SPIFFS] data : D:\Projects\Arduino\sloeber-workspace-OTA\ArduinoOTAesp32_basic_arduino\data
[SPIFFS] offset : 0
[SPIFFS] start : 2686976
[SPIFFS] size : 1472
[SPIFFS] page : 256
[SPIFFS] block : 4096
->/version.txt
[SPIFFS] upload : C:\Users\renzo\AppData\Local\Temp\arduino_build_258074/ArduinoOTAesp32_basic_arduino.spiffs.bin
[SPIFFS] IP : 192.168.1.186
Running: C:\Users\renzo\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.0\tools\espota.exe -i 192.168.1.186 -p 3232 -s -f C:\Users\renzo\AppData\Local\Temp\arduino_build_258074/ArduinoOTAesp32_basic_arduino.spiffs.bin
_>Sending invitation to 192.168.1.186
_>Uploading................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
_>09:21:38 [ERROR]: Error response from device
SPIFFS Upload failed!
La console dell’IDE restituisce un errore, ma il caricamento funziona. Penso che ora ci sia un piccolo bug quando scrivo questo articolo.
L’IDE dà un errore ma è un bug, il caricamento funziona correttamente
È possibile recuperare il file bin del file system da questa riga
[SPIFFS] upload : C:\Users\renzo\AppData\Local\Temp\arduino_build_258074/ArduinoOTAesp32_basic_arduino.spiffs.bin
Sketch per aggiornare il filesystem con un file nella scheda SD
Riutilizzo lo sketch precedente, e aggiungo una sezione per gestire l’aggiornamento del firmware.
/*
* Update ESP32 firmware with external SD
* Check firmware.bin, if present start update then rename in firmware.bak
*
* Update filesystem with external SD
* Check filesystem.bin, if present start update then rename in filesystem.bak
*
* Renzo Mischianti <www.mischianti.org>
*
* https://mischianti.org/
*/
// include the SD library:
#include <SPI.h>
#include <Update.h>
#include <SD.h>
#include <SPIFFS.h>
const int chipSelect = SS;
void progressCallBack(size_t currSize, size_t totalSize) {
Serial.printf("CALLBACK: Update process at %d of %d bytes...\n", currSize, totalSize);
}
#define FIRMWARE_VERSION 0.1
String FILESYSTEM_VERSION = "0.0";
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("\nInitializing SD card...");
// we'll use the initialization code from the utility libraries
// since we're just testing if the card is working!
if (!SD.begin(SS)) {
Serial.println("initialization failed. Things to check:");
Serial.println("* is a card inserted?");
Serial.println("* is your wiring correct?");
Serial.println("* did you change the chipSelect pin to match your shield or module?");
while (1);
} else {
Serial.println("Wiring is correct and a card is present.");
}
Serial.print("Card size: ");
Serial.println((float)SD.cardSize()/1000);
Serial.print("Total bytes: ");
Serial.println(SD.totalBytes());
Serial.print("Used bytes: ");
Serial.println(SD.usedBytes());
Serial.print(F("\nCurrent firmware version: "));
Serial.println(FIRMWARE_VERSION);
Serial.print(F("\nSearch for firmware.."));
File firmware = SD.open("/firmware.bin");
if (firmware) {
Serial.println(F("found!"));
Serial.println(F("Try to update!"));
Update.onProgress(progressCallBack);
Update.begin(firmware.size(), U_FLASH);
Update.writeStream(firmware);
if (Update.end()){
Serial.println(F("Update finished!"));
}else{
Serial.println(F("Update error!"));
Serial.println(Update.getError());
}
firmware.close();
if (SD.rename("/firmware.bin", "/firmware.bak")){
Serial.println(F("Firmware rename succesfully!"));
}else{
Serial.println(F("Firmware rename error!"));
}
delay(2000);
ESP.restart();
}else{
Serial.println(F("not found!"));
}
Serial.print(F("Firmware version "));
Serial.println(FIRMWARE_VERSION);
Serial.print(F("Inizializing FS..."));
if (SPIFFS.begin()){
Serial.println(F("done."));
}else{
Serial.println(F("fail."));
}
Serial.print(F("FileSystem version "));
File versionFile = SPIFFS.open(F("/version.txt"), "r");
if (versionFile) {
FILESYSTEM_VERSION = versionFile.readString();
versionFile.close();
}
Serial.println(FILESYSTEM_VERSION);
Serial.print(F("\nSearch for filesystem update.."));
File filesystem = SD.open("/filesystem.bin");
if (filesystem) {
Serial.println(F("found!"));
Serial.println(F("Try to update!"));
Update.onProgress(progressCallBack);
Update.begin(filesystem.size(), U_SPIFFS);
Update.writeStream(filesystem);
if (Update.end()){
Serial.println(F("Update finished!"));
}else{
Serial.println(F("Update error!"));
Serial.println(Update.getError());
}
filesystem.close();
if (SD.rename("/filesystem.bin", "/filesystem.bak")){
Serial.println(F("Filesystem rename succesfully!"));
}else{
Serial.println(F("Filesystem rename error!"));
}
delay(2000);
ESP.restart();
}else{
Serial.println(F("not found!"));
}
}
void loop(void) {
}
Ci sono delle informazioni relevanti:
Update.begin(filesystem.size(), U_SPIFFS);
Cambio U_FLASH in U_SPIFFS, questo imposta internamente l’indirizzo corretto della sezione flash e inizia l’aggiornamento da lì.
Provare lo sketch
Creiamo un file version.txt
nella cartella dei dati dello sketch, e scrivo 0.1
all’interno, e lo uso come versione del FileSystem, quindi carico la cartella dei dati nel filesystem.
Initializing SD card...Wiring is correct and a card is present.
Card size: 3972006.00
Total bytes: 3967680512
Used bytes: 458752
Current firmware version: 0.10
Search for firmware..not found!
Firmware version 0.10
Inizializing FS...done.
FileSystem version 0.1
Search for filesystem update..not found!
Ora modificheremo il file version.txt
con la versione 0.2, quindi lo caricheremo sul dispositivo, quindi
Cambia versione in 0.2
in
, rigenera senza caricare e copia il file version.txt
ArduinoOTAesp8266_sd_fs_update.mklittlefs.bin
sulla SD e rinominalo in filesystem.bin
.
Ora inserisci la SD e controlla l’uscita seriale.
Initializing SD card...Wiring is correct and a card is present.
Card size: 3972006.00
Total bytes: 3967680512
Used bytes: 1966080
Current firmware version: 0.10
Search for firmware..not found!
Firmware version 0.10
Inizializing FS...done.
FileSystem version 0.2
Search for filesystem update..found!
Try to update!
CALLBACK: Update process at 0 of 1507328 bytes...
CALLBACK: Update process at 4096 of 1507328 bytes...
CALLBACK: Update process at 8192 of 1507328 bytes...
CALLBACK: Update process at 12288 of 1507328 bytes...
CALLBACK: Update process at 16384 of 1507328 bytes...
[...]
CALLBACK: Update process at 1486848 of 1507328 bytes...
CALLBACK: Update process at 1490944 of 1507328 bytes...
CALLBACK: Update process at 1495040 of 1507328 bytes...
CALLBACK: Update process at 1499136 of 1507328 bytes...
CALLBACK: Update process at 1503232 of 1507328 bytes...
CALLBACK: Update process at 1507328 of 1507328 bytes...
Update finished!
Filesystem rename succesfully!
ets Jun 8 2016 00:22:57
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6388
entry 0x400806b4
Initializing SD card...Wiring is correct and a card is present.
Card size: 3972006.00
Total bytes: 3967680512
Used bytes: 1966080
Current firmware version: 0.10
Search for firmware..not found!
Firmware version 0.10
Inizializing FS...done.
FileSystem version 0.3
Search for filesystem update..not found!
La prima volta trova il filesystem.bin
poi cambia il nome e la volta successiva non fa nulla.
Grazie
- ESP32: piedinatura, specifiche e configurazione dell’Arduino IDE
- ESP32: fileSystem integrato SPIFFS
- ESP32: gestire più seriali e logging per il debug
- ESP32 risparmio energetico pratico
- ESP32 risparmio energetico pratico: gestire WiFi e CPU
- ESP32 risparmio energetico pratico: modem e light sleep
- ESP32 risparmio energetico pratico: deep sleep e ibernazione
- ESP32 risparmio energetico pratico: preservare dati al riavvio, sveglia a tempo e tramite tocco
- ESP32 risparmio energetico pratico: sveglia esterna e da ULP
- ESP32 risparmio energetico pratico: sveglia da UART e GPIO
- ESP32: filesystem integrato LittleFS
- ESP32: filesystem integrato FFat (Fat/exFAT)
- ESP32-wroom-32
- ESP32-CAM
- ESP32: ethernet w5500 con chiamate standard (HTTP) e SSL (HTTPS)
- ESP32: ethernet enc28j60 con chiamate standard (HTTP) e SSL (HTTPS)
- Come usare la scheda SD con l’esp32
- esp32 e esp8266: file system FAT su memoria SPI flash esterna
- Gestione aggiornamenti firmware e OTA
- Gestione del firmware
- Aggiornamento OTA con Arduino IDE
- Aggiornamento OTA con browser web
- Aggiornamenti automatici OTA da un server HTTP
- Aggiornamento del firmware non standard
- Integrare LAN8720 con ESP32 per la connettività Ethernet con plain (HTTP) e SSL (HTTPS)
- Collegare l’EByte E70 (CC1310) ai dispositivi ESP32 c3/s3 ed un semplice sketch di esempio
- ESP32-C3: piedinatura, specifiche e configurazione dell’IDE Arduino
- Integrazione del modulo W5500 su ESP32 con Core 3: supporto nativo ai protocolli Ethernet con SSL e altre funzionalità
- Integrazione del modulo LAN8720 su ESP32 con Core 3: supporto nativo del protocollo Ethernet con SSL e altre funzionalità.