Mental model
Deep sleep is closer to "power off with an alarm clock" than to pausing:
- CPUs and most RAM are powered down. Only the RTC controller, the ULP coprocessor and RTC fast/slow memory stay on.
- On wake-up the chip boots again and your sketch starts from
setup(). Normal global variables are reset. - Anything that must survive goes into RTC memory (
RTC_DATA_ATTR) or flash (Preferences/NVS).
Wake-up sources: RTC timer, ext0 (one RTC GPIO), ext1 (several RTC GPIOs), touch pad, ULP coprocessor.
Example (original ESP32, Arduino core)
#include <Arduino.h>
#include "esp_sleep.h"
#define uS_TO_S_FACTOR 1000000ULL // timer wake-up takes microseconds
#define TIME_TO_SLEEP 300 // seconds
#define WAKE_GPIO GPIO_NUM_33 // must be an RTC-capable GPIO
RTC_DATA_ATTR int bootCount = 0; // survives deep sleep, not a power cut
void setup() {
Serial.begin(115200);
bootCount++;
switch (esp_sleep_get_wakeup_cause()) {
case ESP_SLEEP_WAKEUP_TIMER: Serial.println("woke: timer"); break;
case ESP_SLEEP_WAKEUP_EXT0: Serial.println("woke: button"); break;
default: Serial.println("woke: power-on or reset"); break;
}
Serial.printf("boot #%d\n", bootCount);
// ... read sensor, send data, then:
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
esp_sleep_enable_ext0_wakeup(WAKE_GPIO, 0); // wake when the pin goes LOW
Serial.flush();
esp_deep_sleep_start(); // never returns
}
void loop() {} // not reached
Pitfalls
- No wake-up source enabled → the chip sleeps until a hardware reset.
- Timer units are microseconds.
esp_sleep_enable_timer_wakeup(60)sleeps 60 µs, not 60 s. - Wrong pin for ext0/ext1: only RTC-capable GPIOs can wake the chip; the set differs per ESP32 variant.
- RTC memory is not a database: it survives deep sleep but not a power cut. Use Preferences for settings.
- Dev board current ≠ chip current: USB-serial chips, LEDs and regulators on dev boards often draw far more than the ESP32 in deep sleep. Measure on your final hardware.
- Native USB boards (e.g. ESP32-S3): the USB serial port disappears while the chip sleeps, so the serial monitor disconnects. That's expected.