A capacitive soil-moisture sensor is one of the easiest ways to make an ESP32 irrigation system smarter, but the raw analogue value is not a universal “soil moisture percentage”. These inexpensive probes measure changes in capacitance caused largely by the dielectric properties of the surrounding soil. The reading depends on the sensor design, supply voltage, soil type, salinity, mounting depth and even how tightly the soil is packed around the probe.
The right approach is therefore:
Read stable analogue voltage
→ calibrate in your own soil
→ filter noise
→ publish a relative 0–100% moisture value
→ use thresholds with hysteresis
→ let Home Assistant decide whether watering is needed
This guide uses a classic ESP32 with ESPHome, but the same method works with ESP32-C3, C6 and S3 boards as long as you choose a suitable ADC pin.
Capacitive vs Resistive Soil Sensors
| Feature | Resistive probe | Capacitive probe |
|---|---|---|
| Measurement principle | Electrical conductivity/resistance through soil | Capacitance / dielectric change |
| Exposed metal electrodes | Usually yes | Usually no |
| Electrode corrosion | Common | Much lower |
| Influence of soil salts | High | Still present, but generally less direct |
| Long-term installation | Poor unless carefully managed | Better |
| Typical output | Analogue or comparator | Analogue voltage |
Seeed describes its capacitive sensor as corrosion-resistant because the metal electrodes do not need direct exposure to the soil. It also explicitly warns that the sensor is intended for qualitative moisture measurement rather than laboratory-grade quantitative volumetric water content.
For garden automation, that is normally fine. You rarely need to know that the soil contains exactly 23.7% volumetric water. You need to know whether a particular bed is dry enough to justify irrigation.
What the Sensor Actually Measures
Water has a much higher dielectric constant than dry soil and air. A capacitive probe detects how its electric field changes as the water content around the sensing section changes.
On many common analogue probes:
Dry soil → higher output voltage
Wet soil → lower output voltage
That direction is common but not universal, so test the actual sensor before writing automation logic.
Do not interpret its percentage as an absolute agronomic VWC measurement unless the sensor has been characterised for that purpose. Industrial soil probes use more controlled electronics, calibration and often temperature/electrical-conductivity compensation.
Typical Wiring to ESP32
For a 3.3 V-compatible analogue capacitive sensor:
| Sensor | ESP32 |
|---|---|
| VCC | 3.3 V |
| GND | GND |
| AO / SIG | ADC1 pin such as GPIO34 |
On the classic ESP32, GPIO34 is a convenient ADC1 input and is input-only, so it cannot accidentally drive the sensor output.
If your module is specified for 5 V operation, do not assume its analogue output is automatically safe for a 3.3 V ESP32 ADC. Measure the maximum output voltage or use the manufacturer’s specification. A sensor powered at 5 V can potentially output more voltage than the ESP32 should receive.
Why ADC1 Is Usually the Better Choice
On the original ESP32, ADC1 pins are generally the least troublesome choice for analogue sensors. Older Arduino/ESP-IDF combinations historically had restrictions around ADC2 while Wi-Fi was active, and ADC behaviour differs across newer ESP32 variants.
The practical rule is simple: check the pinout for your exact ESP32 and choose an ADC pin that is not reserved for flash, PSRAM, USB or boot strapping.
For ESP32-C3 XIAO, for example, our XIAO ESP32-C3 pinout guide recommends the ADC1 pins over the board’s ADC2-labelled A3 input.
ESPHome ADC Configuration
sensor:
- platform: adc
pin: GPIO34
id: soil_voltage
name: "Soil Moisture Voltage"
attenuation: auto
update_interval: 5s
entity_category: diagnostic
Current ESPHome supports attenuation: auto, which combines the available ESP32 attenuation ranges automatically. ESPHome notes that its usable measured range is approximately 0.075 V to 3.12 V in its tests, with exact limits varying between chips.
This is another reason to run the sensor from 3.3 V where possible and confirm the actual output range before connecting it permanently.
Do Not Start by Mapping Air and Water to 0% and 100%
A lot of tutorials calibrate a probe like this:
sensor in air = 0%
sensor in water = 100%
That is useful as a quick functional test, but it is not the best irrigation calibration. Your plant does not live in air or a glass of water.
A better two-point calibration is:
- Install the sensor at its real depth and orientation.
- Let the soil dry to the point where you genuinely want irrigation to start.
- Record the stable sensor voltage. Call that your practical 0% or dry threshold.
- Water the soil thoroughly and allow excess water to drain.
- Wait until the root zone reaches a stable wet condition rather than measuring during a puddle.
- Record that voltage as your practical 100% reference.
This produces a percentage that actually means something for your garden.
Example Calibration
Suppose your installed probe measures:
Dry irrigation threshold: 2.62 V
Wet drained soil: 1.38 V
Because the voltage decreases as moisture increases, map the values in reverse:
filters:
- calibrate_linear:
- 2.62 -> 0
- 1.38 -> 100
- clamp:
min_value: 0
max_value: 100
ESPHome’s calibrate_linear filter is designed specifically to convert known measured sensor values into useful engineering values.
Full Calibrated ESPHome Sensor
sensor:
- platform: adc
pin: GPIO34
name: "Garden Soil Moisture"
id: garden_soil_moisture
attenuation: auto
update_interval: 5s
filters:
- median:
window_size: 7
send_every: 3
send_first_at: 3
- calibrate_linear:
- 2.62 -> 0
- 1.38 -> 100
- clamp:
min_value: 0
max_value: 100
- round: 1
unit_of_measurement: "%"
device_class: moisture
state_class: measurement
accuracy_decimals: 1
The calibration values above are examples only. Replace them with your own dry and wet readings.
Why Use a Median Filter?
Analogue soil sensors can produce occasional spikes from Wi-Fi activity, supply noise, long cables or ADC variation.
A median filter is useful because it rejects isolated outliers without averaging one huge bad reading into the result. ESPHome’s current median filter keeps a rolling window and publishes the median at the selected interval.
For a slowly changing quantity such as soil moisture, there is little reason to publish every noisy five-second ADC sample directly to Home Assistant.
Moving Average Is Another Good Option
If the sensor is noisy but does not produce sharp isolated spikes, use:
- sliding_window_moving_average:
window_size: 12
send_every: 12
With a five-second update interval, that publishes one one-minute average.
Do not over-filter. A one-hour moving average will make the graph pretty but can hide the important transition immediately after irrigation.
Power the Sensor Only When Measuring
A capacitive sensor does not suffer exposed-electrode electrolysis in the same way as a cheap resistive fork, but permanent outdoor power is still not always ideal. Low-cost boards can absorb moisture around PCB edges and components, drift with temperature, or corrode around unprotected circuitry.
Duty-cycling the sensor also saves power on a battery node.
For a robust design, switch the sensor supply using a small MOSFET/load switch rather than assuming every sensor can be powered directly from an ESP32 GPIO.
ESP32 GPIO
|
MOSFET / load switch
|
3.3 V → soil sensor
sensor output → ESP32 ADC
Then the sequence is:
sensor power ON
wait for circuit to settle
take several ADC readings
publish filtered value
sensor power OFF
Simple ESPHome Power-Switch Concept
If your hardware includes a MOSFET/load switch controlled by GPIO25:
switch:
- platform: gpio
pin: GPIO25
id: soil_sensor_power
internal: true
restore_mode: ALWAYS_OFF
sensor:
- platform: adc
pin: GPIO34
id: soil_adc
attenuation: auto
update_interval: never
You can then use an ESPHome interval/script to enable power, allow a short settling period, trigger the ADC update and switch the probe off again. The exact settling time depends on the sensor electronics, so measure it rather than assuming every capacitive board stabilises in the same 50 ms.
Cheap “Capacitive v1.2” Sensors Are Not Waterproof
The sensing blade may be coated, but the electronics at the top of many inexpensive PCB probes are exposed.
Do not bury the entire board. Insert only the intended sensing area and keep:
- Components above the soil line.
- Cable solder joints dry.
- Connector away from irrigation spray.
- PCB edges protected where practical.
Seeed gives the same warning for its Grove capacitive probe: do not insert the sensor beyond the marked maximum soil line.
Conformal Coating and Epoxy
For a permanent DIY installation, you can protect the exposed component area and PCB edges with suitable conformal coating or potting material, while keeping connectors and intentionally exposed sensing surfaces appropriate to the sensor design.
Any coating near the capacitive sensing region changes the dielectric environment slightly, so calibrate after the final waterproofing treatment, not before.
If you need a sensor that can genuinely remain buried outdoors for years, use a purpose-built waterproof or industrial probe rather than expecting a £2 exposed PCB to behave like an IP68 agricultural sensor.
Sensor Placement Matters More Than People Expect
A perfectly calibrated sensor in the wrong place produces useless irrigation decisions.
Place the probe:
- Inside the active root zone.
- At a representative depth.
- Away from a dripper’s immediate wet spot.
- Away from roof runoff.
- Not directly beside a retaining wall or concrete edge that dries differently.
- In soil representative of the irrigation zone.
For lawn, the useful root-zone depth may be very different from a deep shrub or tree bed. One sensor cannot automatically represent every plant in the garden.
Use More Than One Sensor for Large Zones
If one irrigation zone contains different soil or exposure conditions, consider two or three sensors and make the watering decision from a robust aggregate.
For example, use the median of three bed sensors rather than allowing one unusually wet probe beside a dripper to suppress irrigation for the entire zone.
Home Assistant is a good place to create this aggregate because it already receives all the sensor entities.
Do Not Use One Exact Threshold
A rule like:
if moisture < 35:
water
else:
stop
can chatter if the reading sits around 35%.
Use hysteresis instead:
Below 30% → soil considered dry
Above 45% → soil considered wet
30–45% → keep previous state / no new decision
Even better, use moisture to decide whether a scheduled irrigation cycle is allowed to start rather than switching water on and off every time the ADC moves by one percent.
Home Assistant Irrigation Condition
With the ESP32 Smart Irrigation Controller from the previous guide, Home Assistant can start the irrigation cycle only when the soil is dry:
alias: Garden Irrigation - Moisture Controlled
triggers:
- trigger: time
at: "05:30:00"
conditions:
- condition: numeric_state
entity_id: sensor.garden_soil_moisture
below: 30
- condition: state
entity_id: binary_sensor.irrigation_rain_sensor
state: "off"
actions:
- action: switch.turn_on
target:
entity_id: switch.irrigation_cycle
mode: single
This is much safer than allowing an analogue sensor to control a valve continuously. If the sensor fails, the worst case is usually a skipped scheduled cycle rather than an uncontrolled open valve.
Add a Sensor-Failure Check
A disconnected analogue sensor may produce a value that looks extremely dry or extremely wet depending on the ADC input and board.
Before relying on it for irrigation, establish the normal electrical range. For example, if the calibrated sensor should always operate between 1.2 and 2.8 V, values outside that range can indicate a wiring fault.
ESPHome can expose the raw voltage as a diagnostic entity while publishing the calibrated percentage separately. That makes debugging much easier.
Raw Voltage + Calibrated Percentage
sensor:
- platform: adc
pin: GPIO34
id: soil_raw
name: "Soil Sensor Voltage"
attenuation: auto
update_interval: 10s
entity_category: diagnostic
filters:
- median:
window_size: 5
send_every: 1
- platform: copy
source_id: soil_raw
name: "Soil Moisture"
filters:
- calibrate_linear:
- 2.62 -> 0
- 1.38 -> 100
- clamp:
min_value: 0
max_value: 100
- round: 1
unit_of_measurement: "%"
device_class: moisture
state_class: measurement
This gives you both the engineering diagnostic and the friendly Home Assistant percentage.
Long Sensor Cables
An analogue signal running several metres through a garden is much more vulnerable to noise and voltage drop than a short cable inside a plant pot.
For longer runs:
- Use a shared solid ground.
- Keep the analogue wire away from pumps, solenoid-valve cables and mains wiring.
- Use twisted/shielded cable where appropriate.
- Filter readings.
- Consider putting the ESP32/ADC closer to the probes.
- For genuinely long agricultural runs, use a digital/RS-485 industrial probe instead.
When an ADS1115 Helps
The built-in ESP32 ADC is good enough for ordinary irrigation thresholds, but an external ADS1115 can help when you want:
- Several analogue probes.
- Better repeatability/resolution.
- A cleaner analogue front end.
- Differential measurements for other sensors.
See our ADS1115 with ESPHome: Gain, Differential Inputs and Calibration guide.
Remember that an ADS1115 does not magically fix a poor sensor or bad placement. It only measures the electrical output more precisely.
Battery-Powered Soil Sensor Node
A garden probe is well suited to deep-sleep operation because soil moisture changes slowly.
A battery node can:
wake every 15 minutes
→ power sensor
→ wait for stabilisation
→ take several readings
→ connect to Wi-Fi
→ publish moisture
→ sleep
There is usually no benefit in sampling soil moisture every second for Home Assistant. A 10–30 minute interval is enough for most gardens and saves enormous battery power.
The XIAO ESP32-C6 and XIAO ESP32-S3 are attractive battery platforms because their boards include lithium charging; see our XIAO ESP32-C6 and XIAO ESP32-S3 guides.
Common Problems
| Symptom | Likely cause / first check |
|---|---|
| Percentage is backwards | Reverse dry/wet calibration points |
| Always reads 100% | ADC input saturated or wet calibration incorrect |
| Always reads 0% | Disconnected signal, dry calibration or wrong ADC pin |
| Reading jumps when Wi-Fi transmits | Supply/ADC noise; add median/average filtering |
| Different soil gives different percentage | Normal for cheap relative capacitive probes; recalibrate |
| Sensor works for months then drifts | Moisture ingress, PCB edge corrosion or soil/placement change |
| Works indoors but fails outdoors | Electronics not waterproof |
| One sensor says wet while plants are dry | Probe placed too close to dripper or wrong depth |
| ADC voltage above expected range | Check sensor supply/output before reconnecting ESP32 |
| Irrigation toggles repeatedly near threshold | Add hysteresis and schedule-based logic |
Recommended Setup for Home Assistant Irrigation
For a practical garden, I would use:
- A capacitive probe installed permanently at representative root depth.
- 3.3 V supply if the module supports it.
- ESP32 ADC1 input.
- Median filtering.
- Calibration in the actual soil after installation.
- Raw-voltage diagnostic entity.
- Calibrated relative percentage for dashboards.
- Moisture used as a condition to permit/skip scheduled irrigation.
- Physical rain sensor as a separate lockout.
- ESPHome sprinkler controller handling actual valve timing locally.
That gives you a useful smart-irrigation signal without pretending a low-cost analogue PCB is a laboratory soil-water instrument.
Related Smart Garden Guides
- ESP32 Smart Irrigation Controller with ESPHome and Home Assistant — multi-zone valves, pump logic, rain lockout and schedules.
- ADS1115 with ESPHome — higher-resolution analogue measurements and calibration.
- ESP32 Water Meter for Home Assistant — measure actual irrigation flow and total water use.
- ESP32 Water Tank Level Monitor — tank level interlock for stored-water irrigation.
Official and Reference Resources
- ESPHome ADC Sensor — ESP32 attenuation, voltage range and ADC setup.
- ESPHome Sensor Filters — calibrate_linear, clamp, median and averaging filters.
- Seeed Grove Capacitive Moisture Sensor — capacitive principle, corrosion resistance and qualitative measurement warning.
- DFRobot Waterproof Capacitive Soil Moisture Sensor — example of a purpose-built waterproof analogue capacitive probe.