Deep Sleep: Wake Sources, State, RTC Memory
Battery Life Is a State Machine With the Power Removed Between Steps
The robot hand has a small wireless calibration puck. It wakes, samples temperature near the motors, sends one status packet, and disappears again. The product manager wants it to run for months from a small battery.
The firmware engineer says, "No problem, the ESP32 can deep sleep at microamps." That sentence is true in the same way that "a car can idle" is true: it ignores everything else attached to the system. Regulators leak. Sensors stay powered. Pull-ups burn current. Wi-Fi bursts are expensive. A forgotten LED can cost more than the sleeping microcontroller.
Deep sleep is not a pause button. It is a design pattern: do the expensive work quickly, save the minimum state needed for the next cycle, configure a wake source, turn most of the chip off, and accept that the next wake looks a lot like boot.
By the end, you can
- Calculate charge per wake-sleep cycle from active current, active time, sleep current and interval
- Explain why reducing active time can matter more than shaving a few microamps from sleep
- Choose timer, GPIO, touch or ULP wake based on what remains powered in deep sleep
- Use RTC memory for small state that must survive deep sleep, while treating normal RAM as lost
- Write firmware as a wake loop that handles cold boot, timer wake and external wake differently
- Measure the whole sleeping system instead of trusting only the microcontroller datasheet
The battery sees charge, not intent
The active current can be tens or hundreds of milliamps. The deep-sleep current can be microamps. The reason the system still works is not that the active current is small. It is that the active interval is short.
The useful unit here is charge per cycle. If the board wakes every five minutes,
spends 2.5 s active at 90 mA, then sleeps the remaining 297.5 s at 12 uA,
the charge is:
The sleep part is only about 3.6 mA*s. The active burst is about 225 mA*s.
In this example, making the wake code one second faster saves more than cutting
sleep current by several microamps.
Try these moves:
- Double the wake interval from 300 s to 600 s. The active charge is the same, but the average current falls.
- Raise active time from 2.5 s to 7 s. The battery life collapses faster than the sleep-current number suggests.
- Raise sleep current from 12 uA to 80 uA. Now leakage matters because the long interval has become expensive.
- Lower active current but leave active time long. You still pay for every second awake.
In a 5-minute sleep cycle, which change usually gives the biggest win when Wi-Fi active current dominates?
-
Correct. When active charge dominates, reducing active seconds is often the largest lever.
-
Names do not change charge per cycle.
-
A larger battery hides the problem until leakage, self-discharge or product size catches up.
-
GPIO34 is input-only, and blinking during sleep is exactly the kind of load that ruins the budget.
The wake source must stay alive
Deep sleep turns off the main CPU and much of the chip. Only the retained domains can notice the event that wakes the system. This is why wake-source selection is an electrical design decision, not just a firmware call.
Timer wake is the cleanest first design. It is perfect for "sample every five minutes" or "phone home once per hour." The RTC timer remains alive, wakes the chip, and the firmware runs the same short loop each time.
External wake is for events that cannot wait for the next timer tick: a lid opening, a magnet moving, a fault line asserting, or a user button. The circuit must hold a valid level while the chip sleeps and while it wakes.
Motion sensors are a different bargain. A PIR module can wake the system when a warm object moves, but the module itself consumes power. For a wall-powered device that is fine. For a coin cell it may be the main load. The wake source has to fit the battery, not just the feature list.
Touch wake and ULP wake are powerful but easy to over-use. Touch depends on board geometry, enclosure material and noise. ULP lets a tiny coprocessor sample slowly while the main CPU sleeps, but it adds a second program and another set of limits. Use them when the hardware reason is clear.
RTC memory is a small notebook
After deep sleep, ordinary RAM is not something to trust. Code starts again, global variables are initialized again, and the program has to inspect the wake reason. The state that must survive belongs in RTC memory or in nonvolatile storage, depending on how important and how write-heavy it is.
Good RTC state is small and disposable:
- Boot count.
- Last sensor sample.
- Backoff timer after a failed transmission.
- Calibration coefficients copied from flash.
- A version number or checksum so stale state can be rejected.
Bad RTC state is a whole application database. If the information must survive battery removal, save it to flash or external storage with a wear strategy. If the information can be recomputed after a cold boot, do not make the sleep path fragile by preserving too much.
A board wakes every 10 minutes. It draws 120 mA for 4 s, then sleeps at 20 uA
for the remaining time. Estimate the charge per cycle and say which term dominates.
Show worked solution
Active charge is 120 * 4 = 480 mA*s. Sleep time is 596 s, and sleep current is
0.020 mA, so sleep charge is about 11.9 mA*s. Total is about 492 mA*s, and
the active term dominates.
Firmware is a wake loop
A deep-sleep program should be written as a loop that can start from several causes. Was this a true power-on reset? A timer wake? A GPIO wake? A brownout after a weak battery sagged during Wi-Fi transmit? Those are different stories.
On every wake, do the same disciplined sequence:
- Read and log the wake reason as early as possible.
- Check whether RTC state is valid for this firmware version.
- Bring up only the peripherals needed for this cycle.
- Do the measurement or event handling.
- Transmit or store the result.
- Put external sensors and loads into their lowest safe state.
- Save the small state record.
- Configure the next wake source.
- Enter deep sleep.
If the board sometimes wakes and immediately sleeps again, log why. If it wakes from reset instead of the timer, log that separately. Debug output is expensive, but a few early serial lines during development can save days of guessing.
Why should deep-sleep firmware read the wake reason before doing normal work?
-
Correct. The same entry point can be reached by several causes, and the safe response can differ.
-
Ohm's law is not stateful firmware metadata.
-
Regular RAM is not the place to keep state across deep sleep.
-
Wi-Fi transmission is active work. It is usually one of the costly parts of the wake burst.
Measure the whole sleeping system
The datasheet number is for a chip in a specified condition. Your board includes a regulator, pull resistors, sensors, level shifters, LEDs, flash, leakage paths and maybe a USB bridge. A real product battery sees all of it.
For active current, a USB meter or bench supply readout may be enough to find large problems. For sleep current, the measurement tool becomes part of the experiment. A handheld multimeter on its microamp range can add burden voltage. A scope plus current probe may miss long sleep intervals. A dedicated power profiler is often the right tool when you need to see both the Wi-Fi spike and the sleep floor.
The measurement checklist is blunt:
- Remove or disable status LEDs before claiming a sleep number.
- Measure with sensors powered and unpowered, not only with the ESP32 alone.
- Verify the regulator's quiescent current at the actual battery voltage.
- Check pull-up and divider currents that run during sleep.
- Trigger real wake events, not only timer wake in a firmware example.
- Record temperature if leakage or battery chemistry matters.
Key takeaways
- Deep sleep saves power when the wake path is short and the sleeping system is truly quiet.
- Charge per cycle is ; peak current alone is not the answer.
- Wake sources must remain powered and connected to an awake domain: timer, RTC GPIO, touch or ULP.
- RTC memory is for small temporary state. It is not a substitute for nonvolatile storage after battery removal.
- Measure the whole board, including regulators, sensors, pulls, dividers and debug hardware.
When to choose light sleep instead
Deep sleep is best when wake latency can be hundreds of milliseconds and normal RAM does not need to survive. Light sleep is useful when latency matters and RAM retention is worth the extra current. The engineering choice is not "lowest current number wins." It is the lowest energy that still meets the response-time and state-retention needs of the product.
A sleeping product is still an active design. Its pins have reset states, its sensors have leakage, its firmware has memory boundaries, and its battery is counting every microamp-second. Treat deep sleep as a complete system mode, and the battery-life math starts behaving like engineering instead of hope.