Guide · 22 min di lettura

ESP32 Brownout Detector was triggered: cause e soluzioni

ESP32 Brownout detector was triggered e riavvii continui: alimentatore, cavo, condensatore, codici rst, Guru Meditation, Task WDT ed ESP Exception Decoder.

Il messaggio ESP32 Brownout detector was triggered significa che la tensione di alimentazione della scheda è scesa per un attimo sotto un limite sicuro e che il chip si è riavviato per proteggersi. Il problema quasi mai è nel codice, ma nell'alimentazione: una porta USB debole, un cavo sottile e lungo, un regolatore insufficiente oppure servo e strisce LED alimentati dalla stessa linea dell'ESP32. Il secondo grande motivo per cui un ESP32 continua a riavviarsi sono i crash del software; in questo caso il Monitor seriale mostra righe come Guru Meditation Error, task_wdt o Stack canary.

La buona notizia: l'ESP32 ti dice da solo perché si è riavviato, basta saper leggere i suoi messaggi. In questa guida imparerai prima a riconoscere i codici rst nelle righe di avvio e i messaggi di errore, poi risolverai il brownout una volta per tutte con l'alimentatore, il cavo e un condensatore. Dopo vedremo gli errori Guru Meditation come LoadProhibited e StoreProhibited, l'overflow dello stack, i puntatori nulli e i timeout del watchdog, e seguirai un crash fino alla riga di codice con ESP Exception Decoder. Infine daremo un'occhiata ai pin di strapping (GPIO0, 2, 12 e 15) che possono rovinare l'avvio.

Scheda di sviluppo ESP32 DevKit
Scheda di sviluppo ESP32: i 5 V dell'USB vengono abbassati a 3,3 V dal regolatore sulla scheda. La maggior parte dei problemi di brownout nasce da brevi cali su questa linea a 3,3 V.

Perché l'ESP32 continua a riavviarsi? Prima leggi il messaggio

Prima di iniziare la diagnosi, apri il Monitor seriale a 115200 baud e premi il pulsante EN della scheda. A ogni avvio il bootloader in ROM dell'ESP32 stampa prima una riga con una data come "ets Jun 8 2016 00:22:57" e poi una riga del tipo rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT). La parte rst indica perché la scheda si è riavviata, la parte boot in quale modalità è partita. Se la scheda è entrata in un ciclo, subito sopra queste righe trovi il messaggio di errore, le ultime parole dell'esecuzione precedente. La tabella riassume i messaggi che vedrai e da dove partire:

Cosa vedi nel Monitor serialeSignificatoDove guardare
Brownout detector was triggeredLa tensione di alimentazione è scesa sotto la sogliaAlimentatore, cavo, condensatore
Guru Meditation Error: Core 1 panic'ed (LoadProhibited)Il codice ha tentato di leggere da un indirizzo non validoPuntatore nullo, limiti di un array
Guru Meditation Error: Core 1 panic'ed (StoreProhibited)Il codice ha tentato di scrivere in un indirizzo non validoPuntatore nullo, buffer che trabocca
Stack canary watchpoint triggered (loopTask)Lo stack di un task si è riempitoGrandi array locali, ricorsione
task_wdt: Task watchdog got triggeredUn task non ha rilasciato la CPU per più di 5 secondiCicli senza pause, task bloccati
Interrupt wdt timeout on CPU0 / CPU1Un interrupt o gli interrupt disattivati hanno superato i 300 msISR lunga, Serial dentro la ISR
boot:0x3 (DOWNLOAD_BOOT...) waiting for downloadLa scheda è partita in modalità programmazioneGPIO0 LOW all'avvio
invalid header o flash read errNon è stato possibile leggere la memoria flashGPIO12 HIGH all'avvio, caricamento interrotto

Che cos'è "Brownout detector was triggered" e perché succede?

Un brownout è un breve calo di tensione senza una vera interruzione dell'alimentazione. L'ESP32 contiene un rilevatore di brownout che controlla di continuo l'alimentazione, e nel core Arduino la sua soglia è impostata al livello più basso, circa 2,43 V. Appena la tensione scende sotto questo valore, il chip mette al sicuro la radio e la memoria flash, scrive "Brownout detector was triggered" nel Monitor seriale e si riavvia. Il motivo è semplice: con una tensione bassa la flash può essere letta male, i dati salvati possono corrompersi e la CPU può eseguire istruzioni a caso. Il rilevatore fa ripartire la scheda in modo pulito invece di lasciarla comportarsi in modo imprevedibile. Il modulo ESP32-WROOM-32 è progettato per funzionare tra 3,0 e 3,6 V, quindi quando la linea arriva a 2,43 V è già da tempo fuori dalla zona sicura.

Dopo un messaggio di brownout, la riga di avvio mostra rst:0xc (SW_CPU_RESET) oppure rst:0x3 (SW_RESET) a seconda della versione del core Arduino, perché l'interrupt del rilevatore stampa il messaggio e poi riavvia il chip via software. Non farti ingannare: lo stesso codice annota nella memoria del chip che la causa è stata un brownout, e esp_reset_reason() restituisce ESP_RST_BROWNOUT. Quando interviene il reset per brownout dell'hardware stesso, la riga riporta invece rst:0xf (RTCWDT_BROWN_OUT_RESET). Nei core 3.x, basati su ESP-IDF 5, questa riga è diventata un messaggio di log di livello info (I BOD: Brownout detector was triggered). Poiché le librerie precompilate del core Arduino scrivono solo i log di livello errore, il messaggio di solito non compare affatto e la scheda si riavvia in silenzio; se all'avvio vedi un rst:0x3 o rst:0xc inspiegabile, controlla il motivo del reset con lo sketch di diagnosi più avanti. Per capire perché la tensione cala, bisogna guardare quanta corrente assorbe l'ESP32:

Stato di funzionamentoCorrente tipica (chip ESP32)
Deep sleep (timer RTC attivo)Circa 10 µA
Light sleepCirca 0,8 mA
Wi-Fi spento, CPU a 240 MHz30–68 mA
Ricezione Wi-Fi (RX)95–100 mA
Trasmissione Wi-Fi, 802.11b, 19,5 dBmCirca 240 mA
Calibrazione radio all'avvio e momento della connessionePuò superare i 400 mA in picchi di pochi microsecondi

Questa differenza è il cuore del brownout: finché il tuo codice non accende il Wi-Fi, la scheda lavora tranquilla con circa 50 mA, ma alla riga WiFi.begin() la corrente si moltiplica per cinque o sei in pochi microsecondi. Se alimentatore, cavo e regolatore non riescono a stare dietro a questa richiesta improvvisa, la tensione crolla. Per questo Espressif consiglia per l'ESP32 un alimentatore in grado di fornire almeno 500 mA. Il sintomo è molto familiare: la scheda si avvia, scrive qualche riga nel Monitor seriale, si riavvia proprio quando parte il Wi-Fi o il Bluetooth e tutto diventa un ciclo infinito. Lo stesso può succedere quando si muove un servo, scatta un relè o una striscia LED diventa bianca.

Le cause più comuni del brownout

  • Cavo USB sottile o lungo: i fili di alimentazione sottili dei cavi economici possono arrivare a 0,5 Ω tra andata e ritorno. Per la legge di Ohm, un picco di 400 mA perde 0,2 V in un cavo così.
  • Porta USB debole o hub: le porte di tastiere e monitor, gli hub non alimentati e le porte frontali di alcuni portatili fanno calare la tensione nei picchi di corrente.
  • Caduta del regolatore (dropout): l'AMS1117 presente sulla maggior parte delle schede ha bisogno di 1,0–1,3 V di differenza tra ingresso e uscita. Se la tensione sul pin 5V scende sotto circa 4,3 V, l'uscita non riesce a mantenere 3,3 V.
  • Collegare direttamente una batteria: una batteria al litio da 3,7 V sul pin 5V porta l'uscita sotto i 3 V a causa del dropout del regolatore; due pile AA sotto carico scendono presto sotto il minimo dell'ESP32.
  • Il pin 3.3V dell'Arduino Uno: da questo pin si consiglia di prelevare solo circa 50 mA; per un ESP32 con il Wi-Fi attivo non basta assolutamente.
  • Carichi sulla stessa linea: se servo, relè, buzzer, motori DC o una striscia WS2812B sono alimentati dagli stessi 5 V dell'ESP32, ogni movimento trascina giù la tensione.
  • Breadboard e cavetti jumper: contatti allentati e jumper sottili aggiungono un po' di resistenza a ogni collegamento; far passare l'alimentazione dalla breadboard peggiora il problema.
  • ESP32-CAM: quando fotocamera, Wi-Fi e LED flash funzionano insieme, la corrente sale molto; questa scheda vuole 5 V e almeno 2 A. Trovi i dettagli nella guida ESP32-CAM.
Leggere 3,3 V sul multimetro non significa che l'alimentazione sia solida. Un multimetro fa solo poche misure al secondo e mostra un valore vicino a una media, mentre i cali che provocano il brownout durano da pochi microsecondi a pochi millisecondi e non compaiono mai sul display. Solo un oscilloscopio può mostrarli. Se non ne hai uno, applica le soluzioni seguenti nell'ordine e controlla dopo ogni passo se l'errore è sparito. Le basi della misura sono in Come usare il multimetro.

Soluzione 1: migliora l'alimentatore e il cavo

Il primo passo, e il più efficace, è rinforzare l'alimentazione. Collega la scheda con un cavo dati corto, spesso e che sai essere buono, direttamente a una porta USB sul retro del computer oppure a un alimentatore da 5 V da almeno 1 A. Le porte USB 2.0 sono progettate per dare 500 mA e le USB 3.0 900 mA; i 500 mA consigliati da Espressif sono proprio il limite di una porta USB 2.0, e appena si aggiungono le perdite del cavo iniziano i guai. Se basta cambiare cavo per eliminare l'errore, la colpa era molto probabilmente della sua resistenza. Puoi calcolare quanta tensione perde un cavo con V = I × R nello strumento Legge di Ohm.

Regolatore di tensione AMS1117 da 3,3 V
AMS1117-3.3: il regolatore della maggior parte delle schede ESP32. Ha bisogno di 1,0–1,3 V di differenza tra ingresso e uscita; se il pin 5V scende sotto circa 4,3 V, la sua uscita non riesce a mantenere 3,3 V.
Tipo di alimentazioneRischio di brownoutNota
Cavo corto e spesso e porta USB posterioreBassoLa soluzione più semplice durante lo sviluppo
Cavo lungo e sottile, porta frontale o hubAltoLa resistenza del cavo fa calare la tensione nei picchi
Alimentatore da 5 V e almeno 1 A sul pin 5V o VINBassoConsigliato per i progetti definitivi
Sorgente da 3,3 V già pronta direttamente sul pin 3V3Dipende dalla sorgenteDeve fornire almeno 500 mA e non superare mai 3,6 V
Batteria al litio da 3,7 V tramite l'AMS1117AltoSotto circa 4 V sulla batteria, l'uscita scende sotto 3 V
Batteria al litio con regolatore 3,3 V a bassa caduta (LDO) o buck-boostBassoFornisce 3,3 V stabili anche mentre la batteria si scarica
Due pile AA direttamente sul pin 3V3Molto altoSotto carico la tensione scende in fretta sotto il minimo dell'ESP32

Nei progetti a batteria serve attenzione. Una cella al litio come la 18650 dà 4,2 V carica e circa 3,0 V scarica. Questo intervallo non va bene né collegato direttamente al pin 3V3 (4,2 V superano il limite di 3,6 V) né al pin 5V con il suo AMS1117. La soluzione corretta è portare la batteria al pin 5V con un modulo elevatore (boost) da 5 V, oppure alimentare direttamente la linea 3V3 con un LDO a bassa caduta capace di erogare almeno 500 mA (per esempio ME6211 o HT7833) più un condensatore. Puoi stimare quanto durerà il tuo progetto a batteria con lo strumento Durata della batteria e conoscere il circuito di ricarica nella guida al modulo di ricarica TP4056.

Soluzione 2: aggiungi un condensatore tra 3V3 e GND

Un condensatore funziona come un piccolo serbatoio che fornisce energia durante un picco di corrente finché il regolatore e il cavo non recuperano. Metti tra i pin 3V3 e GND, il più vicino possibile alla scheda, un condensatore elettrolitico da 100–470 µF e accanto un condensatore ceramico da 100 nF. L'elettrolitico copre i cali dell'ordine dei millisecondi, il ceramico le oscillazioni brevissime ad alta frequenza. Puoi vederne l'effetto in modo approssimativo con ΔV = I × Δt / C: anche se un condensatore da 470 µF fornisse da solo 200 mA in più per 200 µs, la tensione calerebbe di appena 0,085 V. La scritta 104 su un condensatore ceramico significa 100 nF; puoi decifrare gli altri codici con lo strumento Codice dei condensatori.

Tipi di condensatori
Nei condensatori elettrolitici la gamba lunga è il polo positivo (+) e va su 3V3; la gamba dal lato della striscia sul corpo va su GND. Per la linea a 3,3 V basta un modello da 6,3 V o 10 V.
Non montare mai un elettrolitico al contrario: si scalda, si gonfia e può scoppiare. Se lo colleghi alla linea 5V, scegline uno da almeno 10 V. I condensatori molto grandi (da 1000 µF in su) richiedono una forte corrente di carica all'accensione, che può mettere sotto sforzo per un attimo la porta USB e rallentare la salita della linea a 3,3 V; su 3V3, 470 µF bastano per la maggior parte dei progetti. Come funzionano i condensatori lo spieghiamo in Che cos'è un condensatore?

Soluzione 3: alimenta separatamente servo, motori e strisce LED

Anche se l'ESP32 è alimentato bene, i carichi collegati alla stessa linea possono far calare la tensione. Perfino un piccolo servo come l'SG90 assorbe qualche centinaio di mA quando inizia a muoversi; un LED WS2812B consuma circa 60 mA a bianco pieno, quindi una striscia da 30 LED può arrivare a 1,8 A. Alimenta questi carichi non dal pin 5V o 3V3 dell'ESP32 ma da una sorgente da 5 V separata; per esempio puoi abbassare un alimentatore da 12 V a 5 V con un modulo step-down LM2596. La regola più importante è collegare tra loro i GND delle due sorgenti; senza una massa comune la linea del segnale non ha un riferimento e il servo o la striscia si comportano a caso. Ne parliamo in dettaglio in Arduino si resetta da solo? e GND e massa comune.

Modulo step-down (buck) LM2596
Modulo step-down LM2596: abbassa in modo efficiente 12 V a 5 V ed è ideale per alimentare carichi come servo, relè o strisce LED separatamente dall'ESP32. L'uscita si regola con un trimmer; impostala a 5 V con il multimetro prima di collegare qualcosa.
Puoi anche attenuare i picchi di corrente via software. Avvia il Wi-Fi prima di muovere i servo o di accendere la striscia LED; limita la luminosità della striscia con setBrightness(); attiva servo e relè a qualche centinaio di millisecondi di distanza invece che tutti insieme. Anche abbassare la potenza di trasmissione Wi-Fi con WiFi.setTxPower() riduce il picco di corrente; i dettagli sono in L'ESP32 non si connette al WiFi.

Disattivare il rilevatore di brownout è una soluzione?

La "soluzione" più proposta in rete è spegnere il rilevatore con una sola riga. Il codice qui sotto disattiva il rilevatore azzerando il registro di brownout dell'ESP32, e il messaggio di errore sparisce. Ma i cali di tensione continuano; semplicemente nessuno ti avvisa più. Usa questo codice solo per la diagnosi: se con il rilevatore spento la scheda funziona bene, hai la conferma che il problema è sicuramente l'alimentazione. Poi cancella la riga e sistema l'alimentazione.

C++ (Arduino IDE)
1#include "soc/soc.h"
2#include "soc/rtc_cntl_reg.h"
3
4void setup() {
5  // YALNIZ TEŞHİS İÇİN: brownout dedektörünü kapat / DIAGNOSIS ONLY: disable the brownout detector
6  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
7
8  Serial.begin(115200);
9  Serial.println("Brownout dedektoru kapali / brownout detector disabled");
10}
11
12void loop() {
13}
Non lasciare il rilevatore disattivato in modo permanente. WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0) non si limita a zittire l'avviso: disattiva anche il reset hardware del rilevatore e il suo compito di spegnere flash e radio quando la tensione è bassa, così il chip continua a funzionare senza protezione ben al di sotto del suo minimo di 3,0 V. Quando la tensione scende sotto 2,4 V, i dati scritti in flash (Preferences, EEPROM, LittleFS), e perfino il programma stesso durante un aggiornamento OTA, possono corrompersi, il Wi-Fi può cadere senza un motivo apparente e la scheda può bloccarsi questa volta con errori Guru Meditation o congelarsi del tutto. L'impostazione non è permanente: il chip riattiva il rilevatore a ogni avvio, quindi la riga deve essere la prima di setup(), e appena la cancelli la protezione torna. Questo registro esiste sull'ESP32 classico, sull'S2, sull'S3 e sul C3; i modelli più recenti come l'ESP32-C6 non lo hanno e il codice non si compila. La vera soluzione è sempre sistemare l'alimentazione.

Codici rst: l'ESP32 ti dice perché si è riavviato

Il valore rst: che la ROM stampa a ogni avvio indica come si è conclusa l'esecuzione precedente. In un avvio normale il valore boot è 0x13 (SPI_FAST_FLASH_BOOT), cioè la scheda avvia il programma dalla flash. La tabella riassume i codici che incontrerai più spesso. I codici della ROM non sempre bastano da soli: ESP.restart() e il riavvio dopo un Guru Meditation compaiono entrambi con il codice 0xc, mentre un brownout appare come 0xc o 0x3 a seconda della versione del core. Per distinguerli, usa lo sketch con esp_reset_reason() della prossima sezione.

Codice rstNomeChe cosa significa?
0x1POWERON_RESETAlimentazione collegata per la prima volta o pulsante EN premuto
0x3SW_RESETIl software ha resettato l'intero sistema digitale; nelle versioni recenti del core compare anche dopo un brownout
0x5DEEPSLEEP_RESETLa scheda si è svegliata dal deep sleep (normale)
0x7 / 0x8TG0WDT_SYS_RESET / TG1WDT_SYS_RESETUn watchdog di un gruppo timer ha resettato il sistema via hardware; gli interrupt sono rimasti disattivati troppo a lungo o non è riuscito a partire nemmeno il gestore di panic
0x9RTCWDT_SYS_RESETIl watchdog dell'RTC ha resettato il core digitale
0xcSW_CPU_RESETRiavvio software: ESP.restart(), dopo un Guru Meditation o dopo un brownout nel core Arduino
0xfRTCWDT_BROWN_OUT_RESETReset hardware per brownout: tensione di alimentazione instabile
0x10RTCWDT_RTC_RESETIl watchdog dell'RTC ha resettato tutto il chip, RTC compreso; si vede soprattutto su schede che si bloccano durante l'avvio

Sketch di diagnosi: stampa il motivo del reset, la memoria e lo stack

Carica il codice qui sotto come sketch separato oppure aggiungi le sue righe al setup() e al loop() del progetto che dà problemi. A ogni avvio la scheda scrive nel Monitor seriale il motivo del reset in testo leggibile, quante volte si è avviata e lo stato della memoria. Il contatore segnato con RTC_DATA_ATTR è salvato nella memoria RTC, quindi sopravvive ai reset software e al deep sleep e si azzera solo quando l'alimentazione viene tolta del tutto. Così, se il contatore sale ogni pochi secondi, capisci subito che la scheda è bloccata in un ciclo di reset.

C++ (Arduino IDE)
1#include <esp_system.h>
2
3RTC_DATA_ATTR uint32_t bootCount = 0;   // yazılım resetinde korunur / survives software resets
4
5// Reset nedenini okunabilir yazıya çevir / turn the reset reason into readable text
6const char* reasonText(esp_reset_reason_t r) {
7  switch (r) {
8    case ESP_RST_POWERON:   return "POWERON: guc acilisi ya da EN / power-on or EN button";
9    case ESP_RST_SW:        return "SW: ESP.restart()";
10    case ESP_RST_PANIC:     return "PANIC: Guru Meditation";
11    case ESP_RST_INT_WDT:   return "INT_WDT: kesme watchdog'u / interrupt watchdog";
12    case ESP_RST_TASK_WDT:  return "TASK_WDT: gorev watchdog'u / task watchdog";
13    case ESP_RST_WDT:       return "WDT: diger watchdog / other watchdog";
14    case ESP_RST_DEEPSLEEP: return "DEEPSLEEP: derin uykudan uyanma / deep sleep wake-up";
15    case ESP_RST_BROWNOUT:  return "BROWNOUT: gerilim dusmesi / supply voltage dropped";
16    default:                return "UNKNOWN: bilinmiyor / unknown";
17  }
18}
19
20void setup() {
21  Serial.begin(115200);
22  delay(1000);                          // Seri Monitör'ün açılmasını bekle / wait for the Serial Monitor
23  bootCount++;
24  Serial.printf("Acilis sayisi / boot count: %u\n", (unsigned)bootCount);
25  Serial.printf("Reset nedeni / reset reason: %s\n", reasonText(esp_reset_reason()));
26}
27
28void loop() {
29  // Bellek durumu / memory status
30  Serial.printf("Bos heap / free heap: %u B, en dusuk / minimum: %u B, en buyuk blok / largest block: %u B\n",
31                (unsigned)ESP.getFreeHeap(), (unsigned)ESP.getMinFreeHeap(), (unsigned)ESP.getMaxAllocHeap());
32  // loopTask yığınında hiç kullanılmamış en küçük alan / smallest unused space on the loopTask stack
33  Serial.printf("loopTask bos yigin / free stack: %u B\n", (unsigned)uxTaskGetStackHighWaterMark(NULL));
34  delay(5000);
35}

I valori che il codice stampa nel ciclo rivelano anche problemi silenziosi. Se l'heap libero cala un po' a ogni giro, il tuo programma ha una perdita di memoria e prima o poi la scheda andrà in crash. Se il blocco più grande è molto più piccolo dell'heap libero, la memoria è frammentata; di solito dipende da oggetti String che crescono e si restringono di continuo nel ciclo. Se lo stack libero di loopTask scende sotto qualche centinaio di byte, l'overflow dello stack è dietro l'angolo. Se il motivo del reset è BROWNOUT, concentrati sulle sezioni sull'alimentazione; se è PANIC, TASK_WDT o INT_WDT, sulle sezioni software che seguono.

Che cos'è un Guru Meditation Error? Leggi il report del crash riga per riga

Un Guru Meditation Error è il report di crash che il gestore di panic stampa quando la CPU dell'ESP32 incontra un errore da cui non può riprendersi; il nome viene dalla schermata di errore dei vecchi computer Amiga. A prima vista fa paura, ma contano solo poche righe. Core 1 indica su quale core è avvenuto l'errore: con Arduino, setup() e loop() girano sul core 1, mentre lo stack Wi-Fi gira sul core 0. Il nome tra parentesi è il tipo di eccezione. Alla fine del report la scheda scrive "Rebooting..." e si riavvia; nella riga di avvio vedrai rst:0xc.

RigaSignificato
Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.Il codice sul core 1 ha tentato di leggere da un indirizzo non valido e l'errore non è stato gestito
PC : 0x400d1a2cIndirizzo dell'istruzione che ha causato il crash; se inizia con 0x400d, il tuo codice o una libreria girava dalla flash
EXCCAUSE: 0x0000001cCodice dell'eccezione; 0x1c, cioè 28, significa LoadProhibited
EXCVADDR: 0x00000000Indirizzo a cui si è tentato di accedere; 0 o un numero molto piccolo indica un puntatore nullo
Backtrace: 0x400d1a29:0x3ffb2270 0x400d0f6e:0x3ffb2290 ...Catena delle chiamate; ogni coppia ha la forma PC:SP e il decoder la traduce in una riga di codice
ELF file SHA256: ...Impronta del programma andato in crash; il decoder ha bisogno esattamente della stessa compilazione
Rebooting...Il gestore di panic riavvia il chip via software

LoadProhibited, StoreProhibited e gli altri tipi di eccezione

EccezioneEXCCAUSEChe cosa è successo?Causa frequente
LoadProhibited28 (0x1c)Lettura da un indirizzo non validoPuntatore nullo o non inizializzato, oggetto eliminato
StoreProhibited29 (0x1d)Scrittura in un indirizzo non validoScrittura tramite un puntatore nullo, buffer che esce dall'array
InstrFetchProhibited20 (0x14)Lettura di un'istruzione da un indirizzo non validoPuntatore a funzione o callback non assegnati
IllegalInstruction0 (0x0)Istruzione non validaStack corrotto, return dimenticato in una funzione che deve restituire un valore
LoadStoreAlignment9 (0x9)Accesso alla memoria non allineatoConvertire a forza un array di byte in un tipo come uint32_t*
IntegerDivideByZero6 (0x6)Divisione intera per zeroDividere per un contatore che può valere zero
Unhandled debug exception-Eccezione di debugStack canary watchpoint triggered: overflow dello stack
Interrupt wdt timeout on CPU0/CPU1-Il watchdog degli interrupt è scadutoISR lunga, Serial o delay dentro la ISR
Cache disabled but cached memory region accessed-Accesso a codice in flash mentre la flash era occupataFunzione di interrupt senza IRAM_ATTR

Il più comune di questi errori è l'uso di un puntatore nullo. NULL corrisponde all'indirizzo 0 e sull'ESP32 non c'è memoria leggibile intorno all'indirizzo 0, quindi leggere dove punta un puntatore vuoto dà LoadProhibited e scriverci dà StoreProhibited. In questo caso EXCVADDR è un indizio perfetto: 0x00000000 indica il puntatore stesso, mentre valori piccoli come 0x00000004 o 0x00000010 indicano un campo dentro un puntatore vuoto (NULL più la posizione del campo). Nei progetti Arduino la causa più frequente è una funzione che restituisce NULL per dire "non trovato" e quel valore viene usato senza controllo. Nell'esempio qui sotto strstr() restituisce NULL se non trova il testo; senza controllo la scheda va in crash con EXCVADDR 0x00000005.

C++ (Arduino IDE)
1const char* response = "temp=23.5;hum=40";   // sunucudan gelen yanıt / reply from a server
2
3void setup() {
4  Serial.begin(115200);
5  delay(500);
6
7  // YANLIŞ: "pres=" yoksa strstr NULL döner ve kart çöker (EXCVADDR 0x00000005)
8  // WRONG: if "pres=" is missing strstr returns NULL and the board crashes (EXCVADDR 0x00000005)
9  // float pressure = atof(strstr(response, "pres=") + 5);
10
11  // DOĞRU: işaretçiyi kullanmadan önce NULL kontrolü yap / RIGHT: check for NULL before using the pointer
12  const char* found = strstr(response, "pres=");
13  if (found != nullptr) {
14    float pressure = atof(found + 5);
15    Serial.println(pressure);
16  } else {
17    Serial.println("pres alani bulunamadi / pres field not found");
18  }
19}
20
21void loop() {
22}
Prendi qualche buona abitudine contro i puntatori nulli: inizializza i puntatori con nullptr quando li dichiari, controlla il valore restituito dalle funzioni begin() delle librerie, rimetti il puntatore a nullptr dopo aver fatto delete di un oggetto e assicurati che l'indice sia minore della dimensione dell'array quando ci scrivi. Se nell'IDE di Arduino imposti gli avvisi del compilatore su Tutti da File > Impostazioni, vedrai un return dimenticato ed errori simili già in compilazione.

Overflow dello stack: l'errore "Stack canary watchpoint triggered"

Sull'ESP32 ogni task ha uno stack di dimensione fissa, dove vengono salvati le variabili locali, le chiamate di funzione e gli indirizzi di ritorno. Con Arduino, il task loopTask che esegue setup() e loop() ha uno stack di 8192 byte. Dichiarare un array locale da 10.000 byte dentro loop(), una funzione che richiama sé stessa (ricorsiva) o una funzione di libreria con molte variabili locali supera questo limite. Alla fine dello stack c'è una zona di guardia (canary); quando lo stack la raggiunge, la scheda scrive Guru Meditation Error: Core 1 panic'ed (Unhandled debug exception) e subito sotto Debug exception reason: Stack canary watchpoint triggered (loopTask). Il nome tra parentesi è il task il cui stack è traboccato. A volte lo stesso problema si presenta come ***ERROR*** A stack overflow in task loopTask has been detected. Ecco come risolverlo:

  • Togli i grandi array dallo stack: dichiara l'array come globale o aggiungi static davanti; così si trova nella RAM permanente e non sullo stack.
  • Ingrandisci lo stack di loopTask: scrivi SET_LOOP_TASK_STACK_SIZE(16 * 1024); in cima allo sketch per portare lo stack di loop() a 16 KB.
  • Dai abbastanza spazio ai tuoi task: sull'ESP32 la dimensione dello stack passata a xTaskCreate e xTaskCreatePinnedToCore è in byte, non in word come in FreeRTOS su altre piattaforme. 1024 byte sono pochi perfino per un task che usa Serial.printf; parti da 4096.
  • Misura: uxTaskGetStackHighWaterMark(NULL) restituisce in byte la quantità minima di stack che il task non ha mai usato finora; se scende sotto qualche centinaio di byte, ingrandisci lo stack.
  • Evita la ricorsione: trasforma le funzioni che richiamano sé stesse in cicli o limitane la profondità.

Task watchdog: l'errore "task_wdt: Task watchdog got triggered"

Un watchdog (cane da guardia) è un timer che si accorge di un programma bloccato e salva la scheda. Il watchdog dei task (Task WDT) dell'ESP32 si aspetta che i task registrati diano segni di vita a intervalli regolari. Nel core Arduino controlla di default il task inattivo (IDLE) del core 0, con un tempo di 5 secondi. Se un task sul core 0 non rilascia la CPU per 5 secondi, il task IDLE non può girare e nel Monitor seriale compare un messaggio che inizia con E (10257) task_wdt: Task watchdog got triggered. Subito dopo arrivano l'elenco dei task che non hanno azzerato il watchdog in tempo (di solito - IDLE (CPU 0)) e, sotto Tasks currently running:, i task in esecuzione in quel momento. Nel core Arduino questo provoca un panic con la riga task_wdt: Aborting. e la scheda si riavvia.

Le cause più frequenti sono: un ciclo assegnato al core 0 con xTaskCreatePinnedToCore senza nemmeno un vTaskDelay(), un while che aspetta la risposta di un sensore senza timeout, oppure delay() e operazioni lunghe dentro le funzioni callback di librerie come AsyncWebServer. Nell'ultimo caso nell'elenco vedrai il task async_tcp al posto di IDLE. La soluzione è dividere i lavori lunghi in piccoli pezzi e aggiungere ai cicli brevi attese come vTaskDelay(1). La funzione loop() di per sé non è controllata di default; se vuoi, chiama enableLoopWDT() in setup() perché la scheda si riavvii anche quando loop() resta bloccato per più di 5 secondi. Spegnere il watchdog con disableCore0WDT() nasconde l'errore ma non sistema il codice bloccato. Per saperne di più su task e core, leggi FreeRTOS e dual core sull'ESP32. Il codice qui sotto mostra una struttura corretta dei task e le precauzioni contro l'overflow dello stack:

C++ (Arduino IDE)
1SET_LOOP_TASK_STACK_SIZE(16 * 1024);   // loop() yığını 8 KB yerine 16 KB / loop() stack 16 KB instead of 8 KB
2
3volatile uint32_t sampleCount = 0;
4
5// 0. çekirdekte çalışan görev / task running on core 0
6void sensorTask(void* parameter) {
7  for (;;) {
8    sampleCount = sampleCount + 1;       // sensörünü burada oku / read your sensor here
9    vTaskDelay(pdMS_TO_TICKS(10));       // IDLE görevine sıra ver, task_wdt tetiklenmez / let IDLE run, no task_wdt
10  }
11}
12
13void setup() {
14  Serial.begin(115200);
15  // Yığın boyutu bayt cinsindendir: 4096 bayt / stack size is in bytes: 4096 bytes
16  xTaskCreatePinnedToCore(sensorTask, "sensorTask", 4096, NULL, 1, NULL, 0);
17}
18
19void loop() {
20  static uint8_t buffer[10000];          // static: yığında değil kalıcı RAM'de / static: in RAM, not on the stack
21  memset(buffer, 0, sizeof(buffer));
22
23  Serial.printf("Ornek / samples: %u, loopTask bos yigin / free stack: %u B\n",
24                (unsigned)sampleCount, (unsigned)uxTaskGetStackHighWaterMark(NULL));
25  delay(1000);
26}

Interrupt wdt timeout e IRAM_ATTR: crash negli interrupt

Il watchdog degli interrupt (Interrupt WDT) è molto più impaziente: se una funzione di interrupt (ISR) o un pezzo di codice con gli interrupt disattivati supera i 300 ms, la scheda va in crash con Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1). Usare Serial.print, delay(), I2C o il Wi-Fi dentro una ISR è la causa più frequente. Un'altra trappola è la memoria flash: mentre Preferences, EEPROM o LittleFS scrivono in flash, la cache della flash viene disattivata per un istante. Se in quel momento arriva un interrupt la cui funzione si trova in flash, la scheda dà l'errore Cache disabled but cached memory region accessed. La soluzione è contrassegnare le ISR con IRAM_ATTR, così stanno in RAM, e limitarsi ad alzare un flag al loro interno; il lavoro vero lo fa loop(). Le variabili condivise tra la ISR e loop() devono essere volatile.

C++ (Arduino IDE)
1const int BUTTON_PIN = 27;              // buton GPIO 27 ile GND arasında / button between GPIO 27 and GND
2volatile bool buttonPressed = false;    // ISR ile loop arasında paylaşılan bayrak / flag shared by the ISR and loop
3uint32_t pressCount = 0;
4
5void IRAM_ATTR onButton() {             // IRAM_ATTR: fonksiyon flaşta değil RAM'de durur / the function lives in RAM, not flash
6  buttonPressed = true;                 // yalnızca bayrak kaldır, Serial yok / only set a flag, no Serial
7}
8
9void setup() {
10  Serial.begin(115200);
11  pinMode(BUTTON_PIN, INPUT_PULLUP);
12  attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), onButton, FALLING);
13}
14
15void loop() {
16  if (buttonPressed) {
17    buttonPressed = false;
18    pressCount++;
19    Serial.printf("Butona basildi / button pressed: %u\n", (unsigned)pressCount);   // yavaş iş burada / slow work here
20  }
21}

Trasformare il Backtrace in una riga di codice con ESP Exception Decoder

Gli indirizzi nella riga Backtrace da soli non dicono nulla; lo strumento che li traduce in file, funzione e numero di riga del tuo codice sorgente si chiama ESP Exception Decoder. Nel vecchio IDE Arduino 1.8 era un plugin aggiunto al menu Strumenti. Nell'IDE Arduino 2 si usa un'estensione della community con lo stesso nome:

  1. Scarica il file con estensione .vsix dalla sezione Releases del progetto dankeboy36/esp-exception-decoder su GitHub. Per l'IDE Arduino 2 scegli una versione 1.x; le nuove versioni 2.x sono pensate per VS Code.
  2. Chiudi l'IDE Arduino e copia il file in %UserProfile%\.arduinoIDE\plugins su Windows oppure in ~/.arduinoIDE/plugins su macOS e Linux; se la cartella non esiste, creala.
  3. Apri l'IDE e lo sketch che va in crash, compilalo con Verifica e caricalo sulla scheda.
  4. Apri il Monitor seriale e aspetta che il crash si ripeta.
  5. Apri la tavolozza dei comandi con Ctrl+Shift+P (Cmd+Shift+P su macOS) ed esegui ESP Exception Decoder: Show Decoder Terminal.
  6. Copia dal Monitor seriale il blocco Guru Meditation insieme alla riga Backtrace e incollalo nel terminale che si apre; lo strumento mostra ogni indirizzo con nome del file, funzione e numero di riga.

Se non riesci a installare l'estensione, puoi fare lo stesso a mano. Il menu Sketch > Export Compiled Binary lascia un file con estensione .elf nella cartella build all'interno della cartella dello sketch. Il comando xtensa-esp32-elf-addr2line -pfiaC -e sketch.ino.elf 0x400d1a29 0x400d0f6e della toolchain dell'ESP32 traduce questi indirizzi in nomi di funzione e numeri di riga. Se usi PlatformIO, basta aggiungere la riga monitor_filters = esp32_exception_decoder al file platformio.ini; il report del crash viene decodificato automaticamente nel monitor seriale.

Il decoder dà risultati corretti solo con il file .elf esattamente della stessa compilazione andata in crash. Se cambi una sola riga e ricompili, gli indirizzi si spostano e l'output indica righe sbagliate. Se la riga Backtrace termina con CORRUPTED, lo stack è danneggiato; di solito è il segno di un overflow dello stack o di un buffer che ha superato i suoi limiti.

Pin di strapping: come GPIO0, GPIO2, GPIO12 e GPIO15 rovinano l'avvio

All'avvio l'ESP32 guarda il livello di alcuni pin per decidere come partire. Si chiamano pin di strapping e conta solo il loro livello nel momento del reset; finito l'avvio, si possono usare come normali GPIO. Il problema nasce quando un sensore, un pulsante o un modulo collegato porta il pin al livello sbagliato durante l'avvio. A quel punto la scheda non avvia il programma, entra in modalità programmazione o non riesce a leggere la flash; da fuori anche questo sembra "l'ESP32 non si avvia" oppure "continua a resettarsi". Puoi vedere la piedinatura completa della tua scheda nello strumento Pinout.

PinResistenza internaRuolo all'avvioCosa succede con il livello sbagliato?
GPIO0Pull-upLOW attiva la modalità programmazione (download), HIGH l'avvio normaleboot:0x3 (DOWNLOAD_BOOT) e waiting for download; il programma non parte
GPIO2Pull-downDeve essere LOW o scollegato per entrare in programmazione; nell'avvio normale non contaUn circuito che lo porta a HIGH impedisce il caricamento
GPIO12 (MTDI)Pull-downSceglie la tensione della flash: LOW 3,3 V, HIGH 1,8 VSe HIGH, una flash da 3,3 V non viene alimentata bene; la scheda non parte o entra in un ciclo di reset
GPIO15 (MTDO)Pull-upSe LOW silenzia i messaggi di avvio della ROMLe righe di avvio non compaiono nel Monitor seriale e la diagnosi diventa più difficile
GPIO5Pull-upImposta il timing SDIORaramente crea problemi sulle schede di sviluppo
Una resistenza di pull-up, un relè o un modulo sensore su GPIO12 che porta il pin a HIGH all'avvio è il motivo più nascosto per cui un ESP32 non si avvia affatto. Se devi usare questo pin, assicurati che il modulo lo lasci LOW al momento dell'avvio. In alternativa il comando espefuse.py set_flash_voltage 3.3V fornito con esptool scrive in modo permanente la tensione della flash in un eFuse ed elimina l'effetto di GPIO12 all'avvio; però non si può annullare e va fatto solo su moduli con flash da 3,3 V (come l'ESP32-WROOM-32).

Le schede più recenti hanno pin di strapping diversi: sull'ESP32-S3 influiscono sull'avvio GPIO0, GPIO3, GPIO45 e GPIO46, sull'ESP32-C3 GPIO2, GPIO8 e GPIO9. L'ESP32-S3 usa gli stessi nomi di eccezione Xtensa dell'ESP32 classico. Sull'ESP32-C3 con core RISC-V vedrai invece Load access fault al posto di LoadProhibited e Store access fault al posto di StoreProhibited, e il registro MTVAL prende il ruolo di EXCVADDR. Il messaggio di brownout è uguale su tutti i modelli.

ESP32 e Raspberry Pi Pico con MicroPython

Se programmi l'ESP32 con MicroPython, il brownout si presenta esattamente allo stesso modo, perché il problema è nell'hardware e non nel software. Gli errori nel codice Python invece compaiono come un Traceback leggibile al posto di un Guru Meditation, e la scheda va in crash di rado. Puoi leggere il motivo del reset con machine.reset_cause(), ma attenzione: la versione di MicroPython per ESP32 non restituisce un valore apposito per il brownout, lo segnala come PWRON_RESET insieme all'accensione. Se la scheda riparte di continuo con PWRON_RESET senza che tu la tocchi, sospetta di nuovo l'alimentazione. Il codice qui sotto è per l'ESP32; sul Raspberry Pi Pico il modulo machine conosce meno tipi di reset. Sul Pico il regolatore buck-boost dell'ingresso VSYS funziona con qualsiasi tensione tra 1,8 e 5,5 V, quindi i problemi di brownout sono molto più rari; per conoscere la scheda, leggi Che cos'è il Raspberry Pi Pico?

MicroPython
1import machine, gc, time
2
3# Reset nedenleri (ESP32 için) / reset causes (for ESP32)
4causes = {
5    machine.PWRON_RESET: "PWRON: guc acilisi ya da brownout / power-on or brownout",
6    machine.HARD_RESET: "HARD: cokme ya da machine.reset() / crash or machine.reset()",
7    machine.WDT_RESET: "WDT: watchdog",
8    machine.DEEPSLEEP_RESET: "DEEPSLEEP: derin uykudan uyanma / deep sleep wake-up",
9    machine.SOFT_RESET: "SOFT: Ctrl+D ile yazilim reseti / soft reset with Ctrl+D",
10}
11print("Reset nedeni / reset cause:", causes.get(machine.reset_cause(), "bilinmiyor / unknown"))
12
13while True:
14    gc.collect()                                     # çöp toplayıcıyı çalıştır / run the garbage collector
15    print("Bos RAM / free RAM:", gc.mem_free(), "bayt / bytes")
16    time.sleep(5)

Errori frequenti e soluzioni

SintomoCausa probabileSoluzione
Brownout detector was triggered all'avvio del Wi-FiCavo, porta o regolatore non reggono il picco di correnteCavo corto e spesso, alimentatore da 1 A, 470 µF + 100 nF tra 3V3 e GND
Reset quando un servo gira o un relè scattaIl carico condivide la linea di alimentazione dell'ESP32Alimenta il carico con una sorgente da 5 V separata e collega i GND
I reset iniziano quando la batteria si scarica un po'Dropout dell'AMS1117Usa un LDO o un convertitore buck-boost
Guru Meditation, EXCVADDR 0x00000000Puntatore nulloControlla il puntatore prima di usarlo
Stack canary watchpoint triggered (loopTask)Lo stack di loop() è pienoRendi static i grandi array o usa SET_LOOP_TASK_STACK_SIZE
task_wdt: - IDLE (CPU 0)Ciclo senza pause sul core 0Aggiungi vTaskDelay al ciclo
Interrupt wdt timeout on CPU1ISR troppo lungaNella ISR alza solo un flag, usa IRAM_ATTR
Scheda muta, boot:0x3 e waiting for downloadGPIO0 LOW all'avvioTogli il circuito su GPIO0 e premi EN
La scheda non si avvia affatto, errore di lettura della flashGPIO12 HIGH all'avvioSposta il pull-up o il modulo da GPIO12 a un altro pin
Failed to connect to ESP32 durante il caricamentoGPIO2 HIGH o la scheda non entra in programmazioneLibera GPIO2 e tieni premuto BOOT all'inizio del caricamento
Rispetta l'ordine durante la diagnosi: prima cambia cavo e alimentatore, poi aggiungi il condensatore, quindi alimenta separatamente servo e LED. Se dopo la scomparsa del messaggio di brownout i reset continuano, guarda il motivo del reset nello sketch di diagnosi e passa alle sezioni software. Se imposti Strumenti > Core Debug Level su Verbose, il core dell'ESP32 stampa messaggi molto più dettagliati sul Wi-Fi e sugli eventi di sistema. Per i problemi di caricamento, dai un'occhiata anche a Lo sketch non si carica su Arduino.

La tua scheda è stabile: e adesso?

  • Dispositivo a batteria: con il deep sleep dell'ESP32 addormenta la scheda tra una misura e l'altra e scendi a pochi microampere.
  • Aggiornamenti senza fili: carica il codice senza cavo USB con l'OTA dell'ESP32.
  • Pannello in tempo reale: segui i dati dei sensori dal vivo nel browser con WebSocket sull'ESP32.
  • Invia notifiche: con un bot Telegram con ESP32 ricevi sul telefono il motivo del reset ogni volta che la scheda si riavvia.
  • Spettacolo di luci: pilota in sicurezza una striscia WS2812B NeoPixel con un'alimentazione separata.

La maggior parte dei problemi di riavvio dell'ESP32 è un problema di alimentazione oppure qualche riga di codice sbagliata; quando leggi bene il messaggio, entrambi si risolvono in fretta. Per ripassare le basi della scheda, dai un'occhiata a Che cos'è l'ESP32? Nell'app BlueGrays trovi progetti con ESP32 con LED, servo, strisce NeoPixel, connessione Wi-Fi, web server, aggiornamenti OTA e deep sleep, ognuno con schema del circuito e codice passo passo, così puoi provare in progetti reali le tecniche di alimentazione e diagnosi che hai imparato qui.

Domande frequenti

Come si risolve ESP32 Brownout detector was triggered?

Questo errore indica che la tensione di alimentazione dell'ESP32 è scesa per un attimo sotto circa 2,43 V. Usa prima un cavo USB corto e spesso con una sorgente da 5 V da almeno 1 A, poi aggiungi un condensatore elettrolitico da 100–470 µF e uno ceramico da 100 nF tra 3V3 e GND. Alimenta carichi come servo, relè e strisce LED con una sorgente separata e collega i GND tra loro.

Perché il mio ESP32 continua a riavviarsi?

Le cause più comuni sono un'alimentazione insufficiente (brownout), crash del software (Guru Meditation), timeout del watchdog e pin di strapping al livello sbagliato durante l'avvio. Apri il Monitor seriale a 115200 baud e premi EN; l'ultimo messaggio prima del reset e il codice rst all'avvio mostrano la causa. La funzione esp_reset_reason() ti permette anche di leggerla dal codice.

Cosa significa Guru Meditation Error LoadProhibited?

Significa che il codice sull'ESP32 ha tentato di leggere da un indirizzo di memoria non valido. Se EXCVADDR è 0 o un numero molto piccolo, quasi sicuramente è stato usato un puntatore nullo. Incolla la riga Backtrace in ESP Exception Decoder per trovare il file e la riga in cui è avvenuto l'errore.

Si può disattivare il rilevatore di brownout dell'ESP32?

Sì, con la riga WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0), ma così si zittisce solo l'avviso. Poiché i cali di tensione continuano, i dati in flash possono corrompersi e la scheda può andare in crash con altri errori. Usalo solo per poco tempo, per confermare che il problema dipende dall'alimentazione.

Come si risolve ESP32 Task watchdog got triggered?

Questo messaggio indica che un task controllato non ha rilasciato la CPU per 5 secondi; con Arduino l'elenco di solito mostra il task IDLE del core 0. Aggiungi vTaskDelay() ai cicli dei tuoi task, usa dei timeout quando aspetti un sensore ed evita delay() o operazioni lunghe nelle callback del web server. Spegnere il watchdog nasconde l'errore ma non ne corregge la causa.

Che alimentatore serve per un ESP32?

Espressif consiglia per l'ESP32 un alimentatore in grado di fornire almeno 500 mA; in pratica un alimentatore da 5 V e 1 A lascia un margine sicuro. Se usi un ESP32-CAM o aggiungi carichi come servo o strisce LED, scegli una sorgente da 2 A o più e, se possibile, alimenta quei carichi da una linea separata.

Vedi tutti i progetti
LED Lampeggiante con ESP32
#103Principiante

LED Lampeggiante con ESP32

Insegna l'uso di base delle uscite GPIO con l'ESP32. Otteniamo un effetto lampeggiante accendendo e spegnendo un LED dal pin digitale. Versione ESP32 del classico progetto blink su Arduino UNO; i comandi di base di blink nell'ambiente Arduino sono gli stessi, ma la disposizione dei pin e i livelli GPIO a 3,3 V dell'ESP32 sono diversi da quelli di Arduino UNO.

4.7(37)
99
Connessione Wi-Fi STA con ESP32 (con display LCD)
#127Avanzato

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.

4.4(21)
34
Servomotore ESP32 (controllo tramite potenziometro)
#118Intermedio
Premium

Servomotore ESP32 (controllo tramite potenziometro)

In questo progetto controlliamo un servomotore SG90 tramite un potenziometro. Regoliamo l'angolo del servomotore mappando il valore analogico letto dal potenziometro su un intervallo compreso tra 0 e 180 gradi. La libreria ESP32Servo genera segnali per servomotori sui GPIO adatti dell'ESP32 che possono funzionare come uscite; in questo progetto si utilizza GPIO 18. Si tratta di un metodo di controllo fondamentale per bracci robotici, gimbal per telecamere e meccanismi di porte automatiche.

4.3(29)
42
Controllo della striscia LED NeoPixel WS2812B con ESP32
#126Intermedio
Premium

Controllo della striscia LED NeoPixel WS2812B con ESP32

I LED indirizzabili WS2812B (NeoPixel) sono LED RGB intelligenti che possono essere controllati in cascata tramite un unico pin dati. In questo progetto controlleremo una striscia WS2812B da 8 LED utilizzando la libreria Adafruit_NeoPixel per creare un'animazione fluida dell'arcobaleno. Sebbene il livello logico a 3,3 V dell'ESP32 funzioni senza problemi con la maggior parte dei componenti WS2812B, in caso di instabilità mostreremo la soluzione con una resistenza in serie da 470 Ω e un condensat

4.9(19)
30
Server web asincrono ESP32 (con indicazione dell'IP sul display LCD)
#129Avanzato

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).

4.8(16)
26
ESP32 Deep Sleep — Risparmio della batteria (OLED + contatore in RTC RAM)
#135Avanzato
Premium

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,

4.3(10)
16
Aggiornamento OTA dell'ESP32 — Installazione wireless del firmware (con display LCD)
#132Avanzato
Premium

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

4.6(14)
22
Sistema di Allarme Movimento ESP32 (PIR + Buzzer + LED + Telegram)
#145Avanzato
Premium

Sistema di Allarme Movimento ESP32 (PIR + Buzzer + LED + Telegram)

Un sistema di allarme di sicurezza intelligente che attiva buzzer e LED quando il sensore PIR rileva movimento, inviando contemporaneamente una notifica istantanea al proprietario tramite Telegram. Dispone di un tempo di attesa di 30 secondi per limitare la frequenza degli allarmi ripetuti; questo meccanismo non verifica la validità dei rilevamenti del sensore PIR né elimina le false attivazioni. Adatto a sicurezza domestica, monitoraggio di garage, magazzini o studi. Con l'ESP32-CAM è possibile

0.0(0)
9