A D1 mini with a capacitive soil sensor is the start of every plant-watering project. The sensor’s AOUT goes to A0, the D1 mini’s only analog pin, and it is powered from 3V3.
A0 is where the D1 mini differs from a bare ESP8266 module: an on-board divider lets it read about 0–3.2 V instead of 0–1 V, so the sensor connects directly. The sketch averages a few readings and turns them into a percentage after a two-point calibration.
Wiring
| Wemos D1 mini | Capacitive soil moisture sensor v1.2 | Wire | Notes |
|---|---|---|---|
| 3V3 | VCC | red | From 3V3 so AOUT can never go above what A0 accepts. |
| GND | GND | black | |
| A0 | AOUT | yellow | The board’s 220 kΩ / 100 kΩ divider scales about 0–3.2 V down to the chip’s 0–1 V. |
3.3–5.5 V part, 3.3 V board. The output is an analog voltage that stays below the supply. Power it from 3.3 V on ESP32 and Pico so AOUT can never exceed the ADC input range; on an Uno 5 V is fine.
Board quirks
- The ESP8266 has one analog input. The bare chip reads 0–1 V; the D1 mini adds a 220 kΩ / 100 kΩ divider in front of it, so A0 on the header spans about 0–3.2 V → 0–1023. A second analog sensor needs an external ADC such as an ADS1115.
- Calibrate on your own sensor: note the raw value in dry air and in a glass of water (only up to the line on the board), and put them in
DRY_RAW/WET_RAW. Higher raw = drier. - Calling
analogRead(A0)back-to-back in a tight loop on the ESP8266 is known to knock Wi-Fi off. The sketch spaces its 8 samples 10 ms apart, which is plenty. - Many cheap “v1.2” boards are missing the regulator’s supporting parts or have the 555 timer swapped for a part that needs 5 V. If the reading barely changes between dry and wet at 3.3 V, the board is faulty — not your code.
- Never put the sensor above the line marked on the PCB, and seal the top edge with nail polish or heat-shrink before the monsoon — water on the electronics drifts the reading.
Code
// Capacitive soil moisture sensor (v1.2) on a Wemos D1 mini (ESP8266).
// VCC → 3V3, GND → GND, AOUT → A0. The D1 mini's A0 divider reads about 0-3.2 V as 0-1023.
// Calibrate: note the raw value in dry air and in a glass of water, and put them below.
const int DRY_RAW = 760; // sensor in dry air (yours will differ)
const int WET_RAW = 380; // sensor in water up to the line
int readAveraged() {
long sum = 0;
for (int i = 0; i < 8; i++) {
sum += analogRead(A0);
delay(10); // don't hammer the ADC: back-to-back analogRead() calls can drop Wi-Fi
}
return sum / 8;
}
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println("Soil sensor on A0 - raw 0-1023 (about 0-3.2 V)");
}
void loop() {
int raw = readAveraged();
int pct = map(raw, DRY_RAW, WET_RAW, 0, 100);
pct = constrain(pct, 0, 100);
Serial.printf("Raw %d (%.2f V) Moisture %d %%\n", raw, raw * 3.2f / 1023.0f, pct);
delay(2000);
}// Capacitive soil moisture sensor (v1.2) on a Wemos D1 mini (ESP8266).
// VCC → 3V3, GND → GND, AOUT → A0. The D1 mini's A0 divider reads about 0-3.2 V as 0-1023.
// Calibrate: note the raw value in dry air and in a glass of water, and put them below.
const int DRY_RAW = 760; // sensor in dry air (yours will differ)
const int WET_RAW = 380; // sensor in water up to the line
int readAveraged() {
long sum = 0;
for (int i = 0; i < 8; i++) {
sum += analogRead(A0);
delay(10); // don't hammer the ADC: back-to-back analogRead() calls can drop Wi-Fi
}
return sum / 8;
}
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println("Soil sensor on A0 - raw 0-1023 (about 0-3.2 V)");
}
void loop() {
int raw = readAveraged();
int pct = map(raw, DRY_RAW, WET_RAW, 0, 100);
pct = constrain(pct, 0, 100);
Serial.printf("Raw %d (%.2f V) Moisture %d %%\n", raw, raw * 3.2f / 1023.0f, pct);
delay(2000);
}Expected serial output
Soil sensor on A0 - raw 0-1023 (about 0-3.2 V)
Raw 742 (2.32 V) Moisture 5 %
Raw 511 (1.60 V) Moisture 66 %
Raw 498 (1.56 V) Moisture 69 %Soil sensor on A0 - raw 0-1023 (about 0-3.2 V) Raw 742 (2.32 V) Moisture 5 % Raw 511 (1.60 V) Moisture 66 % Raw 498 (1.56 V) Moisture 69 %
Common errors
Reading stuck at 1023
AOUT is above about 3.2 V — the sensor is powered from 5V. Move VCC to 3V3.
Reading stuck near 0
AOUT isn’t connected, or the sensor isn’t powered. Check the GND and VCC wires.
Percentage over 100 or under 0
Your dry/wet calibration doesn’t match this sensor. Re-measure and update DRY_RAW and WET_RAW; the sketch clamps the result to 0–100.