ESP32/Sleep and wake-up/68. Deep sleep and wake sources
Your chip
Your language
Sleep and wake-up · 68 of 81

Deep sleep and wake sources

The chip switches almost all of itself off and draws around 10 microamps. That is the easy part. The number that decides whether the battery lasts a week or a year is how many seconds it is awake either side.

/esp32/deep-sleep-and-wake-sources · arduino · S3

Where the battery actually goes

Awake 4 s every 15 min
5 mo
Wake every15 min
Awake for4.0 s
Battery2000 mAh
Average draw
543 µA
Runs for
5 mo
Spent awake
98%
98% of the battery is spent in the 4.0 seconds it is awake. Halving the sleep current changes nothing here; halving the awake time nearly doubles the life. Store the Wi-Fi channel and IP in RTC memory so the next join takes 0.5 s instead of 3, and do not delay() waiting for a sensor you could have started before connecting.

The wake sources

SourceCostsUse for
TimerNothing extraAnything periodic
ext0 — one RTC pinNothing extraA single button or a reed switch
ext1 — several RTC pinsNothing extraA keypad, several sensors
Touch padA few µAA button with no moving parts
ULP co-processor~100 µA while checkingWatching an analog value

Only RTC-capable GPIOs can wake the chip. On the classic ESP32 that is 0, 2, 4, 12–15, 25–27 and 32–39 — an ordinary GPIO cannot do it.

Light sleep, and when to prefer it

Light sleep keeps RAM and the Wi-Fi connection alive and costs around 800 µA. Execution resumes on the next line rather than restarting. It is the right choice when the wake-up must be immediate and the connection must survive; deep sleep is the right choice for anything measured in minutes.

On your S3
ChipXtensa LX7 · 2 × 240 MHz
Board settingESP32S3 Dev Module
Default I2CSDA 8 · SCL 9
Watch out forThe port vanishes after upload

The code

Deep sleep is not a pause - the board restarts from the top of setup when it wakes. Anything that must survive goes in RTC memory, which is the only RAM that stays powered.

deep_sleep.ino
#include <esp_sleep.h>

RTC_DATA_ATTR int wakeCount = 0;     // survives deep sleep, not power loss

void setup() {
  Serial.begin(115200);
  delay(50);

  esp_sleep_wakeup_cause_t why = esp_sleep_get_wakeup_cause();
  Serial.printf("boot %d, cause %d\n", ++wakeCount, why);

  // ... take a reading, send it, and be quick about it ...

  esp_sleep_enable_timer_wakeup(15ULL * 60 * 1000000);   // 15 minutes
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_33, 0);          // or a low pin

  Serial.flush();                    // or the last line is lost
  esp_deep_sleep_start();            // nothing after this line runs
}

void loop() {}

The reset reason tells you whether this is a cold boot or a wake-up, and they usually want different code. A first boot might provision Wi-Fi; a wake-up must not.

When it does not work

The current is 20 mA, not 10 µA

Almost always the dev board rather than the chip. A power LED, a USB-serial chip and an inefficient regulator all keep drawing while the ESP32 sleeps. Measure the bare module, or cut the LED.

Variables are back to their initial values after waking

That is correct - deep sleep restarts the program. Mark anything that must survive with RTC_DATA_ATTR, and keep it small.

The battery lasts days instead of months

Look at how long it is awake, not at the sleep current. Four seconds at 120 mA every minute is the whole budget. Cache the Wi-Fi channel and IP in RTC memory to cut the reconnect from three seconds to under one.

The last serial line is always missing

Deep sleep cuts power to the UART mid-transmission. Call Serial.flush() before sleeping.

Where this goes next

Ten microamps is not the floor. Five is, and getting there is a matter of what you switch off before the same function call.

Hibernation, the floor below sleep

Edit this page — content/esp32/deep-sleep-and-wake-sources.mdx

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse ESP32 on the forum