Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

Capacitive soil moisture sensor with Wemos D1 mini (A0)

Read a capacitive soil moisture sensor on the Wemos D1 mini’s A0 pin, which spans about 0–3.2 V, and calibrate dry and wet values into a moisture percentage.

Arduino C++Verified — core esp8266 3.1.2, 3 Nov 2026Compile-only

Community draft — report a mistake

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 miniOnly the pins used are shown · 3.3 V logicCapacitive soil moisture sensor v1.2A03V3GNDGNDVCCAOUT
Every connection
Wemos D1 miniCapacitive soil moisture sensor v1.2WireNotes
3V3VCCredFrom 3V3 so AOUT can never go above what A0 accepts.
GNDGNDblack
A0AOUTyellowThe 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

soil-moisture-d1mini.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// 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

Serial Monitor · 115200Output
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.

↑↓ to move · Enter to open