Battery-Powered Soil Sensor with ESP32-C6 and ESPHome
Build a wireless soil moisture sensor that runs for over a year on three AA batteries using the ESP32-C6's 7µA deep sleep mode and ESPHome. This guide covers wiring, deep sleep configuration, battery life calculations, and Home Assistant integration for garden automation.
What You Need
Why the ESP32-C6 for Battery Sensors
The ESP32-C6 draws just 7µA in deep sleep — matching the ESP32-S3 but adding WiFi 6 and Thread support, and dramatically less than the classic ESP32's 10uA.
The C6's WiFi 6 support adds another efficiency advantage. Target Wake Time (TWT) lets the access point schedule exactly when the ESP32 checks in, eliminating wasted radio-on time. Combined with the RISC-V low-power co-processor that can monitor GPIO pins without waking the main core, the C6 is purpose-built for battery-powered sensor networks.
For a soil moisture sensor that wakes every 30 minutes, reads an ADC value, transmits over WiFi, and returns to deep sleep, the average current draw is approximately 150uA. Three AA batteries (2500mAh at 3.6V via LDO) provide roughly 16,000 hours — over 1.8 years of operation.
Step-by-Step Instructions
-
Step 1 Create ESPHome YAML Config
Start with a new ESPHome device configuration. In Home Assistant, go to the ESPHome dashboard and create a new device. Select ESP32-C6 as the board type and set the framework to esp-idf (the Arduino framework does not fully support the C6 yet).
The base YAML defines the WiFi connection, API key, and OTA update password. Set the WiFi power_save_mode to LIGHT for battery operation — this reduces WiFi radio-on time by 30-40% compared to the default NONE setting.
esphome: name: soil-sensor-garden platform: ESP32 board: esp32-c6-devkitc-1
wifi: ssid: !secret wifi_ssid password: !secret wifi_password power_save_mode: LIGHT
Tip: Use a static IP address in your WiFi config to skip DHCP negotiation — this saves 1-3 seconds of radio-on time per wake cycle. -
Step 2 Configure Deep Sleep with 30-Minute Wake Cycles
Add the deep_sleep component to your YAML. Set the sleep duration to 30 minutes (1800 seconds). The run_duration controls how long the ESP32 stays awake to read sensors and transmit data — 30 seconds is generous for a single sensor reading.
deep_sleep: run_duration: 30s sleep_duration: 30min
During the 30-second wake window, ESPHome reads all sensors, connects to WiFi, pushes values to Home Assistant via the native API, and checks for OTA updates. If no OTA is pending, it returns to deep sleep where the C6 draws just 7µA.
For critical applications like frost monitoring, add a GPIO wake source so an external comparator circuit can wake the ESP32 immediately when temperature drops below a threshold, independent of the 30-minute schedule.
Tip: Set run_duration to 60 seconds during initial setup to give yourself time for OTA updates. Reduce to 30 seconds once the config is stable. -
Step 3 Wire Capacitive Soil Moisture Sensor to ADC
Connect a capacitive soil moisture sensor (v1.2 or v2.0) to the ESP32-C6. Wire the sensor's AOUT pin to GPIO 0 (ADC1 channel 0). Connect VCC to a GPIO pin (such as GPIO 2) rather than directly to 3.3V — this lets you power the sensor only during readings to save battery.
In ESPHome, configure the sensor as an ADC input with a power management switch:
switch: - platform: gpio pin: GPIO2 id: sensor_power restore_mode: ALWAYS_OFF
sensor: - platform: adc pin: GPIO0 name: "Soil Moisture" update_interval: never attenuation: 11db id: soil_adc
The attenuation of 11dB sets the ADC input range to 0-3.1V, matching the capacitive sensor's output range. The update_interval is set to never because we trigger readings manually in an automation that powers the sensor, waits 500ms for stabilization, reads the value, and powers off.
Tip: Capacitive sensors are preferred over resistive probes — they do not corrode in soil and last years without degradation. -
Step 4 Calculate Battery Life
The battery life calculation has three components: deep sleep current, active current, and wake frequency.
Deep sleep: 7µA continuous. Over 30 minutes, that is 7µA times 0.5 hours = 3.5µAh per cycle.
Active phase: WiFi transmission on the C6 draws approximately 240mA peak, with an average of about 120mA over the 10-second active window (including sensor warmup, ADC read, WiFi connect, data push). That is 120mA times 10/3600 hours = 0.33mAh per cycle.
Total per cycle: 0.33mAh + 0.0035mAh = 0.3335mAh. With 48 cycles per day, daily consumption is approximately 16mAh.
Three AA lithium batteries (Energizer Ultimate Lithium, 3000mAh at 1.5V each, 4.5V total through a 3.3V LDO) provide about 3000mAh usable capacity. At 16mAh per day, that is 187 days — roughly 6 months. Switch to a 3.7V 18650 LiPo cell (3500mAh) for 218 days, or add a small 5V solar panel with a TP4056 charge controller for indefinite operation.
Tip: Use lithium AA cells instead of alkaline — they maintain voltage better in cold weather and have a flatter discharge curve. -
Step 5 Flash and Test
Connect the ESP32-C6 via USB-C and flash the firmware from the ESPHome dashboard. The initial flash must be done over USB — subsequent updates use OTA during the wake window.
After flashing, monitor the logs in ESPHome to verify the wake cycle. You should see the sensor power on, the ADC reading, the WiFi connection, the Home Assistant API sync, and then the deep sleep entry. The entire active phase should take 8-15 seconds.
Calibrate the soil moisture sensor by recording the raw ADC value in dry air (typically 2.8-3.1V) and in a glass of water (typically 1.0-1.5V). Use these values to create a linear calibration in ESPHome that maps the raw voltage to a 0-100% moisture percentage.
Tip: Wrap the sensor electronics (not the probe) in heat shrink tubing or conformal coating to protect against condensation in outdoor installations. -
Step 6 Add to Home Assistant
The ESPHome device appears automatically in Home Assistant under Settings, then Devices and Services. Accept the integration and the soil moisture sensor entity is immediately available for dashboards and automations.
Create an automation that sends a notification when soil moisture drops below 30% — this indicates the plant needs watering. For a garden automation, use the soil moisture reading to trigger a smart irrigation valve via a Zigbee or WiFi relay.
Set up a history graph in your Home Assistant dashboard to track moisture trends over days and weeks. This data helps you understand each plant's watering needs and optimize irrigation schedules. The 30-minute update interval provides sufficient resolution for soil moisture, which changes slowly over hours.
Frequently Asked Questions
How do I calibrate a capacitive soil moisture sensor?
Record the raw ADC voltage in dry air (your 0% baseline, typically 2.8-3.1V) and submerged in water (your 100% baseline, typically 1.0-1.5V). Use ESPHome's calibrate_linear filter to map these two points to a 0-100% scale. Re-calibrate if you change soil types.
What batteries should I use for an ESP32-C6 sensor?
Three AA lithium batteries (Energizer Ultimate Lithium) deliver 4.5V through a 3.3V LDO regulator, lasting 6+ months with 30-minute wake cycles. For longer life, use a 3.7V 18650 LiPo with a solar panel and TP4056 charger for indefinite operation.
Does WiFi 6 on the ESP32-C6 improve battery life?
Yes. WiFi 6's Target Wake Time (TWT) lets the access point schedule data exchanges, reducing unnecessary radio-on time. Combined with the C6's 7µA deep sleep, TWT can reduce average power consumption by 15-25% compared to WiFi 4 on the classic ESP32, depending on your router's WiFi 6 support.
Can I add a solar panel for indefinite battery life?
Yes. A small 5V 1W solar panel with a TP4056 charge controller and 3.7V 18650 LiPo cell provides indefinite operation. The sensor draws only 16mAh per day, and even a cloudy day produces 50-100mAh from a 1W panel. Mount the panel facing south at a 30-45 degree angle.
How many soil sensors can I run on one Home Assistant instance?
Home Assistant handles hundreds of ESPHome devices without performance issues. The practical limit is your WiFi network — most consumer routers support 30-50 concurrent devices. For larger sensor networks (50+ nodes), consider Thread mesh networking with an ESP32-C6 border router.
Can I use the ESP32-C3 instead of the C6 for this project?
Yes, the ESP32-C3 works with ESPHome for soil sensing. The ESP32-C3 draws 5µA in deep sleep — 2µA less than the C6's 7µA. Choose the C3 for absolute minimum power draw; choose the C6 for WiFi 6 and Thread support.
What is the range of a capacitive soil moisture sensor?
Capacitive soil sensors detect moisture in a roughly 3cm radius around the probe. Insert the probe vertically with the sensing area at root depth — typically 5-10cm for garden plants, 15-20cm for shrubs. Each sensor monitors one plant or a small cluster of plants with similar water needs.