The Reset That Ruins Your Week: Hunting Down Random Microcontroller Brownouts
Every maker knows this particular flavor of pain. You flash the firmware, run it for a few hours, everything's golden. You screw the enclosure shut, mount it on the wall, and two days later you get a text from Home Assistant telling you your garage sensor dropped offline. Again. For the third time this week.
Intermittent microcontroller resets are the worst kind of bug because they rarely reproduce when you're watching. The board behaves perfectly on your bench with a nice bench supply, then falls apart in the real world. The good news: these gremlins almost always fall into one of a handful of categories, and there's a systematic way to flush them out.
Start With the Obvious Suspect: Power
Before you blame your code, look at your power rail. Brownout resets are the single most common cause of "random" reboots, and they're usually self-inflicted.
The classic scenario: you're running an ESP32 or an nRF52 off a long USB cable or a cheap wall wart, and everything's fine until the radio fires up a transmission at full power. That transmit burst can pull 300–500mA in a spike lasting just a few milliseconds. If your supply and wiring can't source it, the rail sags, the brownout detector trips, and the chip reboots. From your perspective, it's random. From the chip's perspective, it's doing exactly what it was told.
Here's how to catch it:
- Check the reset reason. Most modern MCUs log why they reset. On ESP32, pull the register or check the boot log —
RTCWDT_BROWNOUT_RESETis your smoking gun. On STM32, read the RCC_CSR flags. Don't skip this step; it saves hours of guessing. - Scope the rail. Set your oscilloscope to normal trigger mode, trigger on a falling edge a few hundred millivolts below nominal, and let it sit. When the gremlin strikes, you'll have the capture. A 100mV dip lasting 2ms that you'd never see with a multimeter is obvious on a scope.
- Do the math on your wiring. 24 AWG jumper wire has about 0.08Ω per foot. A 500mA spike through three feet of dupont wire and a breadboard's sketchy contacts can drop half a volt. Breadboards are especially notorious — those spring contacts were never meant to carry radio-level current bursts.
Decoupling: The Rule Everyone Knows and Ignores
We've all heard "put a 100nF cap next to every VCC pin," and we've all been tempted to skip it because the board worked anyway. Then it worked anyway... until it didn't.
Decoupling caps are your first line of defense against inrush and switching transients. A bulk electrolytic (say 470µF) at the power entrance handles slow sags, while 100nF ceramics right at each chip's supply pins handle the fast spikes. If your board resets when a relay clicks or a motor kicks on, that's an inrush problem — the switched load is yanking the shared rail down, and your MCU is collateral damage.
One subtlety worth knowing: ceramic capacitors lose capacitance under DC bias. That 10µF 0805 MLCC might only be delivering 4µF at 3.3V. If your budget was tight to begin with, you're running on fumes.
Ground Loops and the Return Path Nobody Thinks About
Current flows in loops. That spike current pulled by your radio or your servo has to get back to the supply, and if it's returning through the same thin traces your sensitive analog circuitry uses as a ground reference, you've built yourself a noise injector.
Symptoms of a ground problem include resets that correlate with mechanical loads, ADC readings that jump when things switch, and behavior that changes when you touch the enclosure or swap USB cables. Fixes range from simple (star grounding — run each return path back to a single point) to structural (a proper ground plane on a real PCB instead of a bird's nest of jumper wires).
When It Actually Is the Firmware
Sometimes the hardware is innocent. Before you reflow the whole board, check these firmware suspects:
- Watchdog timers. If you enabled a watchdog and your code blocks on an I2C read that never returns (hello, stuck sensor), the dog bites and the chip resets. Look for
WDTin your reset reason. The fix is proper timeout handling on your bus transactions, not disabling the watchdog. - Stack overflows and wild pointers. A corrupted return address can send the CPU into the weeds until it trips an exception and reboots. Enable stack canaries if your RTOS supports them, and put a hard fault handler that logs instead of silently rebooting.
- Race conditions on shared state. These are rarer, but a corrupted peripheral config can wedge a chip in ways that look like hardware failure.
A trick that pays for itself: log the reset reason and a uptime counter to flash (or better, to your network) on every boot. After a week of data, you'll know whether you're chasing brownouts, watchdog bites, or software faults — and whether they correlate with your furnace kicking on at 3 AM.
The Long Stakeout
The hardest part of intermittent bugs is simply waiting. Set up your scope with a segmented memory or a trigger on the power rail, log reset reasons persistently, and let the thing run. A gremlin that strikes once a week is maddening, but it's also predictable: capture it once, and the fix is usually a 10-cent capacitor and an hour of rework.
The ghost in the machine is almost never a ghost. It's a voltage sag, a missing decoupling cap, or a watchdog you forgot you armed. Give it a week of patient surveillance, and it'll confess.