Open Claw
中文
· OpenClaw Team

ESP32 Deep Sleep Power Optimization for Always-On AI Agents

One of ESP-Claw’s key advantages is its low power consumption — just 0.5 watts when active. But what if you want to run your AI agent on a battery or solar panel? With the right sleep strategies, you can extend battery life from hours to weeks.

This guide covers everything from basic deep sleep to advanced wake-on-event patterns.

Understanding ESP32 Power States

The ESP32 has several power states, each with dramatically different current draw:

StateESP32-C3 CurrentESP32-S3 CurrentDescription
Active (Wi-Fi TX)~130mA~180mAFull operation, transmitting data
Active (Wi-Fi RX)~95mA~120mAListening for data
Modem Sleep~15mA~20mACPU active, Wi-Fi radio off
Light Sleep~0.8mA~1.2mACPU paused, RAM retained, fast wake
Deep Sleep~5µA~7µAOnly RTC memory retained, slow wake
Hibernation~2.5µA~3µAMinimal state, only RTC timer wake

The difference between active and deep sleep is a factor of 25,000x. This is what makes battery-powered AI agents feasible.

Battery Life Calculator

With a common 1000mAh LiPo battery (3.7V):

StrategyAverage CurrentBattery Life
Always active (Wi-Fi on)130mA~7.7 hours
Active 10 sec/min, sleep rest~12mA~3.5 days
Active 10 sec/5 min, deep sleep~2.5mA~16.7 days
Active on motion only (PIR wake)~0.5mA avg~83 days
Deep sleep + RTC timer (hourly check)~0.05mA~2.3 years (theoretical)

The key insight: an AI agent doesn’t need to be connected to Wi-Fi 100% of the time. If you’re primarily using Telegram or MQTT, the agent can sleep between interactions and wake periodically to check for messages.

Basic Deep Sleep Implementation

The simplest deep sleep pattern: sleep for a fixed duration, wake up, check for messages, respond, and go back to sleep.

#include "esp_sleep.h"
#include "esp_wifi.h"
#define SLEEP_DURATION_US (5 * 60 * 1000000ULL) // 5 minutes
void app_main(void) {
// Initialize hardware, connect Wi-Fi
claw_agent_init(&config);
// Check for pending messages
int messages = claw_check_messages();
if (messages > 0) {
// Process all pending messages
claw_process_pending();
// Stay awake for a bit to handle follow-up conversation
vTaskDelay(pdMS_TO_TICKS(30000)); // 30 seconds
}
// Disconnect Wi-Fi cleanly
esp_wifi_disconnect();
esp_wifi_stop();
// Configure wake-up timer
esp_sleep_enable_timer_wakeup(SLEEP_DURATION_US);
// Enter deep sleep
esp_deep_sleep_start();
// Code after this line never executes
}

When the timer fires, the ESP32 reboots from scratch — app_main() runs again from the beginning. This is why deep sleep uses so little power: almost everything is powered off.

Wake-on-GPIO: Motion-Triggered Agent

A more intelligent approach: sleep until a PIR motion sensor detects someone, then wake up and be ready to interact.

#define PIR_GPIO GPIO_NUM_3
#define BUTTON_GPIO GPIO_NUM_9
void configure_wake_sources(void) {
// Wake on PIR motion (GPIO 3 goes high)
esp_sleep_enable_ext0_wakeup(PIR_GPIO, 1); // 1 = wake on high
// Also wake on button press (GPIO 9 goes low)
uint64_t button_mask = (1ULL << BUTTON_GPIO);
esp_sleep_enable_ext1_wakeup(button_mask, ESP_EXT1_WAKEUP_ALL_LOW);
// Fallback: also wake every 30 minutes to check messages
esp_sleep_enable_timer_wakeup(30 * 60 * 1000000ULL);
}
void app_main(void) {
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
switch (cause) {
case ESP_SLEEP_WAKEUP_EXT0:
// PIR triggered — someone is nearby
handle_motion_wake();
break;
case ESP_SLEEP_WAKEUP_EXT1:
// Button pressed — user wants to interact
handle_button_wake();
break;
case ESP_SLEEP_WAKEUP_TIMER:
// Periodic check — look for pending messages
handle_timer_wake();
break;
default:
// First boot or reset
handle_initial_boot();
break;
}
// Go back to sleep
configure_wake_sources();
esp_deep_sleep_start();
}

This pattern gives you the best of both worlds: the agent is responsive when someone is present, and uses almost zero power when the room is empty.

Light Sleep: Faster Response at Higher Power

Deep sleep takes 300-500ms to wake (full reboot). If you need faster response times, use light sleep instead:

// Light sleep keeps RAM contents and wakes in ~1ms
esp_sleep_enable_timer_wakeup(100000); // 100ms
esp_light_sleep_start();
// Execution continues here after wake

Light sleep uses ~0.8mA vs deep sleep’s ~5µA, but the agent wakes almost instantly and doesn’t need to reinitialize.

A practical pattern for light sleep:

  1. Connect to Wi-Fi
  2. Subscribe to MQTT topic
  3. Enter light sleep
  4. Wake periodically (every 100ms) to check for MQTT messages
  5. If a message arrives, process it and respond
  6. Go back to light sleep

This achieves ~1ms response latency while using only ~1mA average current.

Power Optimization Checklist

Beyond sleep modes, several other optimizations reduce power consumption:

Wi-Fi optimizations:

  • Use static IP assignment instead of DHCP (saves ~2 seconds of connection time per wake)
  • Store the Wi-Fi channel and BSSID in RTC memory to skip scanning on wake
  • Use Wi-Fi power save mode (esp_wifi_set_ps(WIFI_PS_MIN_MODEM))
  • Reduce TX power if the router is nearby: esp_wifi_set_max_tx_power(40) (10dBm instead of 20dBm)

Peripheral management:

  • Power off sensors when not reading: control VCC via a GPIO pin through a MOSFET
  • Disable Bluetooth if not used: saves ~10mA
  • Turn off the onboard LED
  • Use I2C clock stretching to let sensors sleep between reads

Firmware optimizations:

  • Reduce log level in production: ESP_LOG_NONE saves CPU cycles and power
  • Use menuconfig to disable unused components (CAN, Ethernet, etc.)
  • Optimize compiler flags: -Os for size (less flash reads = less power)

Solar-Powered Setup

With proper sleep management, an ESP-Claw agent can run indefinitely on solar power.

Hardware needed:

  • 5V/1W mini solar panel (~$3)
  • TP4056 charge controller with battery protection (~$0.50)
  • 1000mAh LiPo battery (~$3)
  • ESP32-C3 SuperMini

Power budget:

  • Solar panel output: ~200mA for 4-5 hours/day = ~800-1000mAh/day
  • Agent consumption (deep sleep + hourly check): ~50µA average = ~1.2mAh/day
  • Even on cloudy days with 10% solar efficiency, the panel produces ~80-100mAh — vastly more than needed

The solar setup provides essentially infinite runtime. The battery serves as a buffer for nighttime and cloudy periods.

Measuring Power Consumption

To verify your optimizations are working, measure actual current draw:

Budget option (~$15): Use a USB power meter (like the YZXstudio ZY1280) between your power supply and the board. It shows real-time current and accumulated energy.

Precise option (~$30): Use a Nordic Power Profiler Kit II or a CurrentRanger. These can measure from microamps to hundreds of milliamps with high time resolution, letting you see exactly what happens during wake/sleep transitions.

Software estimation: ESP-IDF includes esp_pm_dump_locks() to see what’s preventing power saving, and esp_clk_tree_get_freq() to verify clock speeds are reduced during sleep.

Real-World Example: Mailbox Notifier

Here’s a complete real-world application combining deep sleep with AI intelligence:

A motion sensor in the mailbox detects when mail arrives. The ESP32-C3 wakes, connects to Wi-Fi, and sends a Telegram message: “You’ve got mail! Based on the time (2:15 PM), this is likely the regular postal delivery.”

Power consumption: ~5µA (waiting) + ~130mA for ~5 seconds (sending message) = average of ~15µA. A 1000mAh battery lasts over 7 years in theory (battery self-discharge becomes the limiting factor).

The AI adds value over a simple notification: it can learn patterns (“mail usually arrives between 2-3 PM on weekdays”), detect anomalies (“someone opened the mailbox at 11 PM — that’s unusual”), and correlate with other data (“you received a package notification from Amazon today, this might be it”).