Guide · Intermediate · ESP32
ESP32 Watchdogs and Brownout Detection
Why boards reset near motors — and how to log it.
Project template
- Goal & materials
- Steps / firmware
- Troubleshooting
- AI assist notes
- Related gear & books
An ESP32 that runs fine on the bench and resets as soon as a motor, relay, or pump turns on is almost always dealing with power trouble or a watchdog firing. The good news is that the chip tells you why it reset. This guide explains the two mechanisms, shows how to log reset reasons, and covers the hardware fixes that actually stop the resets.
Two different safety nets
Brownout detector
The ESP32 monitors its supply voltage. If it drops below a threshold, the chip resets instead of running in an unreliable state where flash writes and radio operation can misbehave. On the serial console you typically see a message containing "Brownout detector was triggered." The threshold is configurable in ESP-IDF's menuconfig.
Watchdog timers
Watchdogs reset the chip when software stops making progress:
- Task watchdog: fires when a monitored task, including the idle task, does not run for too long. A tight loop that never yields is a common cause.
- Interrupt watchdog: fires when interrupts are blocked for too long, for example by a long-running interrupt handler.
A watchdog reset points at code, a brownout points at power. Knowing which one you have saves hours.
Log the reset reason
ESP-IDF's esp_reset_reason() works in Arduino sketches too. Log it at startup and keep a count in flash so you can see what happened while you were not watching:
#include <Arduino.h>
#include <Preferences.h>
#include "esp_system.h"
const char* reasonName(esp_reset_reason_t r) {
switch (r) {
case ESP_RST_POWERON: return "power-on";
case ESP_RST_BROWNOUT: return "brownout";
case ESP_RST_TASK_WDT: return "task watchdog";
case ESP_RST_INT_WDT: return "interrupt watchdog";
case ESP_RST_PANIC: return "panic/exception";
case ESP_RST_SW: return "software restart";
case ESP_RST_DEEPSLEEP:return "deep sleep wake";
default: return "other";
}
}
void setup() {
Serial.begin(115200);
esp_reset_reason_t r = esp_reset_reason();
Preferences prefs;
prefs.begin("resets", false);
char key; // NVS keys are limited to 15 characters
snprintf(key, sizeof(key), "r%d", (int)r);
uint32_t count = prefs.getUInt(key, 0) + 1;
prefs.putUInt(key, count);
prefs.end();
Serial.printf("Reset reason: %s (seen %u times)\n", reasonName(r), count);
}
void loop() {}
Send the reason over MQTT or include it in your first status message after boot, so remote boards report it too. Avoid writing to flash on every loop; once per boot is fine.
Why motors cause resets
- Supply sag. A motor's startup current pulls the shared supply down, and the ESP32's regulator input drops with it.
- Wi-Fi bursts. The radio draws short current peaks during transmit. Combined with a motor start, a marginal supply dips below the brownout threshold.
- Inductive spikes and ground bounce. Switching motors, relays, and solenoids creates voltage spikes and shifts in the ground reference that can disturb the microcontroller.
- Long, thin wires. Resistance in power wiring turns current peaks into voltage drops.
Hardware fixes, in order of impact
- Separate supplies. Power motors from their own supply and the ESP32 from a clean regulated one, with grounds joined at one point.
- Flyback diodes across relay coils, solenoids, and brushed DC motors driven by a transistor. Many relay modules include them; bare coils need them.
- Bulk capacitance near the ESP32's supply input (a few hundred microfarads electrolytic) plus a small ceramic capacitor, to ride through short dips.
- Proper motor drivers rather than driving loads directly from GPIO pins.
- Short, adequate wiring for power, and keep motor wiring away from signal wiring.
- A better USB cable or supply during development. Long, thin USB cables cause brownouts on their own.
Software fixes for watchdog resets
- Avoid long blocking loops. Break work into steps, and call
delay()oryield()so other tasks run. - Keep interrupt handlers short; set a flag and do the work in the main loop or a task.
- If you add your own tasks to the task watchdog, reset it from each task at a regular interval. The watchdog API changed between ESP-IDF 4.x and 5.x (which newer Arduino-ESP32 cores use), so check the documentation for your version.
- Use the watchdog as a safety net, not something to disable. A device that resets and recovers is better than one that hangs forever.
Common mistakes
- Disabling the brownout detector. Many forum posts suggest it. The resets stop, but the board then runs on bad voltage, which can corrupt flash and cause stranger failures later.
- Powering a servo or motor from the dev board's 5 V or 3.3 V pin.
- Assuming every reset is a software bug and rewriting code that was fine.
- Testing only on a laptop USB port, then deploying on a different supply.
Summary
Log the reset reason first. Brownouts mean the supply is sagging, so separate motor power, add flyback diodes and bulk capacitance, and fix wiring. Watchdog resets mean code is blocking, so restructure loops and interrupt handlers. Keep both safety nets enabled and let them tell you what is wrong.
Related
- Projects hub
- Newsletter
- Books for deeper reading