SensorRig

ESP32-C3 Deep Sleep Current: What the Datasheet Doesn't Tell You About Your Dev Board

16 August 2026 · 8 min read

Hardware used in this build

  • ESP32-C3 dev board — Shed node MCU
    The shed node MCU. Runs the AI_optimized_shed_TX.ino sketch. Seeed's own board.
  • HC-12 433 MHz wireless module — Radio link shed <-> Pi 4
    HiLetgo HC-12 433 MHz SI4438 module with antenna. Reliable for 100–1 000 m links.
  • INA219 — Solar bus voltage + power
    Adafruit INA219 High Side DC Current Sensor Breakout. ±26 V, ±3.2 A, I2C. The one I use.
  • Solar panel + battery — Node power source

Full parts list & affiliate disclosure →

The ESP32-C3 datasheet specifies a deep-sleep current of approximately 5–7 µA with the RTC timer on (ESP32-C3 Technical Reference Manual, Section 3.5.3). On my Seeed Studio XIAO ESP32C3, that number is useless. My node is part of a 100-yard shed link running off a 12 V solar panel and a tractor battery, connected to the house over an HC-12 433 MHz serial radio, and the XIAO’s on-board components keep the MCU from ever approaching the silicon floor. This post breaks down exactly where those milliamps go, names the guilty parts, and explains how to isolate the leaks on your own bench.

What the datasheet actually specifies

The ESP32-C3 Technical Reference Manual (TRM) gives chip-level current figures for the VDD3P3_RTC_0 and VDD3P3_DIG_0 pins under Espressif’s own test conditions:

Sleep modeTypical current
Deep sleep, RTC on~5–7 µA
Deep sleep, RTC off~1 µA
Modem sleep~15 mA
Active, CPU @ 160 MHz~30 mA

Those figures are the silicon floor. They assume the chip alone, minimal peripherals, specific temperature and voltage corners. They are not a dev-board spec. Community measurements on bare ESP32-C3 modules corroborate the sub-10 µA range when the RTC domain is the only thing alive.

What your dev board adds

My shed node uses a Seeed Studio XIAO ESP32C3. The XIAO form factor adds several current paths that do not exist on the die. I identified four major ones by tracing the 3.3 V rail.

1. On-board LDO

The XIAO ESP32C3 uses a Torex XC6210 fixed 3.3 V LDO. The XC6210 datasheet specifies a quiescent current of 30–45 µA typical depending on load and temperature. That is already five to nine times the chip’s own deep-sleep spec before you attach a sensor or radio. The LDO draws this current simply to keep itself regulated — it does not care that the ESP32-C3 is asleep.

2. USB-to-serial bridge

The CH340C on the XIAO is always powered when USB is connected. Typical idle current for the CH340C is in the 1–2 mA range, with peaks up to ~8 mA under load when VCC is present and no serial communication is active. Disconnect USB and that path goes away — but then you cannot program the board without desoldering or reconnecting.

3. Power LED

Wired straight to the 3.3 V rail through a current-limiting resistor. A standard SMD green or red LED at 2.2 V forward drop across 3.3 V draws roughly 2–3 mA. It exists to tell you the board is alive. It also tells your battery the board is alive.

4. Peripherals you left floating

The DHT22 data pin, the HC-12 UART lines, the I2C bus — every GPIO that is not explicitly tri-stated or powered down can keep a peripheral in a partial-active state. The ESP32-C3 keeps GPIO state alive in deep sleep by default. A floating pin can keep a sensor biased.

A comparison of typical configurations:

ConfigurationEstimated deep-sleep currentSource
Bare ESP32-C3 module, RTC on, no peripherals~5–7 µA
XIAO ESP32C3 stock, USB disconnected~50–200 µALDO + LED + bridge leakage (XC6210/CH340C datasheets)
XIAO + DHT22 + HC-12, USB disconnectedDepends on GPIO state and HC-12 power modeMeasure your own node
Stock dev board with USB connected5–15 mACH340C dominates (datasheet + community)

The jump from ~7 µA to ~200 µA is the difference between a 18650 lasting 16 years and one lasting 7 months. At 10 mA — the stock XIAO with the USB bridge active — a 2,500 mAh 18650 is flat in 10 days.

How to measure it yourself

You need a shunt resistor and a differential ADC, or a multimeter with a µA range that does not burden the circuit. The burden voltage on a cheap meter’s µA range can be hundreds of millivolts — enough to collapse the ESP32-C3’s supply and force it out of deep sleep, which will give you a number that is too high.

The INA219 on the shed’s solar bus is useful for the whole-node budget, not for isolating the ESP32-C3. The INA219’s current-sense resolution depends on its programmable gain array (PGA) and calibration. In practice the smallest reliably resolvable step with a 0.01 Ω shunt is on the order of 0.1 mA (100 µA) with standard calibration, not the µA scale. Use it only to confirm you are in the right ballpark; for actual µA-scale numbers, use a dedicated low-offset shunt amplifier or a calibrated DMM on its µA range. If your meter reads unstable on µA, try mA — a jump means your meter burden was collapsing the node’s supply.

Battery 3.3V → shunt (0.01 Ω, 1 %) → [INA219](https://www.amazon.com/dp/B09CBSLXN7?tag=kayparpart-20) VIN+ → [INA219](https://www.amazon.com/dp/B09CBSLXN7?tag=kayparpart-20) VIN- → XIAO 3V3 pin
[INA219](https://www.amazon.com/dp/B09CBSLXN7?tag=kayparpart-20) GND → XIAO GND

A 0.01 Ω shunt gives 1 µV per µA. The INA219 cannot resolve that. Use it only to confirm you are in the right ballpark; for actual µA-scale numbers, use a dedicated low-offset shunt amplifier or a calibrated DMM on its µA range. If your meter reads unstable on µA, try mA — a jump means your meter burden was collapsing the node’s supply.

Safety note on the INA219: The INA219 is a high-side shunt monitor rated for up to 26 V common-mode. The shed’s solar rail can exceed 12 V under charge, and inductive spikes from the HC-12 or relay can push it higher. Keep the INA219 powered from the 3.3 V rail, not from the raw solar input, and respect the common-mode limit. If you move the shunt to the battery side, add transient suppression.

The deep-sleep sketch

The firmware running on the shed node uses esp_deep_sleep_start() after a single sensor read and radio burst:

#include <Arduino.h>
#include <Wire.h>
#include <DHT.h>

#define DHTPIN    0
#define DHTTYPE   DHT22
#define HC12_RX  20
#define HC12_TX  21
#define SLEEP_US 900000000ULL  // 15 minutes

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial1.begin(9600, SERIAL_8N1, HC12_RX, HC12_TX);
  dht.begin();
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  // Frame: <NODE_ID>,<SENSOR>,<VALUE>,<CRC8>
  Serial1.printf("SHD,%0.1f,%0.1f,0\n", h, t);
  Serial1.flush();

  // Power down the GPIO domain explicitly.
  // Leaving VDDSLIO alive keeps pins biased.
  esp_sleep_pd_config(ESP_PD_DOMAIN_VDDSLIO, ESP_PD_OPTION_OFF);
  esp_sleep_enable_timer_wakeup(SLEEP_US);
  esp_deep_sleep_start();
}

void loop() {
  // never reached
}

The esp_sleep_pd_config(ESP_PD_DOMAIN_VDDSLIO, ESP_PD_OPTION_OFF) line matters. By default the ESP32-C3 keeps GPIO state alive in deep sleep. Every pin that floats or drives a peripheral keeps that peripheral biased. On my node the difference is measurable but not yet quantified with a µA-class instrument.

Battery life math

This is where the measured number becomes load-bearing. The arithmetic is simple:

battery_life_hours = battery_capacity_mAh × 1000 / measured_sleep_current_µA

For an 18650 Li-ion (3,000 mAh nominal, ~2,400 mAh usable down to 20 %):

My shed node runs from a 12 V solar panel buffered by a tractor battery, with an INA219 logging bus voltage and power. The node’s steady-state idle current after all peripherals have settled is the residual between the HC-12 transmit burst and the DHT22 read cycle, measured from the battery side with the INA219 in high-resolution mode. At a 15-minute wake interval, runtime is calculated from your current battery capacity divided by that measured sleep current. The INA219 sees the HC-12’s transmit bursts plus the DHT22 read cycle. The deep-sleep baseline is the floor between bursts, and it is the only number that matters for long-term battery projection.

What went wrong

HC-12 TX burst brown-out. The HC-12 draws up to ~100 mA peak during transmit at AT+P8. My first LDO could not hold 3.3 V under that load. The ESP32-C3’s brown-out detector fired, the node reset, the sketch retransmitted, and the brown-out fired again. A 470 µF electrolytic across the 3.3 V rail ended a week of “random” resets. The lesson: your deep-sleep current is only half the story. Your peak current during sensor read + radio TX is what selects your capacitor and regulator.

Floating GPIO keeping peripherals alive. I left the DHT22 data pin floating when the ESP32-C3 entered deep sleep. The sensor’s internal pull-up was enough to keep it from sleeping fully. Explicitly powering down the DHT22 via a GPIO-controlled P-channel MOSFET removed that current. Without the MOSFET, the node’s idle current was measurably higher: the delta is the difference between the DHT22 powered and left floating during sleep, measured with the same shunt setup.

Forgetting the LED. The XIAO’s power LED is always on when USB is connected. If you ever plug the node into USB for debugging and forget to disconnect it before going off-grid, you just turned your 200 µA node into a 10 mA node. I logged the node current with USB connected but idle and compared it to USB disconnected; the difference is the LED plus any bridge leakage on the 3.3 V rail.

Auto-sleep assumption. The HC-12 does not sleep automatically. AT+DLOW reduces the module’s own draw, but the UART lines must still be driven. If the ESP32-C3 enters deep sleep while UART is active, the TX pin can hold the HC-12 in a partial-active state. Disconnect or tri-state the UART before sleeping, or use a GPIO to cut power to the HC-12 entirely.

The honest version

I do not have a single clean measurement for you yet. My shed node is in a wooden box on a 12 V solar rail with an INA219 logging bus voltage and power, and the ESP32-C3’s contribution is the residual after the HC-12 transmit burst and the DHT22 read cycle settles. That residual is measured from the battery side with the INA219 in high-resolution mode after all peripherals have gone idle.

What I do have is a method that isolates the variables:

  1. Shunt at the regulator output for the ESP32-C3 alone.
  2. Shunt at the battery for the whole node.
  3. Delta between idle and deep-sleep gives you the peripheral leakage.
  4. Datasheet for the chip itself (5–7 µA with RTC on, ESP32-C3 Technical Reference Manual Section 3.5.3).

Measure your own board. Report your own numbers. The 7 µA figure is real, but it belongs to the silicon die, not the plastic blob you bought on Amazon.

Related reading