The microcontroller core is rarely the dominant power consumer in an embedded system. Sensors, radios, displays, and communication buses often draw far more. This chapter covers strategies for managing these peripherals to minimize power consumption without sacrificing functionality.
Before optimizing, audit what each component actually draws. A typical IoT sensor node might look like:
| Component | Active Current | Standby Current |
|---|---|---|
| ESP32 core | 30–80 mA | 10 µA (deep sleep) |
| WiFi radio | 160–260 mA (TX burst) | 0 (off) |
| BME280 (temp/humidity) | 3.6 µA (sampling) | 0.1 µA |
| SSD1306 OLED (128×64) | 20–30 mA | 10 µA |
| SIM800L (GSM modem) | 500–2000 mA (TX) | 1 mA (idle) |
The OLED and GSM modem standby currents are significant even when not actively used. If the device spends most of its time sleeping, these standby currents can become the dominant power consumers.
Most sensors have a measurement cycle: power on, wait for stabilization, take reading, power off. The stabilization time (warm-up) is the key constraint.
Temperature/humidity sensors (DHT22, SHT31): DHT22 stabilizes in ~2 s after power-on. If sampling every 60 s, the sensor only needs power for 2 s out of 60 — a 3.3% duty cycle.
Gas sensors (MQ series): These require a 24–48 hour burn-in for calibration and a 20-second pre-heat before each reading. They draw 100–200 mA during preheat — making them unsuitable for battery operation without careful duty-cycle design.
Control via GPIO load switch:
# MicroPython: power-cycle a sensor on a GPIO-controlled switch
import machine, time
SENSOR_PWR = machine.Pin(14, machine.Pin.OUT)
def read_sensor():
SENSOR_PWR.value(1) # power on
time.sleep_ms(100) # stabilization
# ... read I2C/SPI/UART data ...
SENSOR_PWR.value(0) # power off
return reading
WiFi is the single largest power consumer in most ESP32 projects. Key strategies:
Use static IP instead of DHCP: DHCP negotiation adds 500–1000 ms to connection time, during which the radio draws ~100 mA. Configuring a static IP reduces connection time to ~300–500 ms.
Reduce transmit power: The ESP32 transmits at up to 20 dBm. For short-range applications (same room as the router), 10–13 dBm is sufficient and reduces TX current from ~260 mA to ~180 mA.
import network
sta = network.WLAN(network.STA_IF)
sta.active(True)
sta.config(txpower=13) # dBm
Use MQTT instead of HTTP: An MQTT publish after connection is one round-trip packet. HTTP adds TLS handshake, headers, and acknowledgment overhead. For small payloads, MQTT reduces active time by 50–80%.
Always disconnect before sleep: Failing to call sta.disconnect() and sta.active(False) before deep sleep leaves the radio partially active during the sleep entry sequence.
BLE (Bluetooth Low Energy) is designed for low-power operation. A BLE advertisement packet can be sent in ~1.5 ms at ~15 mA — compared to WiFi’s 300–500 ms connection + transmission cycle at 100–260 mA.
For applications where a phone or gateway acts as the receiver, BLE advertising is often more power-efficient than WiFi, especially for short payloads.
Trade-offs:
For indoor sensor nodes near a phone or dedicated BLE gateway, BLE is typically 10–50× more power-efficient than WiFi.
OLED and LCD displays are significant power consumers for battery devices. Strategies:
Turn off the display during sleep: Even in display-off mode, many OLEDs draw 1–5 mA through the charge pump. Use the display’s power-down command or cut power via a load switch.
Reduce brightness: OLED power consumption scales roughly linearly with the number of lit pixels and brightness level. A fully bright white screen draws ~30 mA; the same content at half brightness draws ~15 mA.
Display only when needed: Use a motion sensor, button press, or proximity sensor to wake the display only when a user is present. This can reduce average display power from 20 mA to 0.1 mA or less.
SPI, I2C, and UART hold clock lines and pull resistors active even when not in use.
uart.deinit() in MicroPython before sleeping.For critical low-power designs, consider cutting the entire sensor power domain (VCC) via a load switch. This guarantees zero current from all sensors, pull resistors, and any leakage paths through the bus.
| ← Chapter 5: Arduino and AVR Sleep Modes | Table of Contents | Chapter 7: Laptop CPU Governors and TLP → |