Skip to content

Power Consumption Optimization

Power Consumption Optimization

This section covers detailed techniques for optimizing power consumption in the e-paper display project. While deep sleep provides the largest power savings, several additional optimizations can further extend battery life from months to over a year. After completing this section, you will be able to:

  • Measure and analyze the power budget of the ESP32 + e-paper system
  • Implement hardware and software optimizations for each power domain
  • Calculate expected battery life for different configurations
  • Make trade-off decisions between features and power consumption

Before starting this section, please ensure:

  • Deep sleep configuration is understood (see 02-08)
  • Battery management basics (see 02-09)
  • Access to a multimeter with µA resolution
ESP32 Power Consumption Breakdown
┌─────────────────────────────────────────────────────┐
│ TOTAL POWER │
│ │
│ ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
│ │ WiFi TX │ │ WiFi RX │ │ CPU + Peripherals │ │
│ │ ~200-260 │ │ ~100-130 │ │ ~20-50 mA │ │
│ │ mA │ │ mA │ │ │ │
│ └──────────┘ └──────────┘ └───────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
│ │ E-Paper │ │ E-Paper │ │ Deep Sleep │ │
│ │ Refresh │ │ Idle │ │ ~5-50 µA │ │
│ │ ~20-30mA │ │ ~0 µA │ │ │ │
│ └──────────┘ └──────────┘ └───────────────────┘ │
└─────────────────────────────────────────────────────┘

System current draw per state:

StateCurrentDurationEnergy per Cycle
WiFi connecting120 mA3 seconds0.100 mAh
MQTT data exchange80 mA1 second0.022 mAh
Display refresh25 mA3 seconds0.021 mAh
Deep sleep0.01 mA (10 µA)3593 seconds0.010 mAh
Total per cycle3600 seconds0.153 mAh

The display refresh uses less energy than WiFi connection! Optimizing WiFi connection time has the greatest impact on battery life.

Refresh IntervalCycles/YearEnergy/YearBattery Needed (1-year target)
Every 30 min17,5202,680 mAh~3,000 mAh
Every 1 hour8,7601,340 mAh~1,500 mAh
Every 2 hours4,380670 mAh~800 mAh
Every 6 hours1,460223 mAh~300 mAh
Every 12 hours730112 mAh~150 mAh
Once daily36556 mAh~100 mAh

WiFi connection is the largest energy consumer. Optimize it aggressively:

Before Optimization (standard connection):

// ~5-8 seconds, 120 mA average
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}

After Optimization (fast connection):

// Reduce connection attempts — doesn't need perfect RSSI
WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE);
WiFi.setAutoReconnect(false);
WiFi.setSleep(WIFI_PS_MIN_MODEM); // Modem sleep when idle
WiFi.begin(ssid, password);
// Timeout after 5 seconds — better to retry later than drain battery
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 10) {
delay(500);
attempts++;
}
if (WiFi.status() != WL_CONNECTED) {
// Skip this cycle — use cached data
Serial.println("WiFi timeout, skipping this cycle");
goToSleep();
return;
}

Optimization: Set a strict connection timeout and skip rather than retry indefinitely.

Before entering deep sleep, explicitly disable all peripherals:

void prepareForSleep() {
// Disable WiFi hardware
client.disconnect();
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
// Turn off display power
display.powerOff(); // GxEPD2 method
// Set all GPIOs to safe state
pinMode(EPD_CS, INPUT_PULLDOWN);
pinMode(EPD_DC, INPUT_PULLDOWN);
pinMode(EPD_RST, INPUT_PULLDOWN);
// Disable ADC if not used for battery monitoring
// adc_power_off();
// Bluetooth off
btStop();
}
void goToSleep() {
prepareForSleep();
esp_sleep_enable_timer_wakeup(SLEEP_INTERVAL_US);
esp_deep_sleep_start();
}

Optimize the display update sequence:

void updateDisplayOptimized() {
unsigned long start = millis();
// Fast init — skip full power-on sequence if possible
display.init(4000000, true, 10); // Higher SPI speed
// Use partial refresh if available (major time savings)
// Some displays support updating only a portion of the screen
// Minimize drawing operations
display.fillScreen(GxEPD_WHITE);
// Draw only the minimum content
display.setFont(&FreeMonoBold12pt7b);
display.setCursor(5, 20);
display.print(temperature);
// Single display() call — not multiple
display.display();
unsigned long elapsed = millis() - start;
Serial.print("Display update: ");
Serial.print(elapsed);
Serial.println("ms");
}
GPIO StateCurrent LeakageRecommendation
HIGH output~0 µA✅ Used for CS deselect
LOW output~0 µA✅ Safe for control pins
INPUT pulldown~1 µA✅ For unused pins
INPUT floating~10-50 µA❌ Avoid — unpredictable
// Safe GPIO configuration for sleep
void configureGpioForSleep() {
const int pins[] = {5, 17, 16, 4, 23, 18}; // All used pins
for (int pin : pins) {
gpio_set_direction((gpio_num_t)pin, GPIO_MODE_INPUT);
gpio_set_pull_mode((gpio_num_t)pin, GPIO_PULLDOWN_ONLY);
}
}

Higher SPI speed reduces active time:

// Standard speed
display.init(115200); // ~115kHz SPI — 3-5 second refresh
// Optimized speed
display.init(4000000); // ~4MHz SPI — 1-2 second refresh
// Max safe speed (depends on wiring quality)
display.init(8000000); // ~8MHz SPI — ~1 second refresh (requires short wires)

Caution: Very high SPI speeds may cause communication errors with long wires. Test stability at each speed.

Battery performance degrades in cold temperatures. Adjust the schedule accordingly:

void configureSleepInterval() {
// Read temperature from sensor
float temp = readTemperature();
unsigned long sleepUs;
if (temp < 0) {
// Very cold — battery degraded, update less frequently
sleepUs = 6 * 3600 * 1000000ULL; // Every 6 hours
} else if (temp < 10) {
// Cold — moderate degradation
sleepUs = 3 * 3600 * 1000000ULL; // Every 3 hours
} else {
// Normal temperature
sleepUs = 1 * 3600 * 1000000ULL; // Every 1 hour
}
esp_sleep_enable_timer_wakeup(sleepUs);
}
void setup() {
// 1. Fast boot — no unnecessary delays
Serial.begin(115200);
// 2. Quick WiFi connection
WiFi.mode(WIFI_STA);
WiFi.setSleep(WIFI_PS_MIN_MODEM);
// 3. Connect with strict timeout
WiFi.begin(ssid, password);
unsigned long timeout = millis() + 5000;
while (WiFi.status() != WL_CONNECTED && millis() < timeout) {
delay(100); // Short delay — not 500ms
}
if (WiFi.status() == WL_CONNECTED) {
// 4. Fast MQTT exchange
fetchAndDisplayData(); // ~2 seconds total
}
// 5. Clean shutdown
prepareForSleep();
// 6. Enter deep sleep
esp_sleep_enable_timer_wakeup(SLEEP_INTERVAL_US);
esp_deep_sleep_start();
}
Terminal window
# Measuring with multimeter (series connection)
# 1. Set multimeter to DC mA range
# 2. Disconnect USB power
# 3. Connect multimeter between battery and ESP32
# 4. Record values during each phase
# For µA measurement in sleep mode:
# 1. Switch to µA range
# 2. Ensure ESP32 has entered deep sleep (wait 5 seconds)
# 3. Record stable reading
Typical results (with all optimizations):
Active phase: ~120 mA for ~5 seconds (0.167 mAh)
Sleep phase: ~10 µA for 3595 seconds (0.010 mAh)
Total/cycle: 0.177 mAh
Daily: 4.25 mAh
Battery life: ~282 days with 1200 mAh battery
  • Active phase time is under 10 seconds
  • Deep sleep current is under 50 µA
  • WiFi disconnects properly before sleep
  • Display updates successfully even with fast boot
  • Battery life estimation matches actual measurements within 20%

Issue 1: Sleep Current Too High (>100 µA)

Section titled “Issue 1: Sleep Current Too High (>100 µA)”

Symptoms:

  • Battery drains faster than expected
  • Multimeter shows >100 µA in sleep

Checklist:

  • Are any external peripherals powered during sleep?
  • Is WiFi fully disabled? (WiFi.mode(WIFI_OFF))
  • Are all GPIOs in safe state? (no floating inputs)
  • Is the voltage regulator powered down?
  • Is the e-paper display’s power off? (display.powerOff())

Symptoms:

  • Active phase >15 seconds
  • WiFi connection takes >5 seconds

Solutions:

  • Reduce connection timeout
  • Use cached data if WiFi is slow
  • Increase SPI speed for display refresh
  • Use fast boot techniques
TechniqueSavingsEffortPriority
Deep sleep timer~99.9%Low⭐⭐⭐
WiFi timeout (5s max)~50% of WiFi energyLow⭐⭐⭐
Disconnect WiFi before sleep~10 µA savingsLow⭐⭐⭐
GPIO safe states~10-50 µAMedium⭐⭐
Increase SPI speed~50% display timeMedium⭐⭐
Disable Bluetooth~20 mA (if enabled)Low⭐⭐⭐
Lower CPU frequency~10 mA activeMedium
  1. WiFi connection dominates active power consumption — optimize connection time first
  2. Total active time should be under 5 seconds for optimal battery life
  3. Deep sleep current should be under 20 µA with proper configuration
  4. Every microamp matters — a 10 µA difference in sleep can change battery life by weeks
  5. With all optimizations: ~1 year battery life from a 1200 mAh battery with hourly updates

Target Audience: Alibaba.com IoT Pre-sales Engineers
Status: ✅ Completed