ESP32 OTA: caricare il codice via Wi-Fi senza cavo (ArduinoOTA)
ESP32 OTA: carica il codice via Wi-Fi senza cavo USB. Porta di rete ArduinoOTA, pagina web ElegantOTA, password, schema delle partizioni e upload interrotti.
L'OTA dell'ESP32 (Over-The-Air, aggiornamento "via etere") significa caricare nuovo codice sulla scheda tramite Wi-Fi, senza collegare un cavo USB. Pensa a un sensore montato sul soffitto, a una centralina di irrigazione in giardino o a una scheda relè dentro un quadro elettrico: invece di prendere la scala, smontare la scheda e collegarla al computer per ogni piccola correzione, invii la nuova versione dall'Arduino IDE o dal browser in pochi secondi. La scheda scrive il nuovo programma in memoria in background, lo verifica e si riavvia da sola.
In questa guida imparerai passo dopo passo come funziona l'OTA dentro l'ESP32, tre metodi diversi (ArduinoOTA per l'Arduino IDE, ElegantOTA per il browser e HTTPUpdate per scaricare da un server), come scegliere lo schema di partizioni giusto, come proteggere il caricamento con una password, cosa succede se l'upload si interrompe e come non perdere l'OTA nel prossimo sketch. Tutto il codice è stato compilato e provato con il core Arduino per ESP32.

Cos'è l'OTA dell'ESP32 e come funziona?
La memoria flash dell'ESP32 non è un blocco unico; è divisa in parti da una mappa chiamata tabella delle partizioni. Una tabella compatibile con l'OTA ha due aree uguali per il programma: app0 (ota_0) e app1 (ota_1). Mentre la scheda gira da una delle due, il nuovo programma viene scritto nell'altra. Una piccola partizione otadata ricorda quale area verrà eseguita al prossimo avvio. Così il programma in esecuzione non viene mai toccato durante il caricamento, e la scheda non abbandona il vecchio programma finché il nuovo codice non è stato scritto e verificato per intero.
- Il nuovo programma (il file .bin compilato) arriva alla scheda via Wi-Fi, un pezzo alla volta.
- L'ESP32 scrive ogni pezzo nella partizione di programma non in uso; nel frattempo il codice attuale continua a lavorare.
- Quando il file è arrivato tutto, vengono controllati l'intestazione dell'immagine e il checksum; un file corrotto o incompleto viene rifiutato.
- Se la verifica va a buon fine, otadata viene aggiornata: al prossimo avvio partirà la nuova partizione.
- La scheda si riavvia e parte con il nuovo programma. L'aggiornamento successivo andrà nell'altra partizione; le due aree si usano a turno.
| Metodo | Da dove invii il codice? | Ideale per | Libreria extra |
|---|---|---|---|
| ArduinoOTA | Dalla porta di rete dell'Arduino IDE | Sviluppare alla scrivania, sulla stessa rete | Nessuna (inclusa nel core) |
| ElegantOTA | Scegliendo un .bin nella pagina /update del browser | Far aggiornare chi non ha l'IDE, caricare dal telefono | ElegantOTA |
| HTTPUpdate | La scheda scarica da sola un .bin da un server | Molti dispositivi, dispositivi remoti, aggiornamenti automatici | Nessuna (inclusa nel core) |
Schema delle partizioni (partition scheme) e dimensione della flash
È il requisito dell'OTA che si dimentica più spesso: serve una seconda area libera in cui scrivere il nuovo programma. Per questo il programma più grande che puoi caricare via OTA è più piccolo persino della metà della flash. La tabella delle partizioni si sceglie nell'Arduino IDE da Strumenti > Partition Scheme. Sulle comuni schede ESP32 DevKit con 4 MB di flash (ESP32 Dev Module) le opzioni sono:
| Partition Scheme | Area programma | OTA | File system (SPIFFS/LittleFS) |
|---|---|---|---|
| Default 4MB with spiffs | 2 × 1,25 MB (1.310.720 byte) | Sì | 1,375 MB |
| Minimal SPIFFS (1.9MB APP with OTA) | 2 × 1,875 MB (1.966.080 byte) | Sì | 128 KB |
| No OTA (2MB APP/2MB SPIFFS) | 1 × 2 MB | No | 1,875 MB |
| Huge APP (3MB No OTA/1MB SPIFFS) | 1 × 3 MB | No | 896 KB |
| Minimal (1.3MB APP/700KB SPIFFS) | 1 × 1,25 MB (per schede con 2 MB di flash) | No | 640 KB |
Quanto spazio occupa il tuo programma lo vedi nell'output di compilazione: il nostro primo esempio con Wi-Fi e ArduinoOTA stampa "Sketch uses 758685 bytes (57%) ... Maximum is 1310720 bytes". Quel massimo è la dimensione di una sola area programma dello schema scelto. Se l'occupazione supera il 90 %, presto dovrai passare a Minimal SPIFFS. Un'altra regola importante: la tabella delle partizioni non si può cambiare via OTA. Se hai cambiato schema, quel caricamento va fatto via USB; gli aggiornamenti OTA successivi useranno la nuova tabella. Sulle schede con 8 MB o 16 MB di flash (come molti modelli ESP32-S3), scegliere la dimensione giusta nel menu Flash Size ti dà aree OTA molto più grandi.
Se vuoi vedere da quale partizione sta girando davvero la tua scheda e quanto spazio resta per l'OTA, carica il piccolo sketch qui sotto. Non richiede librerie e usa direttamente le funzioni OTA di ESP-IDF:
1#include <esp_ota_ops.h>
2
3void setup() {
4 Serial.begin(115200);
5 delay(1000);
6 const esp_partition_t* running = esp_ota_get_running_partition();
7 const esp_partition_t* next = esp_ota_get_next_update_partition(NULL);
8
9 Serial.printf("Flash boyutu / Flash size: %u KB\n", ESP.getFlashChipSize() / 1024);
10 Serial.printf("Program boyutu / Sketch size: %u KB\n", ESP.getSketchSize() / 1024);
11 Serial.printf("OTA icin bos alan / Free space for OTA: %u KB\n", ESP.getFreeSketchSpace() / 1024);
12 Serial.printf("Calisan bolum / Running partition: %s (0x%06x)\n", running->label, running->address);
13 if (next != NULL) {
14 Serial.printf("Siradaki OTA bolumu / Next OTA partition: %s (0x%06x)\n", next->label, next->address);
15 } else {
16 Serial.println("OTA bolumu yok: bolum tablosunu degistir / No OTA partition: change the partition scheme");
17 }
18}
19
20void loop() {
21}Con lo schema predefinito, dopo il primo caricamento via USB l'output mostra "Running partition: app0 (0x010000)" e "Next OTA partition: app1 (0x150000)". Se esegui di nuovo il codice dopo un aggiornamento OTA, vedrai che ora gira da app1. Il valore di ESP.getFreeSketchSpace() è la dimensione del programma più grande che puoi caricare via OTA; se il nuovo .bin è più grande, l'aggiornamento non parte.
Metodo 1: caricamento wireless dall'Arduino IDE con ArduinoOTA
La libreria ArduinoOTA è inclusa nel core ESP32, quindi non devi installare nulla. Quando la scheda entra in rete si annuncia tramite mDNS; l'Arduino IDE la rileva e aggiunge una porta di rete al menu Porta. Quando premi Carica, l'IDE invia il programma attraverso questa porta di rete invece che via USB. Sull'ESP32 il servizio OTA ascolta per impostazione predefinita sulla porta 3232. Lo sketch seguente si collega al Wi-Fi, avvia l'OTA con una password e fa lampeggiare il LED integrato come prova:
1#include <WiFi.h>
2#include <ArduinoOTA.h>
3
4const char* WIFI_SSID = "AgAdi"; // Wi-Fi adın / your Wi-Fi name
5const char* WIFI_PASS = "AgSifresi"; // Wi-Fi şifren / your Wi-Fi password
6const int LED_PIN = 2; // çoğu DevKit'te dahili LED / onboard LED on most DevKits
7
8unsigned long lastBlink = 0;
9
10void setup() {
11 Serial.begin(115200);
12 pinMode(LED_PIN, OUTPUT);
13
14 WiFi.mode(WIFI_STA);
15 WiFi.begin(WIFI_SSID, WIFI_PASS);
16 while (WiFi.status() != WL_CONNECTED) { // bağlanana kadar bekle / wait until connected
17 delay(500);
18 Serial.print(".");
19 }
20 Serial.println();
21 Serial.print("IP: ");
22 Serial.println(WiFi.localIP());
23
24 ArduinoOTA.setHostname("bluegrays-esp32"); // IDE'de görünen ad / name shown in the IDE
25 ArduinoOTA.setPassword("ota1234"); // yükleme parolası / upload password
26
27 ArduinoOTA.onStart([]() {
28 // Güncelleme başlıyor: motorları, röleleri güvenli konuma al / update starting: put motors and relays in a safe state
29 String type = (ArduinoOTA.getCommand() == U_FLASH) ? "program" : "dosya sistemi / filesystem";
30 Serial.println("OTA basladi / started: " + type);
31 });
32 ArduinoOTA.onEnd([]() {
33 Serial.println("\nOTA bitti, yeniden baslatiliyor / done, rebooting");
34 });
35 ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
36 Serial.printf("Ilerleme / Progress: %u%%\r", progress * 100 / total);
37 });
38 ArduinoOTA.onError([](ota_error_t error) {
39 Serial.printf("Hata / Error[%u]: ", error);
40 if (error == OTA_AUTH_ERROR) Serial.println("parola / auth failed");
41 else if (error == OTA_BEGIN_ERROR) Serial.println("baslatilamadi, yer yok / begin failed, no space");
42 else if (error == OTA_CONNECT_ERROR) Serial.println("baglanti / connect failed");
43 else if (error == OTA_RECEIVE_ERROR) Serial.println("veri alinamadi / receive failed");
44 else if (error == OTA_END_ERROR) Serial.println("bitirilemedi / end failed");
45 });
46
47 ArduinoOTA.begin(); // OTA hizmetini başlat / start the OTA service
48}
49
50void loop() {
51 ArduinoOTA.handle(); // her turda çağır, unutma / call on every pass, never forget
52
53 // delay() yerine millis(): OTA isteklerini kaçırmamak için / millis() instead of delay() so OTA requests aren't missed
54 if (millis() - lastBlink >= 500) {
55 lastBlink = millis();
56 digitalWrite(LED_PIN, !digitalRead(LED_PIN));
57 }
58}| Riga | A cosa serve? |
|---|---|
| ArduinoOTA.setHostname("bluegrays-esp32") | Il nome mostrato nell'elenco delle porte dell'IDE e in rete. Se hai più schede, dai a ognuna un nome diverso. |
| ArduinoOTA.setPassword("ota1234") | Senza password chiunque nella tua rete può caricare codice sulla scheda. L'IDE chiede questa password prima del caricamento. |
| onStart / onEnd | Si eseguono all'inizio e alla fine dell'aggiornamento. Il posto ideale per fermare i motori, spegnere i relè o mostrare "Aggiornamento" su un display. |
| onProgress | Fornisce la percentuale; puoi disegnare una barra di avanzamento su un LCD o un OLED. |
| onError | Indica il tipo di errore: password, spazio insufficiente, connessione, ricezione o chiusura. |
| ArduinoOTA.handle() | Controlla le richieste OTA in arrivo. Se non viene chiamata spesso dentro loop(), la scheda non può rispondere all'IDE. |
Passo dopo passo: il tuo primo caricamento OTA
- Modifica i valori WIFI_SSID e WIFI_PASS nel codice per la tua rete. L'ESP32 si collega solo a reti a 2,4 GHz.
- Nel menu Strumenti scegli la tua scheda (es. ESP32 Dev Module) e un Partition Scheme con OTA (Default o Minimal SPIFFS).
- Fai il primo caricamento con il cavo USB. È obbligatorio, perché la scheda non ha ancora il codice OTA.
- Apri il Monitor seriale a 115200 baud e annota l'indirizzo IP stampato dalla scheda.
- Scollega il cavo USB e, se vuoi, alimenta la scheda con un'altra sorgente. Entro 10–20 secondi in Strumenti > Porta, sotto porte di rete, compare una riga come "bluegrays-esp32 at 192.168.1.x"; selezionala.
- Cambia nel codice la velocità del LED da 500 a 100 e premi Carica. Quando l'IDE chiede la password, scrivi "ota1234".
- Nella finestra di output vedrai la percentuale di avanzamento e alla fine una riga come "Done" o "Result: OK". La scheda si riavvia e ora il LED lampeggia veloce.
C'è un limite da conoscere: la porta di rete serve solo per caricare e il Monitor seriale non funziona senza fili. Per vedere i messaggi della scheda ricollega l'USB oppure mostra lo stato su una pagina web, su un display o con messaggi MQTT. Mentre sviluppi alla scrivania puoi anche lasciare la scheda collegata via USB e caricare comunque dalla rete; così hai caricamenti veloci e il Monitor seriale insieme.
Protezione con password e sicurezza
Una scheda con il servizio OTA aperto è una porta da cui chiunque nella tua rete può caricare codice. In ArduinoOTA, setPassword() tiene la password in chiaro nel codice; se condividi il codice, puoi passare l'hash MD5 della password con setPasswordHash(), così la password non compare nel sorgente. ElegantOTA protegge la pagina /update con nome utente e password (HTTP Basic Auth).
- Dai a ogni dispositivo una password diversa e difficile da indovinare: valori come "1234" o "admin" sono i primi che vengono provati.
- Non esporre la scheda su internet: aprire l'OTA o la pagina /update verso l'esterno con il port forwarding del router è un rischio serio; questi metodi viaggiano su HTTP non cifrato.
- Usa HTTPUpdate per i dispositivi remoti: poiché è la scheda a chiedere l'aggiornamento, basta una connessione in uscita; se scarichi da internet, preferisci HTTPS con WiFiClientSecure.
- Passa a uno stato sicuro durante l'aggiornamento: in onStart ferma i motori e spegni i relè di riscaldatori e pompe. Il riavvio dura qualche secondo e in quel tempo i pin possono restare indefiniti.
Metodo 2: caricare un .bin dal browser con ElegantOTA
ElegantOTA aggiunge una curata pagina /update al server web che gira sull'ESP32. Apri questa pagina dal telefono o da qualsiasi computer senza Arduino IDE, scegli il file .bin compilato e lo carichi; la barra di avanzamento compare nel browser. È il metodo più pratico quando consegni il dispositivo a qualcun altro o lo aggiorni sul posto.
- Nell'Arduino IDE apri il Gestore librerie, cerca ElegantOTA (Ayush Sharma) e installala.
- Modifica il codice qui sotto e caricalo la prima volta via USB.
- Apri nel browser l'indirizzo stampato nel Monitor seriale (es. http://192.168.1.42/update) e accedi con nome utente "admin" e password "ota1234".
- Lascia selezionata la modalità Firmware e trascina il file .bin; finito il caricamento, la scheda si riavvia da sola.
1#include <WiFi.h>
2#include <WebServer.h>
3#include <ElegantOTA.h>
4
5const char* WIFI_SSID = "AgAdi"; // Wi-Fi adın / your Wi-Fi name
6const char* WIFI_PASS = "AgSifresi"; // Wi-Fi şifren / your Wi-Fi password
7
8WebServer server(80);
9unsigned long otaProgressMillis = 0;
10
11void onOTAStart() {
12 Serial.println("OTA basladi / OTA started"); // röleleri kapat / switch relays off
13}
14
15void onOTAProgress(size_t current, size_t final) {
16 if (millis() - otaProgressMillis > 1000) { // saniyede bir yaz / print once per second
17 otaProgressMillis = millis();
18 Serial.printf("%u / %u bayt / bytes\n", current, final);
19 }
20}
21
22void onOTAEnd(bool success) {
23 Serial.println(success ? "OTA basarili / OTA successful" : "OTA hatasi / OTA failed");
24}
25
26void setup() {
27 Serial.begin(115200);
28 WiFi.mode(WIFI_STA);
29 WiFi.begin(WIFI_SSID, WIFI_PASS);
30 while (WiFi.status() != WL_CONNECTED) {
31 delay(500);
32 Serial.print(".");
33 }
34 Serial.println();
35 Serial.print("Adres / Address: http://");
36 Serial.print(WiFi.localIP());
37 Serial.println("/update");
38
39 server.on("/", []() {
40 server.send(200, "text/plain", "BlueGrays ESP32 - surum / version 1.0");
41 });
42
43 ElegantOTA.begin(&server, "admin", "ota1234"); // /update sayfası + kullanıcı/parola / /update page + user/password
44 ElegantOTA.onStart(onOTAStart);
45 ElegantOTA.onProgress(onOTAProgress);
46 ElegantOTA.onEnd(onOTAEnd);
47
48 server.begin();
49}
50
51void loop() {
52 server.handleClient(); // web isteklerini işle / handle web requests
53 ElegantOTA.loop(); // başarılı yüklemeden sonra yeniden başlatır / reboots after a successful upload
54}Per impostazione predefinita ElegantOTA lavora con la classe sincrona WebServer inclusa nel core, quindi le chiamate server.handleClient() ed ElegantOTA.loop() dentro loop() sono obbligatorie. Se il tuo progetto usa già ESPAsyncWebServer, puoi impostare a 1 l'opzione ELEGANTOTA_USE_ASYNC_WEBSERVER della libreria e usarla con il server asincrono; spieghiamo come configurare il server asincrono nell'articolo Web server asincrono e WebSocket con ESP32. La modalità Filesystem della pagina aggiorna l'immagine LittleFS o SPIFFS (file della pagina web, file di impostazioni) invece del programma.
Ottenere il file .bin: esportare il binario compilato
Per ElegantOTA e HTTPUpdate ti serve il file del programma compilato. Nell'Arduino IDE esegui Sketch > Esporta binario compilato (Export Compiled Binary). L'IDE compila il programma e lascia diversi file in una cartella build dentro la cartella dello sketch. Solo uno di questi va bene per l'OTA:
| File | Contenuto | Si usa per l'OTA? |
|---|---|---|
| mioprogetto.ino.bin | Solo l'applicazione (il tuo programma) | Sì, è il file da caricare |
| mioprogetto.ino.bootloader.bin | Bootloader | No |
| mioprogetto.ino.partitions.bin | Tabella delle partizioni | No |
| mioprogetto.ino.merged.bin (core 3.x) | Bootloader, tabella e programma uniti | No, si scrive solo via USB all'indirizzo 0x0 |
Metodo 3: aggiornamenti automatici da un server con HTTPUpdate
Immagina di avere cinque schede sensore sparse per casa. Invece di caricarle una per una dall'IDE, metti il nuovo .bin su un server e le schede lo scaricano da sole. La libreria HTTPUpdate inclusa nel core ESP32 lo fa con una sola riga. Nell'esempio qui sotto l'aggiornamento parte quando premi il pulsante BOOT (GPIO 0) sulla scheda:
1#include <WiFi.h>
2#include <HTTPUpdate.h>
3
4const char* WIFI_SSID = "AgAdi";
5const char* WIFI_PASS = "AgSifresi";
6// Bilgisayarındaki ya da sunucundaki .bin dosyası / the .bin file on your computer or server
7const char* FIRMWARE_URL = "http://192.168.1.50:8000/firmware.bin";
8const int BUTTON_PIN = 0; // karttaki BOOT butonu / the BOOT button on the board
9
10void setup() {
11 Serial.begin(115200);
12 pinMode(BUTTON_PIN, INPUT_PULLUP);
13 WiFi.begin(WIFI_SSID, WIFI_PASS);
14 while (WiFi.status() != WL_CONNECTED) delay(500);
15 Serial.println("Hazir: guncellemek icin BOOT'a bas / Ready: press BOOT to update");
16}
17
18void loop() {
19 if (digitalRead(BUTTON_PIN) == LOW) { // butona basıldı / button pressed
20 WiFiClient client;
21 httpUpdate.rebootOnUpdate(true); // başarılıysa yeniden başlat / reboot on success
22 t_httpUpdate_return ret = httpUpdate.update(client, FIRMWARE_URL);
23
24 switch (ret) {
25 case HTTP_UPDATE_FAILED:
26 Serial.printf("Hata / Error (%d): %s\n", httpUpdate.getLastError(),
27 httpUpdate.getLastErrorString().c_str());
28 break;
29 case HTTP_UPDATE_NO_UPDATES:
30 Serial.println("Guncelleme yok / No update");
31 break;
32 case HTTP_UPDATE_OK:
33 Serial.println("Tamam / OK"); // buraya genelde gelinmez, kart yeniden başlar / usually not reached, the board reboots
34 break;
35 }
36 delay(1000);
37 }
38}Per provarlo, metti il .bin in una cartella del computer con il nome firmware.bin ed esegui python3 -m http.server 8000 in quella cartella; sostituisci l'indirizzo IP nel codice con l'IP locale del tuo computer. Nell'uso reale sostituisci il pulsante con un timer: per esempio, una volta all'ora la scheda legge un piccolo file "version.txt" e, se il numero di versione sul server è maggiore del suo, avvia l'aggiornamento. Così non finisce nemmeno in un ciclo in cui scarica lo stesso file e si riavvia all'infinito.
Cosa succede se la connessione cade durante l'OTA?
Risposta breve: la scheda non si brickera. Poiché il nuovo programma viene scritto nella partizione non usata e la partizione di avvio cambia solo dopo la verifica del file completo, se il caricamento si interrompe la scheda continua a funzionare con il vecchio programma. Vedrai "Error Uploading" nell'IDE, OTA_RECEIVE_ERROR in ArduinoOTA o un esito negativo in ElegantOTA; risolvi il problema e ripeti il caricamento. Se manca la corrente a metà caricamento vale lo stesso: la scheda si avvia con il vecchio programma. L'unico vero rischio è che il nuovo programma sia difettoso: se carichi un programma che non si collega al Wi-Fi o che non contiene il codice OTA, per il prossimo aggiornamento ti servirà di nuovo il cavo.
- Segnale Wi-Fi debole: se il caricamento si blocca intorno al 30–60 %, avvicina la scheda al router o usa un modulo con antenna esterna. Se WiFi.RSSI() nel Monitor seriale è peggio di -75 dBm, aspettati interruzioni; trovi i dettagli in L'ESP32 non si connette al Wi-Fi.
- Alimentazione insufficiente: la scrittura in flash e la trasmissione Wi-Fi assorbono corrente nello stesso momento. Una porta USB debole o un cavo sottile possono resettare la scheda durante il caricamento; si presenta come un errore di brownout. Usa un alimentatore a 5 V robusto che fornisca almeno 500 mA.
- Attese lunghe in loop(): pause come delay(5000) ritardano la chiamata a handle() e l'IDE segnala "No response from the ESP". Gestisci i tempi con millis().
- Firewall: con ArduinoOTA, all'inizio del caricamento l'ESP32 si ricollega al tuo computer. Se il Firewall di Windows o un antivirus blocca questa connessione in entrata, il caricamento fallisce subito; nella finestra di autorizzazione che compare al primo tentativo consenti le reti private.
Mantenere l'OTA in ogni nuovo sketch
La delusione più comune con l'OTA è questa: carichi via OTA un progetto completamente diverso, quel progetto non contiene codice ArduinoOTA e la scheda non compare più come porta di rete. Il nuovo programma sostituisce del tutto il vecchio; l'OTA non è qualcosa che "resta sulla scheda", ogni programma deve portarlo con sé. Per non risalire sulla scala fino al dispositivo sul soffitto, fai di queste regole un'abitudine:
- Usa un modello: metti la connessione Wi-Fi e le impostazioni di ArduinoOTA in una funzione separata (es. setupOTA()) e inizia ogni nuovo progetto da quel file.
- Metti la chiamata a handle() all'inizio di loop() e non lasciare mai dentro loop() un ciclo che blocca a lungo.
- Riconnettiti se cade il Wi-Fi: usa WiFi.setAutoReconnect(true) o controlla la connessione regolarmente; una scheda senza connessione non può ricevere aggiornamenti.
- Aggiungi una finestra di manutenzione ai progetti con deep sleep: una scheda addormentata non sente la richiesta OTA. Scrivi una modalità che attende l'OTA per 60 secondi prima di dormire se all'avvio è premuto un pulsante o è arrivato un flag MQTT. Per le modalità di sospensione vedi l'articolo ESP32 Deep Sleep.
- Prova prima su una seconda scheda alla scrivania: prima di inviare al dispositivo installato, esegui lo stesso codice su una scheda accanto a te; se si collega al Wi-Fi e compare come porta di rete, è sicuro inviarlo.
- Mostra un numero di versione: tieni una costante FW_VERSION all'inizio del codice e mostrala sulla pagina web o sul display; saprai sempre quale versione gira su quale scheda.
OTA su ESP8266 e Raspberry Pi Pico W
Il codice ArduinoOTA ed ElegantOTA di questa guida funziona con piccole modifiche anche sulle schede ESP8266 (NodeMCU, Wemos D1 Mini): si usa ESP8266WiFi.h al posto di WiFi.h, ESP8266WebServer al posto di WebServer, e la porta OTA è la 8266. Sulle schede ESP8266 con 4 MB di flash devi scegliere nel menu Flash Size un'opzione che lasci abbastanza spazio programma per l'OTA. Sul Raspberry Pi Pico W il core arduino-pico offre il supporto ad ArduinoOTA; qui il nuovo programma viene prima scaricato nel file system LittleFS e copiato al suo posto all'avvio. Per questo sul Pico W devi riservare nel menu Flash Size un file system più grande del programma. MicroPython non ha uno strumento OTA pronto; si possono scrivere piccoli script che scaricano e sostituiscono file .py dalla rete, ma non è un aggiornamento verificato a due partizioni come sull'ESP32.
Idee di progetti con l'OTA
- Sensore a soffitto o a parete: cambia le soglie di una scheda che misura temperatura, umidità e movimento senza toccare un cavo.
- Relè domotico: aggiorna via OTA le regole orarie della scheda relè nel quadro elettrico; metti i relè in uno stato sicuro dentro onStart.
- Dispositivi per Home Assistant: aggiungi nuove funzioni dalla rete ai sensori collegati a Home Assistant via MQTT.
- Centralina di irrigazione del giardino: cambia gli orari di irrigazione e la soglia di umidità del terreno senza aprire la scatola stagna.
- Barra di avanzamento su LCD: mostra il valore di onProgress come percentuale e barra su un LCD 16x2; il progetto ESP32 OTA di BlueGrays fa esattamente questo.
- Aggiornamento di una flotta: fai controllare ogni notte a più schede, con HTTPUpdate, se sullo stesso server c'è una nuova versione.
Errori comuni e soluzioni
| Sintomo | Causa probabile | Soluzione |
|---|---|---|
| Nessuna porta di rete nel menu Porta | Scheda su un'altra rete, mDNS bloccato, il codice non chiama ArduinoOTA.begin() | Usa la stessa rete a 2,4 GHz, riavvia l'IDE, controlla che l'IP compaia nel Monitor seriale |
| "No response from the ESP" | delay() lungo in loop(), scheda occupata o firewall | Usa millis() invece di delay(), consenti l'IDE nel firewall |
| "Authentication Failed" | Password OTA sbagliata | Inserisci il valore di setPassword del codice; se l'hai dimenticata, carica una volta via USB |
| "Not Enough Space" / Begin Failed | Schema Huge APP o No OTA, il programma non entra nella seconda area | Scegli Minimal SPIFFS e carica una volta via USB; riduci il programma |
| Il caricamento si interrompe a metà | Segnale debole, calo di tensione, connessione persa | Avvicina la scheda al router, usa un alimentatore a 5 V robusto, riprova; il vecchio programma continua a funzionare |
| Dopo il caricamento la scheda non entra in rete | Il nuovo codice non ha Wi-Fi né OTA, SSID sbagliato | Correggi via USB; d'ora in poi inizia ogni progetto dal modello OTA |
| "Wrong Magic Byte" o errore di attivazione in ElegantOTA | È stato scelto merged.bin, bootloader.bin o un file compilato per un altro chip | Carica solo il file mioprogetto.ino.bin |
L'OTA è la chiave per portare i progetti con ESP32 dalla scrivania a un'installazione vera: una volta configurato bene, correzioni, nuove funzioni e cambi di soglia arrivano senza fili in pochi secondi. Nell'app BlueGrays trovi il progetto ESP32 OTA Update (con IP e avanzamento mostrati su un LCD) insieme ai progetti su connessione Wi-Fi, Async Web Server, mDNS e NTP, tutti con schema del circuito e codice passo dopo passo.
Domande frequenti
Cos'è l'OTA dell'ESP32?
L'OTA (Over-The-Air) consiste nel caricare un nuovo programma sull'ESP32 via Wi-Fi invece che con un cavo USB. La scheda scrive il nuovo codice in una partizione di programma libera, lo verifica e si riavvia con la nuova versione. Il primo sketch con OTA va caricato una volta via USB.
Perché la porta di rete dell'ESP32 non compare nell'Arduino IDE?
Le cause più comuni sono il computer e la scheda su reti diverse, una rete ospiti che isola i dispositivi e la chiamata ArduinoOTA.begin() nel codice che non viene mai eseguita. Controlla nel Monitor seriale che la scheda abbia ottenuto un IP, riavvia l'IDE e aspetta qualche secondo.
Quale partition scheme scegliere per l'OTA dell'ESP32?
Sulle schede con 4 MB di flash scegli Default (area programma di 2 × 1,25 MB) oppure, se il programma è grande, Minimal SPIFFS (2 × 1,875 MB). Huge APP e No OTA non hanno una seconda area programma, quindi con questi l'OTA non funziona. Il primo caricamento dopo il cambio di schema va fatto via USB.
Un aggiornamento OTA interrotto può brickare l'ESP32?
No. Il nuovo programma viene scritto in una partizione vuota e la partizione di avvio cambia solo dopo la verifica dell'intero file. Se cade la connessione o la corrente, la scheda si avvia con il vecchio programma e puoi semplicemente ripetere il caricamento.
Si può usare il Monitor seriale durante il caricamento OTA?
La porta di rete serve solo a caricare codice; il Monitor seriale non funziona senza fili. Per vedere i messaggi puoi lasciare la scheda collegata via USB o mostrare le informazioni su una pagina web, un display o via MQTT.
Come si imposta una password OTA sull'ESP32?
In ArduinoOTA chiami ArduinoOTA.setPassword("password") prima di begin(); l'IDE chiede questa password prima del caricamento. Se non vuoi che la password compaia nel codice, passa il suo hash MD5 con setPasswordHash(). In ElegantOTA proteggi la pagina con begin(&server, "utente", "password").
Progetti da realizzare dopo questo articolo
Vedi tutti i progetti
Aggiornamento OTA dell'ESP32 — Installazione wireless del firmware (con display LCD)
In questo progetto imparerai a installare il nuovo firmware sull'ESP32 tramite Wi-Fi, senza bisogno di un cavo USB. Grazie alla libreria ArduinoOTA, l'ESP32 diventa visibile sulla rete e viene automaticamente elencato come bluegrays-ota nella scheda "Network port" dell'IDE di Arduino. Il primo caricamento avviene tramite USB, mentre tutti gli aggiornamenti successivi saranno wireless — una caratteristica fondamentale per i dispositivi sul campo. Sul display LCD I2C vengono visualizzati, sia

Connessione Wi-Fi STA con ESP32 (con display LCD)
In questo progetto colleghiamo l'ESP32 alla rete Wi-Fi domestica in modalità Station (STA) in modo sicuro e tollerante agli errori. Separiamo SSID e password in un file secrets.h per impedire fughe su Git, impostiamo un meccanismo di riconnessione automatica e visualizziamo il livello del segnale RSSI e l'indirizzo IP su un display LCD I2C. Il LED interno funge da indicatore di stato.

Server web asincrono ESP32 (con indicazione dell'IP sul display LCD)
In questo progetto trasformiamo l'ESP32 in un server web asincrono che potrete controllare dal vostro telefono o computer collegato alla stessa rete Wi-Fi. Grazie alla libreria ESPAsyncWebServer, il server è in grado di elaborare più richieste contemporaneamente (a differenza del classico WebServer.h, che si blocca su una singola richiesta).

ESP32 mDNS: accesso al dispositivo tramite bluegrays-esp.local (con schermo LCD)
In questo progetto, aggiungendo il servizio mDNS (Multicast DNS) all'ESP32, consentiamo l'accesso tramite un nome host leggibile, come bluegrays-esp.local, anziché tramite l'indirizzo IP. Anche se l'IP assegnato dal DHCP dovesse cambiare, potrete sempre raggiungere il dispositivo con lo stesso nome. Eseguendo anche un piccolo server web, inviamo comandi di controllo dei LED dal browser all’indirizzo http://bluegrays-esp.local/. Sul display LCD I2C vengono visualizzati il nome host, l’IP e lo

Contatore WebSocket ESP32 (2 pulsanti + LCD + Web in tempo reale)
In questo progetto due pulsanti collegati all'ESP32 (GPIO 5 incrementa, GPIO 4 decrementa) modificano un contatore. Il valore si aggiorna all'istante su un display LCD I2C 16x2 e, grazie al supporto WebSocket di ESPAsyncWebServer, in tutti i browser collegati senza ricaricare la pagina. Al posto del polling HTTP si usa un'unica connessione persistente e l'ESP32 invia il nuovo valore a tutti con ws.textAll().

ESP32: ora reale da Internet tramite NTP
L'ESP32 si connette al Wi-Fi e recupera l'ora reale con precisione al millisecondo dai server NTP (Network Time Protocol). Grazie a configTzTime(), il fuso orario della Turchia (TRT, UTC+3) viene applicato automaticamente e il passaggio all'ora legale è gestito tramite la stringa POSIX TZ. L'ora viene mostrata sul Serial Monitor e su un display LCD I2C opzionale. configTzTime() avvia il servizio SNTP; vengono eseguite risincronizzazioni periodiche finché è disponibile l'accesso alla rete, e

ESP32 HTTPClient + API meteo (con schermo LCD)
In questo progetto, utilizzando l'ESP32, effettuiamo una chiamata REST all'API meteo (wttr.in) tramite Internet utilizzando HTTPClient.h. Analizziamo la risposta JSON restituita tramite ArduinoJson v7 e visualizziamo le informazioni relative a città, temperatura, umidità, condizioni meteorologiche e vento sul display LCD I2C sia in turco che in inglese. wttr.in è gratuito e non richiede una chiave API: basta digitare il nome di una città qualsiasi per ottenere le condizioni meteorologiche in t

ESP32 Deep Sleep — Risparmio della batteria (OLED + contatore in RTC RAM)
La modalità Deep Sleep dell'ESP32 riduce il consumo di corrente a circa 10 µA spegnendo la CPU e la maggior parte dei dispositivi periferici ed è di fondamentale importanza per i dispositivi IoT alimentati a batteria. In questo progetto utilizziamo tre diverse fonti di risveglio: il timer (15 secondi), un pin esterno (EXT0 — pulsante GPIO 33) e il sensore tattile (T0/GPIO 4). Le variabili contrassegnate con RTC_DATA_ATTR vengono preservate durante la modalità Deep Sleep: il contatore di avvio,
Altri articoli
App BlueGrays
Costruisci questo circuito passo passo sul telefono
Schema, codice ed elenco componenti in un’unica schermata. Oltre 200 progetti Arduino, ESP32 e Pico da realizzare.
Inquadra con il telefono
Punta la fotocamera sul codice: si apre lo store del tuo telefono.
oppure apri lo store

