Ratgeber · 20 Min. Lesezeit

ESP32 Brownout Detector was triggered und Guru Meditation lösen

ESP32 Brownout Detector was triggered und ständige Neustarts: Netzteil, Kabel und Kondensator, rst-Codes, Guru Meditation, Task-WDT und Exception Decoder.

Die Meldung ESP32 Brownout Detector was triggered bedeutet, dass die Versorgungsspannung des Boards für einen Moment unter eine sichere Grenze gefallen ist und der Chip sich zum eigenen Schutz neu gestartet hat. Das Problem liegt fast nie im Code, sondern bei der Stromversorgung: ein schwacher USB-Port, ein dünnes und langes Kabel, ein zu kleiner Spannungsregler oder Servos und LED-Streifen, die an derselben Leitung wie der ESP32 hängen. Der zweite große Grund für ständige Neustarts sind Software-Abstürze; dann zeigt der serielle Monitor Zeilen wie Guru Meditation Error, task_wdt oder Stack canary.

Die gute Nachricht: Der ESP32 sagt dir selbst, warum er neu gestartet ist, du musst die Meldungen nur lesen können. In dieser Anleitung lernst du zuerst die rst-Codes in den Bootzeilen und die Fehlermeldungen kennen und behebst den Brownout dann dauerhaft mit Netzteil, Kabel und Kondensator. Danach geht es um Guru-Meditation-Fehler wie LoadProhibited und StoreProhibited, Stack-Überläufe, Nullzeiger und Watchdog-Timeouts, und du verfolgst einen Absturz mit dem ESP Exception Decoder bis zur Codezeile zurück. Zum Schluss schauen wir uns die Strapping-Pins (GPIO0, 2, 12 und 15) an, die den Bootvorgang stören können.

ESP32 DevKit Entwicklungsboard
ESP32-Entwicklungsboard: Die 5 V vom USB werden vom Spannungsregler auf dem Board auf 3,3 V reduziert. Die meisten Brownout-Probleme entstehen durch kurze Einbrüche auf dieser 3,3-V-Leitung.

Warum startet der ESP32 ständig neu? Lies zuerst die Meldung

Bevor du mit der Fehlersuche beginnst, öffne den seriellen Monitor mit 115200 Baud und drücke die EN-Taste auf dem Board. Der ROM-Bootloader im ESP32 gibt bei jedem Start zuerst eine Datumszeile wie "ets Jun 8 2016 00:22:57" aus und danach eine Zeile wie rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT). Der rst-Teil verrät, warum das Board neu gestartet ist, der boot-Teil, in welchem Modus es startet. Hängt das Board in einer Schleife, findest du direkt über diesen Zeilen die Fehlermeldung, die letzten Worte des vorherigen Laufs. Die Tabelle fasst die Meldungen zusammen und zeigt, wo du ansetzen solltest:

Was du im seriellen Monitor siehstBedeutungWo du suchen solltest
Brownout detector was triggeredDie Versorgungsspannung fiel unter die SchwelleNetzteil, Kabel, Kondensator
Guru Meditation Error: Core 1 panic'ed (LoadProhibited)Der Code wollte von einer ungültigen Adresse lesenNullzeiger, Array-Grenzen
Guru Meditation Error: Core 1 panic'ed (StoreProhibited)Der Code wollte an eine ungültige Adresse schreibenNullzeiger, übergelaufener Puffer
Stack canary watchpoint triggered (loopTask)Der Stack einer Task ist vollGroße lokale Arrays, Rekursion
task_wdt: Task watchdog got triggeredEine Task hat die CPU länger als 5 Sekunden nicht freigegebenSchleifen ohne Pausen, hängende Tasks
Interrupt wdt timeout on CPU0 / CPU1Ein Interrupt-Handler oder gesperrte Interrupts dauerten länger als 300 msLange ISR, Serial in der ISR
boot:0x3 (DOWNLOAD_BOOT...) waiting for downloadDas Board ist im Programmiermodus gestartetGPIO0 beim Start LOW
invalid header oder flash read errDer Flash-Speicher konnte nicht gelesen werdenGPIO12 beim Start HIGH, abgebrochener Upload

Was bedeutet "Brownout detector was triggered" und woher kommt es?

Ein Brownout ist ein kurzer Spannungseinbruch ohne kompletten Stromausfall. Im ESP32 steckt ein Brownout-Detektor, der die Versorgung ständig überwacht; im Arduino-Core ist seine Schwelle auf die niedrigste Stufe gesetzt, etwa 2,43 V. Sobald die Spannung darunter fällt, schützt der Chip Funk und Flash-Speicher, schreibt "Brownout detector was triggered" in den seriellen Monitor und startet sich neu. Der Grund ist einfach: Bei zu niedriger Spannung kann der Flash falsch gelesen werden, gespeicherte Daten können beschädigt werden und die CPU kann zufällige Befehle ausführen. Der Detektor sorgt dafür, dass das Board sauber neu startet, statt sich unberechenbar zu verhalten. Das Modul ESP32-WROOM-32 ist für 3,0 bis 3,6 V ausgelegt; bei 2,43 V hat die Spannung den sicheren Bereich also längst verlassen.

Nach einer Brownout-Meldung zeigt die Bootzeile je nach Version des Arduino-Cores rst:0xc (SW_CPU_RESET) oder rst:0x3 (SW_RESET), weil der Interrupt des Detektors zuerst die Meldung ausgibt und den Chip dann per Software neu startet. Lass dich davon nicht täuschen: Derselbe Code vermerkt im Speicher des Chips, dass ein Brownout die Ursache war, und esp_reset_reason() liefert ESP_RST_BROWNOUT. Greift dagegen der eigene Brownout-Reset der Hardware, steht in der Zeile rst:0xf (RTCWDT_BROWN_OUT_RESET). In den 3.x-Cores, die auf ESP-IDF 5 basieren, ist diese Zeile zu einer Info-Logmeldung geworden (I BOD: Brownout detector was triggered). Weil die vorkompilierten Bibliotheken des Arduino-Cores nur Logs der Stufe Error ausgeben, erscheint die Meldung meist gar nicht und das Board startet stillschweigend neu; siehst du beim Booten ein unerklärliches rst:0x3 oder rst:0xc, prüfe den Reset-Grund mit dem Diagnose-Sketch weiter unten. Um zu verstehen, warum die Spannung einbricht, lohnt ein Blick auf den Stromverbrauch des ESP32:

BetriebszustandTypischer Strom (ESP32-Chip)
Deep Sleep (RTC-Timer aktiv)Etwa 10 µA
Light SleepEtwa 0,8 mA
WLAN aus, CPU mit 240 MHz30–68 mA
WLAN empfangen (RX)95–100 mA
WLAN senden, 802.11b, 19,5 dBmEtwa 240 mA
Funkkalibrierung beim Start und VerbindungsaufbauKann in Spitzen von wenigen Mikrosekunden 400 mA übersteigen

Dieser Unterschied ist der Kern des Brownout-Problems: Bis dein Code das WLAN einschaltet, läuft das Board ruhig mit etwa 50 mA, doch in der Zeile WiFi.begin() springt der Strom innerhalb weniger Mikrosekunden auf das Fünf- bis Sechsfache. Kommen Netzteil, Kabel und Regler dieser plötzlichen Anforderung nicht hinterher, bricht die Spannung ein. Deshalb empfiehlt Espressif für den ESP32 ein Netzteil, das mindestens 500 mA liefern kann. Das Symptom kennst du bestimmt: Das Board startet, schreibt ein paar Zeilen in den seriellen Monitor, setzt sich zurück, sobald WLAN oder Bluetooth anlaufen, und das wiederholt sich endlos. Dasselbe kann passieren, wenn sich ein Servo bewegt, ein Relais schaltet oder ein LED-Streifen auf Weiß geht.

Die häufigsten Ursachen für einen Brownout

  • Dünnes oder langes USB-Kabel: Die dünnen Stromadern billiger Kabel kommen hin und zurück auf bis zu 0,5 Ω. Nach dem ohmschen Gesetz kostet eine Spitze von 400 mA in so einem Kabel 0,2 V.
  • Schwacher USB-Port oder Hub: Ports an Tastaturen und Monitoren, passive Hubs und die Frontanschlüsse mancher Laptops lassen die Spannung bei Stromspitzen absacken.
  • Dropout des Spannungsreglers: Der AMS1117 auf den meisten Boards braucht 1,0–1,3 V Differenz zwischen Ein- und Ausgang. Fällt die Spannung am 5V-Pin unter etwa 4,3 V, kann der Ausgang die 3,3 V nicht halten.
  • Akku direkt anschließen: Ein 3,7-V-Li-Ion-Akku am 5V-Pin drückt den Ausgang wegen des Dropouts unter 3 V; zwei AA-Batterien fallen unter Last schnell unter die Mindestspannung des ESP32.
  • Der 3.3V-Pin des Arduino Uno: Aus diesem Pin sollten nur etwa 50 mA entnommen werden; für einen ESP32 mit aktivem WLAN reicht das bei Weitem nicht.
  • Verbraucher an derselben Leitung: Hängen Servos, Relais, Summer, DC-Motoren oder ein WS2812B-Streifen an denselben 5 V wie der ESP32, zieht jede Bewegung die Spannung nach unten.
  • Breadboard und Jumper-Kabel: Wackelige Kontakte und dünne Jumper fügen an jeder Verbindung etwas Widerstand hinzu; die Versorgung über das Breadboard zu führen, verschlimmert das Problem.
  • ESP32-CAM: Laufen Kamera, WLAN und Blitz-LED gleichzeitig, steigt der Strom stark an; dieses Board braucht 5 V und mindestens 2 A. Mehr dazu im Artikel ESP32-CAM.
Wenn das Multimeter 3,3 V anzeigt, heißt das nicht, dass die Versorgung stabil ist. Ein Multimeter misst nur wenige Male pro Sekunde und zeigt etwas Ähnliches wie einen Mittelwert, während die Einbrüche, die einen Brownout auslösen, nur Mikrosekunden bis wenige Millisekunden dauern und im Display nie auftauchen. Sichtbar werden sie nur mit einem Oszilloskop. Hast du keins, arbeite die folgenden Lösungen der Reihe nach ab und prüfe nach jedem Schritt, ob der Fehler verschwunden ist. Die Grundlagen des Messens findest du im Artikel Multimeter richtig benutzen.

Lösung 1: Netzteil und Kabel verbessern

Der erste und wirksamste Schritt ist eine stärkere Versorgung. Schließe das Board mit einem kurzen, dicken Datenkabel, von dem du weißt, dass es gut ist, direkt an einen USB-Port auf der Rückseite deines Computers oder an ein 5-V-Netzteil mit mindestens 1 A an. USB-2.0-Ports sind für 500 mA ausgelegt, USB-3.0-Ports für 900 mA; die von Espressif empfohlenen 500 mA liegen genau an der Grenze eines USB-2.0-Ports, und mit den Kabelverlusten beginnt der Ärger. Behebt schon ein anderes Kabel den Fehler, war sehr wahrscheinlich der Kabelwiderstand schuld. Wie viel Spannung ein Kabel kostet, rechnest du mit V = I × R im Werkzeug Ohmsches Gesetz aus.

AMS1117 3,3-V-Spannungsregler
AMS1117-3.3: der Spannungsregler auf den meisten ESP32-Boards. Er braucht 1,0–1,3 V Differenz zwischen Ein- und Ausgang; fällt der 5V-Pin unter etwa 4,3 V, kann er die 3,3 V am Ausgang nicht halten.
VersorgungBrownout-RisikoHinweis
Kurzes, dickes Kabel und USB-Port auf der RückseiteGeringDie einfachste Lösung beim Entwickeln
Langes, dünnes Kabel, Frontanschluss oder HubHochDer Kabelwiderstand lässt die Spannung bei Stromspitzen einbrechen
5-V-Netzteil mit mindestens 1 A am 5V- oder VIN-PinGeringEmpfohlen für dauerhafte Projekte
Fertige 3,3-V-Quelle direkt am 3V3-PinAbhängig von der QuelleMuss mindestens 500 mA liefern und darf 3,6 V nie überschreiten
3,7-V-Li-Ion-Akku über den AMS1117HochFällt der Akku unter etwa 4 V, sinkt der Ausgang unter 3 V
Li-Ion-Akku mit Low-Dropout-Regler (LDO) für 3,3 V oder Buck-BoostGeringLiefert auch bei sinkender Akkuspannung stabile 3,3 V
Zwei AA-Batterien direkt am 3V3-PinSehr hochUnter Last fällt die Spannung schnell unter die Mindestspannung des ESP32

Bei Akkuprojekten musst du besonders aufpassen. Eine Li-Ion-Zelle wie die 18650 liefert voll geladen 4,2 V und leer etwa 3,0 V. Dieser Bereich passt weder direkt an den 3V3-Pin (4,2 V überschreiten die Grenze von 3,6 V) noch an den 5V-Pin mit seinem AMS1117. Richtig ist entweder, den Akku über ein 5-V-Step-up-Modul (Boost) an den 5V-Pin zu geben, oder die 3V3-Leitung direkt über einen Low-Dropout-Regler mit mindestens 500 mA (zum Beispiel ME6211 oder HT7833) und einen Kondensator zu versorgen. Wie lange dein Projekt mit einem Akku durchhält, berechnest du mit dem Werkzeug Akkulaufzeit; die Ladeschaltung erklärt der Artikel TP4056-Lademodul.

Lösung 2: Kondensator zwischen 3V3 und GND

Ein Kondensator wirkt wie ein kleiner Speicher, der bei einer Stromspitze selbst Energie liefert, bis Regler und Kabel nachkommen. Setze zwischen die Pins 3V3 und GND, möglichst nah am Board, einen Elektrolytkondensator mit 100–470 µF und daneben einen Keramikkondensator mit 100 nF. Der Elko fängt Einbrüche im Millisekundenbereich ab, der Keramikkondensator sehr kurze, hochfrequente Schwankungen. Die Wirkung siehst du grob mit ΔV = I × Δt / C: Selbst wenn ein 470-µF-Kondensator allein 200 µs lang zusätzliche 200 mA liefert, sinkt die Spannung nur um 0,085 V. Die Aufschrift 104 auf einem Keramikkondensator bedeutet 100 nF; andere Codes entschlüsselst du mit dem Werkzeug Kondensator-Code.

Verschiedene Kondensatoren
Bei Elektrolytkondensatoren ist das lange Bein der Pluspol (+) und kommt an 3V3; das Bein auf der Seite mit dem Streifen kommt an GND. Für die 3,3-V-Leitung reicht ein Typ mit 6,3 V oder 10 V Spannungsfestigkeit.
Setze einen Elko niemals verpolt ein: Er wird heiß, bläht sich auf und kann platzen. Schließt du den Kondensator an die 5V-Leitung an, wähle einen mit mindestens 10 V Spannungsfestigkeit. Sehr große Kondensatoren (ab 1000 µF) ziehen beim Einschalten einen hohen Ladestrom, der den USB-Port kurz belasten und den Anstieg der 3,3-V-Leitung verlangsamen kann; 470 µF an 3V3 reichen für die meisten Projekte. Wie Kondensatoren funktionieren, erfährst du in Was ist ein Kondensator?

Lösung 3: Servos, Motoren und LED-Streifen getrennt versorgen

Auch wenn der ESP32 selbst richtig versorgt ist, können Verbraucher an derselben Leitung die Spannung nach unten ziehen. Schon ein kleiner Servo wie der SG90 zieht beim Anlaufen einige hundert mA; eine WS2812B-LED verbraucht bei vollem Weiß etwa 60 mA, ein Streifen mit 30 LEDs kommt also auf bis zu 1,8 A. Versorge diese Verbraucher nicht über den 5V- oder 3V3-Pin des ESP32, sondern aus einer eigenen 5-V-Quelle; zum Beispiel kannst du ein 12-V-Netzteil mit einem LM2596-Step-down-Modul auf 5 V bringen. Die wichtigste Regel: Verbinde die GND-Anschlüsse beider Quellen miteinander; ohne gemeinsame Masse hat die Signalleitung keinen Bezug, und Servo oder Streifen verhalten sich zufällig. Ausführlich behandeln wir das in Arduino startet ständig neu? und GND und gemeinsame Masse.

LM2596 Step-down-Modul (Buck)
LM2596-Step-down-Modul: setzt 12 V effizient auf 5 V herunter und eignet sich ideal, um Verbraucher wie Servos, Relais oder LED-Streifen getrennt vom ESP32 zu versorgen. Der Ausgang wird mit einem Trimmer eingestellt; stelle ihn vor dem Anschließen mit dem Multimeter auf 5 V ein.
Auch per Software kannst du Stromspitzen abmildern. Starte das WLAN, bevor du Servos bewegst oder den LED-Streifen einschaltest; begrenze die Helligkeit des Streifens mit setBrightness(); schalte Servos und Relais nicht gleichzeitig, sondern im Abstand von einigen hundert Millisekunden. Auch eine geringere WLAN-Sendeleistung mit WiFi.setTxPower() senkt den Spitzenstrom; Details im Artikel ESP32 verbindet sich nicht mit dem WLAN.

Ist das Abschalten des Brownout-Detektors eine Lösung?

Die im Netz am häufigsten empfohlene "Lösung" ist, den Detektor mit einer einzigen Zeile abzuschalten. Der folgende Code deaktiviert den Detektor, indem er das Brownout-Register des ESP32 auf null setzt, und die Fehlermeldung verschwindet. Die Spannungseinbrüche bleiben aber; es warnt dich nur niemand mehr. Nutze diesen Code nur zur Diagnose: Läuft das Board mit abgeschaltetem Detektor problemlos, hast du bestätigt, dass das Problem eindeutig an der Versorgung liegt. Danach löschst du die Zeile wieder und reparierst die Versorgung.

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}
Lass den Detektor nicht dauerhaft abgeschaltet. WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0) schaltet nicht nur die Warnung stumm, sondern auch den Hardware-Reset des Detektors und seine Aufgabe, Flash und Funk bei Unterspannung abzuschalten; der Chip läuft dann ungeschützt weit unter seinem Minimum von 3,0 V weiter. Fällt die Spannung unter 2,4 V, können Daten im Flash (Preferences, EEPROM, LittleFS) und bei einem OTA-Update sogar das Programm selbst beschädigt werden, das WLAN kann ohne erkennbaren Grund abbrechen, und das Board stürzt dann mit Guru-Meditation-Fehlern ab oder friert ganz ein. Die Einstellung ist nicht dauerhaft: Der Chip aktiviert den Detektor bei jedem Start wieder, deshalb muss die Zeile die erste in setup() sein, und sobald du sie löschst, ist der Schutz zurück. Dieses Register gibt es beim klassischen ESP32 sowie bei S2, S3 und C3; neuere Modelle wie der ESP32-C6 haben es nicht, dort lässt sich der Code nicht kompilieren. Die echte Lösung ist immer eine bessere Stromversorgung.

rst-Codes: Der ESP32 verrät, warum er neu gestartet ist

Der rst:-Wert, den das ROM bei jedem Start ausgibt, zeigt, wie der vorherige Lauf geendet hat. Bei einem normalen Start ist der boot-Wert 0x13 (SPI_FAST_FLASH_BOOT), das Board startet sein Programm also aus dem Flash. Die Tabelle fasst die häufigsten Codes zusammen. ROM-Codes allein reichen nicht immer: ESP.restart() und ein Neustart nach einer Guru Meditation erscheinen beide als 0xc, ein Brownout je nach Core-Version als 0xc oder 0x3. Um sie zu unterscheiden, nutze den Sketch mit esp_reset_reason() im nächsten Abschnitt.

rst-CodeNameBedeutung
0x1POWERON_RESETErstmals Strom angelegt oder EN-Taste gedrückt
0x3SW_RESETDie Software hat das gesamte digitale System zurückgesetzt; neuere Core-Versionen zeigen das auch nach einem Brownout
0x5DEEPSLEEP_RESETDas Board ist aus dem Deep Sleep aufgewacht (normal)
0x7 / 0x8TG0WDT_SYS_RESET / TG1WDT_SYS_RESETEin Timer-Group-Watchdog hat das System per Hardware zurückgesetzt; Interrupts waren zu lange gesperrt oder selbst der Panic-Handler konnte nicht laufen
0x9RTCWDT_SYS_RESETDer RTC-Watchdog hat den Digitalkern zurückgesetzt
0xcSW_CPU_RESETNeustart per Software: ESP.restart(), nach einer Guru Meditation oder nach einem Brownout im Arduino-Core
0xfRTCWDT_BROWN_OUT_RESETBrownout-Reset der Hardware: instabile Versorgungsspannung
0x10RTCWDT_RTC_RESETDer RTC-Watchdog hat den ganzen Chip samt RTC zurückgesetzt; meist bei Boards, die beim Start hängen

Diagnose-Sketch: Reset-Grund, Speicher und Stack ausgeben

Lade den folgenden Code als eigenen Sketch hoch oder übernimm seine Zeilen in setup() und loop() deines Problemprojekts. Bei jedem Start schreibt das Board den Reset-Grund als lesbaren Text, die Anzahl der Starts und den Speicherzustand in den seriellen Monitor. Der mit RTC_DATA_ATTR markierte Zähler liegt im RTC-Speicher und übersteht daher Software-Resets und Deep Sleep; er wird erst gelöscht, wenn der Strom komplett weg ist. Steigt der Zähler alle paar Sekunden, weißt du sofort, dass das Board in einer Reset-Schleife steckt.

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}

Die Werte, die der Code in der Schleife ausgibt, decken auch stille Probleme auf. Sinkt der freie Heap bei jedem Durchlauf ein wenig, hat dein Programm ein Speicherleck, und das Board wird früher oder später abstürzen. Ist der größte Block viel kleiner als der freie Heap, ist der Speicher fragmentiert; das kommt meist von String-Objekten, die in der Schleife ständig wachsen und schrumpfen. Fällt der freie Stack von loopTask unter ein paar hundert Bytes, steht ein Stack-Überlauf vor der Tür. Lautet der Reset-Grund BROWNOUT, konzentriere dich auf die Abschnitte zur Versorgung; bei PANIC, TASK_WDT oder INT_WDT auf die Software-Abschnitte weiter unten.

Was ist ein Guru Meditation Error? Die Absturzmeldung Zeile für Zeile lesen

Ein Guru Meditation Error ist der Absturzbericht, den der Panic-Handler ausgibt, wenn die CPU des ESP32 auf einen Fehler stößt, von dem sie sich nicht erholen kann; der Name stammt vom Fehlerbildschirm alter Amiga-Computer. Der Bericht sieht zuerst bedrohlich aus, aber nur wenige Zeilen sind wichtig. Core 1 sagt dir, auf welchem Kern der Fehler auftrat: Bei Arduino laufen setup() und loop() auf Kern 1, der WLAN-Stack auf Kern 0. Der Name in Klammern ist die Art der Ausnahme. Am Ende des Berichts schreibt das Board "Rebooting..." und startet neu; in der Bootzeile siehst du rst:0xc.

ZeileBedeutung
Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.Code auf Kern 1 wollte von einer ungültigen Adresse lesen, und der Fehler wurde nicht abgefangen
PC : 0x400d1a2cAdresse des Befehls, bei dem es abstürzte; beginnt sie mit 0x400d, lief dein Code oder eine Bibliothek aus dem Flash
EXCCAUSE: 0x0000001cAusnahmecode; 0x1c, also 28, bedeutet LoadProhibited
EXCVADDR: 0x00000000Die angesprochene Adresse; 0 oder eine sehr kleine Zahl deutet auf einen Nullzeiger hin
Backtrace: 0x400d1a29:0x3ffb2270 0x400d0f6e:0x3ffb2290 ...Aufrufkette; jedes Paar hat die Form PC:SP und wird mit dem Decoder in eine Codezeile übersetzt
ELF file SHA256: ...Fingerabdruck des abgestürzten Programms; der Decoder braucht genau denselben Build
Rebooting...Der Panic-Handler startet den Chip per Software neu

LoadProhibited, StoreProhibited und andere Ausnahmetypen

AusnahmeEXCCAUSEWas ist passiert?Häufige Ursache
LoadProhibited28 (0x1c)Lesen von einer ungültigen AdresseNullzeiger oder nicht initialisierter Zeiger, gelöschtes Objekt
StoreProhibited29 (0x1d)Schreiben an eine ungültige AdresseSchreiben über einen Nullzeiger, Puffer über die Array-Grenze hinaus
InstrFetchProhibited20 (0x14)Befehl von ungültiger Adresse geholtNicht zugewiesener Funktionszeiger oder Callback
IllegalInstruction0 (0x0)Ungültiger BefehlBeschädigter Stack, fehlendes return in einer Funktion mit Rückgabewert
LoadStoreAlignment9 (0x9)Nicht ausgerichteter SpeicherzugriffByte-Array in einen Typ wie uint32_t* umgewandelt
IntegerDivideByZero6 (0x6)Ganzzahl durch null geteiltDivision durch einen Zähler, der null sein kann
Unhandled debug exception-Debug-AusnahmeStack canary watchpoint triggered: Stack-Überlauf
Interrupt wdt timeout on CPU0/CPU1-Interrupt-Watchdog abgelaufenLange ISR, Serial oder delay in der ISR
Cache disabled but cached memory region accessed-Zugriff auf Code im Flash, während der Flash belegt warInterrupt-Handler ohne IRAM_ATTR

Der häufigste dieser Fehler ist ein Nullzeiger. NULL ist die Adresse 0, und beim ESP32 gibt es rund um Adresse 0 keinen lesbaren Speicher; Lesen an der Stelle, auf die ein leerer Zeiger zeigt, ergibt deshalb LoadProhibited, Schreiben StoreProhibited. EXCVADDR ist dabei ein perfekter Hinweis: 0x00000000 steht für den Zeiger selbst, kleine Werte wie 0x00000004 oder 0x00000010 für ein Feld innerhalb eines leeren Zeigers (NULL plus Offset des Feldes). In Arduino-Projekten ist die häufigste Ursache eine Funktion, die NULL für "nicht gefunden" zurückgibt, und dieser Wert wird ohne Prüfung benutzt. Im folgenden Beispiel liefert strstr() NULL, wenn der gesuchte Text fehlt; ohne Prüfung stürzt das Board mit EXCVADDR 0x00000005 ab.

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}
Gewöhne dir ein paar Dinge gegen Nullzeiger an: Initialisiere Zeiger bei der Deklaration mit nullptr, prüfe den Rückgabewert der begin()-Funktionen von Bibliotheken, setze einen Zeiger nach delete auf nullptr und stelle beim Schreiben in Arrays sicher, dass der Index kleiner als die Array-Größe ist. Stellst du in der Arduino IDE unter Datei > Einstellungen die Compiler-Warnungen auf Alle, siehst du ein fehlendes return und ähnliche Fehler schon beim Kompilieren.

Stack-Überlauf: der Fehler "Stack canary watchpoint triggered"

Beim ESP32 hat jede Task einen Stack fester Größe, in dem lokale Variablen, Funktionsaufrufe und Rücksprungadressen liegen. Bei Arduino hat die loopTask, die setup() und loop() ausführt, einen Stack von 8192 Bytes. Ein lokales Array mit 10.000 Bytes in loop(), eine Funktion, die sich selbst aufruft (Rekursion), oder eine Bibliotheksfunktion mit vielen lokalen Variablen sprengt diese Grenze. Am Ende des Stacks liegt ein Wächterbereich (Canary); erreicht der Stack ihn, schreibt das Board Guru Meditation Error: Core 1 panic'ed (Unhandled debug exception) und direkt darunter Debug exception reason: Stack canary watchpoint triggered (loopTask). Der Name in Klammern ist die Task, deren Stack übergelaufen ist. Manchmal zeigt sich dasselbe Problem auch als ***ERROR*** A stack overflow in task loopTask has been detected. So behebst du es:

  • Große Arrays vom Stack holen: Deklariere das Array global oder schreibe static davor; dann liegt es im festen RAM statt auf dem Stack.
  • Den Stack von loopTask vergrößern: Mit SET_LOOP_TASK_STACK_SIZE(16 * 1024); ganz oben im Sketch vergrößerst du den Stack von loop() auf 16 KB.
  • Eigenen Tasks genug Platz geben: Beim ESP32 wird die Stackgröße für xTaskCreate und xTaskCreatePinnedToCore in Bytes angegeben, nicht in Words wie bei FreeRTOS auf anderen Plattformen. 1024 Bytes sind selbst für eine Task mit Serial.printf zu wenig; fang mit 4096 an.
  • Messen: uxTaskGetStackHighWaterMark(NULL) liefert in Bytes den kleinsten Teil des Stacks, den die Task bisher nie benutzt hat; fällt der Wert unter ein paar hundert Bytes, vergrößere den Stack.
  • Rekursion vermeiden: Wandle Funktionen, die sich selbst aufrufen, in Schleifen um oder begrenze ihre Tiefe.

Task-Watchdog: der Fehler "task_wdt: Task watchdog got triggered"

Ein Watchdog ist ein Timer, der ein hängendes Programm bemerkt und das Board rettet. Der Task-Watchdog (Task WDT) des ESP32 erwartet, dass die bei ihm angemeldeten Tasks in regelmäßigen Abständen "ich lebe noch" melden. Im Arduino-Core überwacht er standardmäßig die Leerlauf-Task (IDLE) von Kern 0, mit einer Zeit von 5 Sekunden. Gibt eine Task auf Kern 0 die CPU 5 Sekunden lang nicht frei, kann die IDLE-Task nicht laufen, und im seriellen Monitor erscheint eine Meldung, die mit E (10257) task_wdt: Task watchdog got triggered. beginnt. Danach folgen die Liste der Tasks, die den Watchdog nicht rechtzeitig zurückgesetzt haben (meist - IDLE (CPU 0)), und unter Tasks currently running: die gerade laufenden Tasks. Im Arduino-Core löst das mit der Zeile task_wdt: Aborting. eine Panic aus, und das Board startet neu.

Die häufigsten Ursachen sind: eine mit xTaskCreatePinnedToCore auf Kern 0 gelegte Schleife ohne ein einziges vTaskDelay(), eine while-Schleife, die ohne Timeout auf die Antwort eines Sensors wartet, oder delay() und lange Operationen in den Callbacks von Bibliotheken wie AsyncWebServer. Im letzten Fall siehst du in der Liste statt IDLE die Task async_tcp. Die Lösung: lange Aufgaben in kleine Stücke aufteilen und in Schleifen kurze Pausen wie vTaskDelay(1) einbauen. loop() selbst wird standardmäßig nicht überwacht; wenn du willst, rufst du in setup() enableLoopWDT() auf, damit das Board auch neu startet, wenn loop() länger als 5 Sekunden hängt. Den Watchdog mit disableCore0WDT() abzuschalten, versteckt den Fehler, repariert aber den hängenden Code nicht. Mehr über Tasks und Kerne findest du in ESP32 FreeRTOS und Dual-Core. Der folgende Code zeigt eine saubere Task-Struktur und die Vorkehrungen gegen einen Stack-Überlauf:

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 und IRAM_ATTR: Abstürze in Interrupts

Der Interrupt-Watchdog (Interrupt WDT) ist viel ungeduldiger: Braucht ein Interrupt-Handler (ISR) oder ein Codeabschnitt mit gesperrten Interrupts länger als 300 ms, stürzt das Board mit Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1) ab. Serial.print, delay(), I2C oder WLAN-Funktionen in einer ISR sind die häufigste Ursache. Eine weitere Falle ist der Flash: Während Preferences, EEPROM oder LittleFS in den Flash schreiben, ist der Flash-Cache für einen Moment abgeschaltet. Kommt in dieser Zeit ein Interrupt und liegt sein Handler im Flash, meldet das Board Cache disabled but cached memory region accessed. Die Lösung: ISRs mit IRAM_ATTR markieren, damit sie im RAM liegen, und darin nur ein Flag setzen; die eigentliche Arbeit erledigt loop(). Variablen, die ISR und loop() teilen, müssen volatile sein.

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}

Backtrace mit dem ESP Exception Decoder in eine Codezeile übersetzen

Die Adressen in der Backtrace-Zeile sagen allein nichts; das Werkzeug, das sie in Datei, Funktion und Zeilennummer deines Quellcodes übersetzt, heißt ESP Exception Decoder. In der alten Arduino IDE 1.8 war es ein Plugin im Menü Werkzeuge. In der Arduino IDE 2 nutzt du eine gleichnamige Erweiterung aus der Community:

  1. Lade die Datei mit der Endung .vsix aus dem Bereich Releases des Projekts dankeboy36/esp-exception-decoder auf GitHub herunter. Wähle für die Arduino IDE 2 eine 1.x-Version; die neueren 2.x-Versionen sind für VS Code gedacht.
  2. Schließe die Arduino IDE und kopiere die Datei unter Windows nach %UserProfile%\.arduinoIDE\plugins, unter macOS und Linux nach ~/.arduinoIDE/plugins; lege den Ordner an, falls er fehlt.
  3. Öffne die IDE und den abstürzenden Sketch, kompiliere ihn mit Überprüfen und lade ihn auf das Board.
  4. Öffne den seriellen Monitor und warte, bis der Absturz erneut auftritt.
  5. Öffne mit Strg+Umschalt+P (unter macOS Cmd+Shift+P) die Befehlspalette und führe ESP Exception Decoder: Show Decoder Terminal aus.
  6. Kopiere den Guru-Meditation-Block samt Backtrace-Zeile aus dem seriellen Monitor und füge ihn in das geöffnete Terminal ein; das Werkzeug zeigt zu jeder Adresse Dateiname, Funktion und Zeilennummer.

Kannst du die Erweiterung nicht installieren, geht es auch von Hand. Das Menü Sketch > Export Compiled Binary legt im build-Ordner innerhalb deines Sketch-Ordners eine Datei mit der Endung .elf ab. Der Befehl xtensa-esp32-elf-addr2line -pfiaC -e sketch.ino.elf 0x400d1a29 0x400d0f6e aus der ESP32-Toolchain übersetzt diese Adressen in Funktionsnamen und Zeilennummern. Mit PlatformIO genügt die Zeile monitor_filters = esp32_exception_decoder in der platformio.ini; die Absturzmeldung wird dann im seriellen Monitor automatisch entschlüsselt.

Der Decoder liefert nur mit der .elf-Datei genau desselben Builds, der abgestürzt ist, richtige Ergebnisse. Änderst du eine einzige Zeile und kompilierst neu, verschieben sich die Adressen, und die Ausgabe zeigt falsche Zeilen. Endet die Backtrace-Zeile mit CORRUPTED, ist der Stack beschädigt; das deutet meist auf einen Stack-Überlauf oder einen über seine Grenzen geschriebenen Puffer hin.

Strapping-Pins: Wie GPIO0, GPIO2, GPIO12 und GPIO15 den Start stören

Beim Start liest der ESP32 den Pegel bestimmter Pins, um zu entscheiden, wie er bootet. Diese Pins heißen Strapping-Pins, und nur ihr Pegel im Moment des Resets zählt; nach dem Start kannst du sie wie normale GPIOs nutzen. Das Problem entsteht, wenn ein angeschlossener Sensor, Taster oder ein Modul den Pin beim Start auf den falschen Pegel zieht. Dann startet das Board sein Programm gar nicht, geht in den Programmiermodus oder kann den Flash nicht lesen; von außen sieht auch das aus wie "der ESP32 startet nicht" oder "er setzt sich ständig zurück". Die vollständige Pinbelegung deines Boards findest du im Werkzeug Pinout.

PinInterner WiderstandAufgabe beim StartWas passiert beim falschen Pegel?
GPIO0Pull-upLOW wählt den Programmiermodus (Download), HIGH den normalen Startboot:0x3 (DOWNLOAD_BOOT) und waiting for download; das Programm läuft nicht
GPIO2Pull-downMuss für den Programmiermodus LOW oder offen sein; beim normalen Start egalEine Schaltung, die ihn auf HIGH zieht, verhindert den Upload
GPIO12 (MTDI)Pull-downWählt die Versorgungsspannung des Flash: LOW 3,3 V, HIGH 1,8 VBei HIGH wird ein 3,3-V-Flash nicht richtig versorgt; das Board startet nicht oder hängt in einer Reset-Schleife
GPIO15 (MTDO)Pull-upLOW unterdrückt die Bootmeldungen des ROMIm seriellen Monitor fehlen die Bootzeilen, die Diagnose wird schwerer
GPIO5Pull-upLegt das SDIO-Timing festMacht auf Entwicklungsboards selten Probleme
Ein Pull-up-Widerstand, ein Relais- oder Sensormodul an GPIO12, das den Pin beim Start auf HIGH zieht, ist der am besten versteckte Grund, warum ein ESP32 überhaupt nicht startet. Musst du diesen Pin verwenden, stelle sicher, dass das Modul ihn beim Start auf LOW lässt. Alternativ schreibt der Befehl espefuse.py set_flash_voltage 3.3V aus esptool die Flash-Spannung dauerhaft in eine eFuse und hebt den Einfluss von GPIO12 beim Start auf; das lässt sich jedoch nicht rückgängig machen und sollte nur bei Modulen mit 3,3-V-Flash (etwa dem ESP32-WROOM-32) erfolgen.

Neuere Boards haben andere Strapping-Pins: Beim ESP32-S3 beeinflussen GPIO0, GPIO3, GPIO45 und GPIO46 den Start, beim ESP32-C3 GPIO2, GPIO8 und GPIO9. Der ESP32-S3 verwendet dieselben Xtensa-Ausnahmenamen wie der klassische ESP32. Beim ESP32-C3 mit RISC-V-Kern siehst du dagegen Load access fault statt LoadProhibited und Store access fault statt StoreProhibited, und das Register MTVAL übernimmt die Rolle von EXCVADDR. Die Brownout-Meldung ist bei allen Modellen gleich.

ESP32 und Raspberry Pi Pico mit MicroPython

Programmierst du den ESP32 mit MicroPython, tritt der Brownout genauso auf, denn das Problem steckt in der Hardware, nicht in der Software. Fehler im Python-Code erscheinen dagegen als lesbarer Traceback statt als Guru Meditation, und das Board stürzt nur selten ab. Den Reset-Grund liest du mit machine.reset_cause(), aber Vorsicht: Die ESP32-Version von MicroPython liefert für einen Brownout keinen eigenen Wert, sondern meldet ihn zusammen mit dem Einschalten als PWRON_RESET. Startet das Board ständig mit PWRON_RESET, obwohl du es nicht angefasst hast, verdächtige wieder die Versorgung. Der folgende Code ist für den ESP32; beim Raspberry Pi Pico kennt das machine-Modul weniger Reset-Arten. Beim Pico arbeitet der Buck-Boost-Regler am VSYS-Eingang mit allem zwischen 1,8 und 5,5 V, daher sind Brownout-Probleme viel seltener; mehr zum Board in Was ist der 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)

Häufige Fehler und Lösungen

SymptomMögliche UrsacheLösung
Brownout detector was triggered beim WLAN-StartKabel, Port oder Regler kommen dem Spitzenstrom nicht hinterherKurzes dickes Kabel, 1-A-Netzteil, 470 µF + 100 nF zwischen 3V3 und GND
Reset, wenn sich ein Servo dreht oder ein Relais schaltetDer Verbraucher hängt an der Leitung des ESP32Verbraucher aus eigener 5-V-Quelle versorgen, GNDs verbinden
Resets beginnen, wenn der Akku etwas leerer istDropout des AMS1117LDO oder Buck-Boost-Wandler verwenden
Guru Meditation, EXCVADDR 0x00000000NullzeigerZeiger vor der Benutzung prüfen
Stack canary watchpoint triggered (loopTask)Der Stack von loop() ist vollGroße Arrays static machen oder SET_LOOP_TASK_STACK_SIZE nutzen
task_wdt: - IDLE (CPU 0)Schleife ohne Pausen auf Kern 0vTaskDelay in die Schleife einbauen
Interrupt wdt timeout on CPU1ISR dauert zu langeIn der ISR nur ein Flag setzen, IRAM_ATTR verwenden
Board stumm, boot:0x3 und waiting for downloadGPIO0 beim Start LOWSchaltung an GPIO0 entfernen, EN drücken
Board startet gar nicht, Fehler beim Lesen des FlashGPIO12 beim Start HIGHPull-up oder Modul an GPIO12 auf einen anderen Pin verlegen
Failed to connect to ESP32 beim HochladenGPIO2 HIGH oder das Board kommt nicht in den ProgrammiermodusGPIO2 freimachen, beim Start des Uploads BOOT gedrückt halten
Halte bei der Fehlersuche die Reihenfolge ein: zuerst Kabel und Netzteil tauschen, dann den Kondensator einbauen, danach Servos und LEDs getrennt versorgen. Gibt es nach dem Verschwinden der Brownout-Meldung immer noch Resets, sieh dir den Reset-Grund im Diagnose-Sketch an und wechsle zu den Software-Abschnitten. Stellst du Werkzeuge > Core Debug Level auf Verbose, gibt der ESP32-Core viel ausführlichere Meldungen zu WLAN- und Systemereignissen aus. Bei Upload-Problemen hilft dir auch der Artikel Arduino-Sketch lässt sich nicht hochladen.

Dein Board läuft stabil: Wie geht es weiter?

  • Akkufreundliches Gerät: Lege das Board mit ESP32 Deep Sleep zwischen den Messungen schlafen und senke den Strom in den Mikroampere-Bereich.
  • Drahtlose Updates: Lade Code mit ESP32 OTA ohne USB-Kabel hoch.
  • Echtzeit-Dashboard: Verfolge Sensordaten mit ESP32 WebSocket live im Browser.
  • Benachrichtigungen senden: Mit einem ESP32-Telegram-Bot bekommst du bei jedem Neustart des Boards den Reset-Grund aufs Handy.
  • Lichtshow: Steuere einen WS2812B-NeoPixel-Streifen sicher mit getrennter Versorgung.

Die meisten Neustart-Probleme des ESP32 sind entweder ein Versorgungsproblem oder ein paar Zeilen fehlerhafter Code; liest du die Meldung richtig, sind beide schnell gelöst. Um die Grundlagen des Boards aufzufrischen, wirf einen Blick auf Was ist der ESP32? In der BlueGrays-App findest du ESP32-Projekte mit LEDs, Servos, NeoPixel-Streifen, WLAN-Verbindung, Webserver, OTA-Updates und Deep Sleep, jeweils mit Schritt-für-Schritt-Schaltplan und Code, sodass du die hier gelernten Versorgungs- und Diagnosetechniken in echten Projekten ausprobieren kannst.

Häufige Fragen

Wie behebe ich ESP32 Brownout Detector was triggered?

Dieser Fehler bedeutet, dass die Versorgungsspannung des ESP32 kurz unter etwa 2,43 V gefallen ist. Nutze zuerst ein kurzes, dickes USB-Kabel mit einer 5-V-Quelle, die mindestens 1 A liefert, und setze dann einen 100–470-µF-Elko und einen 100-nF-Keramikkondensator zwischen 3V3 und GND. Versorge Verbraucher wie Servos, Relais und LED-Streifen aus einer eigenen Quelle und verbinde die GNDs.

Warum startet mein ESP32 ständig neu?

Die häufigsten Ursachen sind eine zu schwache Versorgung (Brownout), Software-Abstürze (Guru Meditation), Watchdog-Timeouts und Strapping-Pins, die beim Start auf dem falschen Pegel liegen. Öffne den seriellen Monitor mit 115200 Baud und drücke EN; die letzte Meldung vor dem Reset und der rst-Code beim Start zeigen die Ursache. Mit esp_reset_reason() kannst du sie auch im Code auslesen.

Was bedeutet Guru Meditation Error LoadProhibited?

Es bedeutet, dass Code auf dem ESP32 von einer ungültigen Speicheradresse lesen wollte. Ist EXCVADDR 0 oder eine sehr kleine Zahl, wurde fast sicher ein Nullzeiger benutzt. Füge die Backtrace-Zeile in den ESP Exception Decoder ein, um Datei und Zeile des Fehlers zu finden.

Kann man den Brownout-Detektor des ESP32 abschalten?

Ja, mit der Zeile WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0), aber damit verstummt nur die Warnung. Da die Spannungseinbrüche bleiben, können Daten im Flash beschädigt werden und das Board kann mit anderen Fehlern abstürzen. Nutze das nur kurz, um zu bestätigen, dass das Problem an der Versorgung liegt.

Wie behebe ich ESP32 Task watchdog got triggered?

Die Meldung bedeutet, dass eine überwachte Task die CPU 5 Sekunden lang nicht freigegeben hat; bei Arduino steht in der Liste meist die IDLE-Task von Kern 0. Baue vTaskDelay() in die Schleifen deiner eigenen Tasks ein, nutze Timeouts beim Warten auf Sensoren und vermeide delay() oder lange Operationen in Webserver-Callbacks. Den Watchdog abzuschalten, versteckt den Fehler, behebt aber nicht die Ursache.

Welches Netzteil braucht ein ESP32?

Espressif empfiehlt für den ESP32 ein Netzteil, das mindestens 500 mA liefern kann; in der Praxis lässt ein 5-V-Netzteil mit 1 A eine sichere Reserve. Nutzt du einen ESP32-CAM oder hängst Verbraucher wie Servos oder LED-Streifen an, wähle eine Quelle mit 2 A oder mehr und versorge diese Verbraucher möglichst über eine eigene Leitung.

Alle Projekte ansehen
LED Blinken mit ESP32
#103Anfänger

LED Blinken mit ESP32

Lehrt die grundlegende Verwendung von GPIO-Ausgängen mit ESP32. Wir erreichen einen Blinkeffekt, indem wir eine LED über einen digitalen Pin ein- und ausschalten. ESP32-Version des klassischen Blink-Projekts auf Arduino UNO; die grundlegenden Blink-Befehle in der Arduino-Umgebung bleiben gleich, aber die Pinbelegung und die GPIO-Pegel von 3,3 V des ESP32 unterscheiden sich von denen des Arduino UNO.

4.7(37)
99
ESP32-WLAN-STA-Verbindung (mit LCD-Display)
#127Fortgeschritten

ESP32-WLAN-STA-Verbindung (mit LCD-Display)

In diesem Projekt verbinden wir den ESP32 im Station-Modus (STA) sicher und fehlertolerant mit dem heimischen WLAN. Wir lagern SSID und Passwort in eine separate secrets.h-Datei aus, um Leaks zu Git zu verhindern, richten einen Auto-Reconnect-Mechanismus ein und zeigen RSSI-Signalpegel und IP-Adresse auf einem I2C-LCD-Display an. Die interne LED dient als Statusanzeige. Ein Verbindungsmanager auf Produktionsniveau.

4.4(21)
34
ESP32-Servomotor (Steuerung über Potentiometer)
#118Mittel
Premium

ESP32-Servomotor (Steuerung über Potentiometer)

In diesem Projekt steuern wir einen SG90-Servomotor mit einem Potentiometer. Wir stellen den Servowinkel ein, indem wir den vom Potentiometer gelesenen Analogwert auf den Bereich von 0 bis 180 Grad abbilden. Die ESP32Servo-Bibliothek erzeugt Servosignale an geeigneten GPIO-Pins des ESP32, die als Ausgang verwendet werden können; in diesem Projekt wird GPIO 18 verwendet. Dies ist eine grundlegende Steuerungsmethode für Roboterarme, Kamera-Gimbals und automatische Türmechanismen.

4.3(29)
42
Steuerung des ESP32 WS2812B NeoPixel-Streifens
#126Mittel
Premium

Steuerung des ESP32 WS2812B NeoPixel-Streifens

WS2812B (NeoPixel) adressierbare LEDs sind intelligente RGB-LEDs, die über einen einzigen Datenpin in Reihe geschaltet gesteuert werden können. In diesem Projekt werden wir einen WS2812B-Streifen mit 8 LEDs mithilfe der Adafruit_NeoPixel-Bibliothek steuern und eine fließende Regenbogenanimation erzeugen. Obwohl der 3,3-V-Logikpegel des ESP32 bei den meisten WS2812B-Bausteinen problemlos funktioniert, zeigen wir im Falle von Instabilität die Lösung mit einem 470-Ω-Reihenwiderstand und einem 1000-

4.9(19)
30
ESP32 Async-Webserver (mit IP-Anzeige auf dem LCD)
#129Fortgeschritten

ESP32 Async-Webserver (mit IP-Anzeige auf dem LCD)

In diesem Projekt verwandeln wir den ESP32 in einen asynchronen Webserver, den Sie über Ihr Smartphone oder Ihren Computer im selben WLAN-Netzwerk steuern können. Dank der ESPAsyncWebServer-Bibliothek kann der Server mehrere Anfragen gleichzeitig bearbeiten (im Gegensatz zum klassischen WebServer.h, der bei einer einzigen Anfrage blockiert). Sie können über den Browser die IP-Adresse des ESP32 öffnen und durch Drücken der ON/OFF-Schaltflächen (Routen /on und /off) die an GPIO 5 anges

4.8(16)
26
ESP32 Deep Sleep – Batteriesparmodus (OLED + RTC-RAM-Zähler)
#135Fortgeschritten
Premium

ESP32 Deep Sleep – Batteriesparmodus (OLED + RTC-RAM-Zähler)

Der Deep-Sleep-Modus des ESP32 senkt den Stromverbrauch auf etwa 10 µA, indem er die CPU und die meisten Peripheriegeräte abschaltet, und ist für batteriebetriebene IoT-Geräte von entscheidender Bedeutung. In diesem Projekt verwenden wir drei verschiedene Weckquellen: den Timer (15 s), einen externen Pin (EXT0 – Taste GPIO 33) und die Berührungserkennung (T0/GPIO 4). Mit RTC_DATA_ATTR markierte Variablen bleiben während des Deep-Sleep-Modus erhalten – der Boot-Zähler, der Timer-Wake-Zähler und

4.3(10)
16
ESP32-OTA-Update – Drahtlose Firmware-Installation (mit LCD-Display)
#132Fortgeschritten
Premium

ESP32-OTA-Update – Drahtlose Firmware-Installation (mit LCD-Display)

In diesem Projekt lernst du, wie du auf dem ESP32 ohne USB-Kabel über WLAN neue Firmware installieren kannst. Mit der ArduinoOTA-Bibliothek wird der ESP32 im Netzwerk sichtbar und wird im Reiter „Network port“ der Arduino-IDE automatisch als bluegrays-ota aufgelistet. Die erste Installation erfolgt über USB, alle nachfolgenden Updates erfolgen drahtlos – eine äußerst wichtige Funktion für Feldgeräte. Auf dem I2C-LCD-Display werden der WLAN-Status, die IP-Adresse, der Hostname, der Fortschrit

4.6(14)
22
ESP32 Bewegungsalarmsystem (PIR + Buzzer + LED + Telegram)
#145Fortgeschritten
Premium

ESP32 Bewegungsalarmsystem (PIR + Buzzer + LED + Telegram)

Ein intelligentes Sicherheitsalarmsystem, das Buzzer und LED aktiviert, sobald der PIR-Sensor Bewegung erkennt, und gleichzeitig eine sofortige Benachrichtigung per Telegram an den Besitzer sendet. Ein 30-sekündiger Cooldown begrenzt die Häufigkeit wiederholter Alarme; dieser Mechanismus überprüft weder die Gültigkeit der PIR-Erkennungen noch verhindert er Fehlauslösungen. Geeignet für Heimsicherheit, Garagenüberwachung, Lagerräume oder Arbeitszimmer. Mit ESP32-CAM sind Foto-Benachrichtigungen m

0.0(0)
9