๐ค ESP32 Deep Sleep Won't Wake - Complete Fix Guide
๐ Common Causes of Deep Sleep Wake Issues
- ๐ No Wake Source Configured โ esp_sleep_enable_timer_wakeup() not called
- ๐ Wrong GPIO for External Wake โ Using RTC IO pin incorrectly
- ๐ Wake Level Mismatch โ HIGH vs LOW trigger level
- ๐ RTC Memory Corruption โ Variables stored in RTC memory not preserved
- ๐ Touch Sensor Not Calibrated โ Touch wake thresholds wrong
- ๐ ULP Program Not Running โ ULP coprocessor program not loaded or configured
๐ ESP32 Deep Sleep Wake Sources
| Wake Source | Power Consumption | Best For |
|---|---|---|
| Timer Wake | 5-150ยตA | Regular interval readings |
| External Wake (GPIO) | 5-150ยตA | Button press, motion sensor |
| Touch Wake | 5-150ยตA | Touch buttons |
| ULP Coprocessor | 25-150ยตA | Sensor monitoring in sleep |
| Timer + GPIO | 5-150ยตA | Both interval and external |
1๏ธโฃ Timer Wake - Basic Working Example
The simplest deep sleep configuration:
void setup() {
Serial.begin(115200);
delay(1000);
// Do your work here
Serial.println("Woke up! Taking sensor reading...");
// Configure wake up after 10 seconds (10,000,000 microseconds)
esp_sleep_enable_timer_wakeup(10 * 1000000);
Serial.println("Entering deep sleep for 10 seconds...");
// Go to deep sleep
esp_deep_sleep_start();
}
void loop() {
// This will never run
}
2๏ธโฃ External GPIO Wake - Button or Sensor Trigger
Wake ESP32 when a GPIO pin changes state:
Which GPIOs can wake ESP32?
| GPIOs | Wake Type | Notes |
|---|---|---|
| 0, 2, 4, 12, 13, 14, 15, 25, 26, 27, 32, 33 | RTC IO | Can wake from deep sleep |
| Other GPIOs | Non-RTC | Cannot wake from deep sleep! |
// GPIO 33 is an RTC IO pin - can wake from deep sleep
#define WAKE_PIN 33
void setup() {
Serial.begin(115200);
delay(1000);
// Configure wake pin
// Wake when pin goes HIGH (button press)
esp_sleep_enable_ext0_wakeup(WAKE_PIN, HIGH);
// Or use ext1 for multiple pins:
// esp_sleep_enable_ext1_wakeup(BIT(WAKE_PIN), ESP_EXT1_WAKEUP_ANY_HIGH);
Serial.println("Going to sleep. Press button on GPIO 33 to wake.");
esp_deep_sleep_start();
}
void loop() {}
3๏ธโฃ Touch Wake - Capacitive Touch Buttons
// Touch pins: T0(GPIO4), T1(GPIO0), T2(GPIO2), T3(GPIO15),
// T4(GPIO13), T5(GPIO12), T6(GPIO14), T7(GPIO27), T8(GPIO33), T9(GPIO32)
#define TOUCH_PIN T0 // GPIO4
void setup() {
Serial.begin(115200);
delay(1000);
// Calibrate touch threshold (run once, save value)
int touchValue = touchRead(TOUCH_PIN);
Serial.print("Touch value: ");
Serial.println(touchValue);
// Set threshold lower than normal reading
// Normal: ~50, Touched: ~20
touchSleepWakeUpEnable(TOUCH_PIN, 40);
Serial.println("Touch to wake...");
esp_deep_sleep_start();
}
void loop() {}
4๏ธโฃ Preserve Data Across Sleep with RTC Memory
Variables stored in RTC memory survive deep sleep:
// Variables in RTC memory keep their value across sleep
RTC_DATA_ATTR int bootCount = 0;
void setup() {
Serial.begin(115200);
delay(1000);
// Increment boot counter (survives deep sleep)
bootCount++;
Serial.print("Boot number: ");
Serial.println(bootCount);
// Get wakeup reason
esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason) {
case ESP_SLEEP_WAKEUP_TIMER:
Serial.println("Woke by timer");
break;
case ESP_SLEEP_WAKEUP_EXT0:
Serial.println("Woke by GPIO button");
break;
case ESP_SLEEP_WAKEUP_TOUCH:
Serial.println("Woke by touch");
break;
default:
Serial.println("First boot or other wake");
}
// Configure 10 second timer wake
esp_sleep_enable_timer_wakeup(10 * 1000000);
Serial.println("Going to sleep...");
esp_deep_sleep_start();
}
5๏ธโฃ ULP Coprocessor - Monitor Sensors in Deep Sleep
The ULP (Ultra Low Power) coprocessor can read sensors while main CPU sleeps:
// ULP example: Wake when temperature exceeds threshold
// This requires ULP RISC-V assembly programming (advanced)
// For simpler use, OceanRemote handles ULP automatically
// when you enable "Deep Sleep" mode in device configuration
6๏ธโฃ Debugging - Why Won't My ESP32 Wake?
Use this diagnostic sketch to verify wake configuration:
#include "esp_sleep.h"
void setup() {
Serial.begin(115200);
delay(1000);
// Print wakeup reason from last sleep
print_wakeup_reason();
// Test: Configure timer wake
esp_sleep_enable_timer_wakeup(10 * 1000000);
// Test: Configure GPIO wake on pin 33
// esp_sleep_enable_ext0_wakeup(GPIO_NUM_33, HIGH);
Serial.println("Sleeping for 10 seconds...");
esp_deep_sleep_start();
}
void print_wakeup_reason() {
esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason) {
case ESP_SLEEP_WAKEUP_UNDEFINED:
Serial.println("First boot or reset (not wake from sleep)");
break;
case ESP_SLEEP_WAKEUP_EXT0:
Serial.println("Wakeup caused by external signal using RTC_IO");
break;
case ESP_SLEEP_WAKEUP_EXT1:
Serial.println("Wakeup caused by external signal using RTC_CNTL");
break;
case ESP_SLEEP_WAKEUP_TIMER:
Serial.println("Wakeup caused by timer");
break;
case ESP_SLEEP_WAKEUP_TOUCHPAD:
Serial.println("Wakeup caused by touchpad");
break;
case ESP_SLEEP_WAKEUP_ULP:
Serial.println("Wakeup caused by ULP program");
break;
default:
Serial.print("Wakeup reason: ");
Serial.println(wakeup_reason);
}
}
void loop() {}
โ ๏ธ Common Deep Sleep Mistakes
- Using non-RTC GPIO for wake โ Only specific pins can wake ESP32
- Forgetting to enable wake source โ Must call esp_sleep_enable_* before esp_deep_sleep_start()
- Serial.print after sleep โ Serial may not be ready immediately on wake
- Not adding delay on wake โ Add delay(1000) for Serial to initialize
- Using WiFi in deep sleep โ WiFi turns off in deep sleep
- No pull-up/pull-down on wake pins โ Floating pins cause random wakes
๐ Deep Sleep Power Consumption Reference
| Mode | Current Draw | Battery Life (2000mAh) |
|---|---|---|
| Active + WiFi | 80-240mA | 8-25 hours |
| Modem Sleep | 15-30mA | 2-5 days |
| Light Sleep | 5-10mA | 8-16 days |
| Deep Sleep (timer) | 5-150ยตA | 1-5 months! |
| Hibernation | 2.5-5ยตA | 1-2 years |
๐ Battery-Powered Temperature Sensor (Complete Example)
#include "esp_sleep.h"
#include "DHT.h"
#define DHTPIN 4
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
RTC_DATA_ATTR int bootCount = 0;
void setup() {
Serial.begin(115200);
delay(1000);
bootCount++;
// Print wake reason
esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause();
if (wakeup_reason != ESP_SLEEP_WAKEUP_TIMER) {
Serial.println("First boot - starting sensor readings");
}
// Read sensor (takes 2-3 seconds)
dht.begin();
float temp = dht.readTemperature();
float humidity = dht.readHumidity();
if (!isnan(temp)) {
Serial.print("Temperature: ");
Serial.print(temp);
Serial.println("ยฐC");
// Send to OceanRemote or other service here
}
// Configure timer wake for 5 minutes (5 * 60 * 1000000)
esp_sleep_enable_timer_wakeup(300 * 1000000);
Serial.print("Deep sleep for 5 minutes. Boot count: ");
Serial.println(bootCount);
esp_deep_sleep_start();
}
void loop() {}
โ Best Practices for Deep Sleep
- Use RTC GPIO pins (0,2,4,12-15,25-27,32,33) for external wake
- Add pull-up or pull-down resistors to wake pins to prevent false triggers
- Store persistent data in RTC_DATA_ATTR variables
- Add delay(1000) at start of setup() for Serial to initialize
- Use esp_sleep_get_wakeup_cause() to debug wake sources
- Consider hibernation mode for maximum battery life (2.5ยตA)
- Test with short wake intervals (10 seconds) during development
โ Frequently Asked Questions
Q: How do I make ESP32 wake from deep sleep with a button?
A: Connect button to an RTC GPIO pin (0,2,4,12-15,25-27,32,33) with a pull-up resistor, then call esp_sleep_enable_ext0_wakeup(pin, LOW) for button to GND.
Q: What's the difference between deep sleep and hibernation?
A: Deep sleep (5-150ยตA) keeps RTC memory. Hibernation (2.5-5ยตA) loses RTC memory but consumes less power. Use hibernation if you don't need to preserve data.
Q: Why does my ESP32 wake immediately after going to sleep?
A: Your wake pin is already in the trigger state. Add a pull-up/pull-down resistor or invert the trigger level (HIGH vs LOW).
Q: Can I use WiFi in deep sleep?
A: No. WiFi turns off completely in deep sleep. Wake up, connect to WiFi, send data, then go back to sleep.
Q: Does OceanRemote support deep sleep?
A: Yes! OceanRemote's firmware generator has a "Deep Sleep" option. Just enable it and set your wake interval. We handle all the ULP and wake configuration for you. Generate your firmware โ
๐ Related Troubleshooting Guides
๐ Need a Battery-Optimized Solution?
OceanRemote's deep sleep mode includes:
- โ Configurable wake intervals
- โ Automatic sensor reading
- โ Data upload on wake
- โ Months of battery life
- โ No coding required