A capacitive soil sensor doesn’t corrode like the two-prong resistive kind, which matters for anything left in a pot through the monsoon. On the SuperMini it is a one-pin job — but the C3’s ADC has limits worth knowing.
Wire AOUT to GPIO3, power from 3V3, then calibrate: note the millivolts in dry air and in water and put them in DRY_MV and WET_MV. The sketch averages 16 readings to tame noise.
Wiring
| ESP32-C3 SuperMini | Capacitive soil moisture sensor v1.2 | Wire | Notes |
|---|---|---|---|
| 3V3 | VCC | red | At 3.3 V the output stays inside the C3’s ADC range. |
| GND | GND | black | |
| 3 | AOUT | yellow | GPIO3 = ADC1_CH3. |
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
- Use GPIO0–4 for analog on the C3. GPIO5 is ADC2, which Espressif’s errata say not to use for readings.
- The C3’s ADC measures up to roughly 2.5 V; anything higher reads as full scale. Powering the sensor from 3V3 keeps its output (about 1.0–2.3 V) inside that window. Powered from 5 V, dry readings can saturate.
- Some cheap “v2.0” boards use an NE555 instead of a TLC555 and don’t work at 3.3 V — the reading barely changes. Look for “TLC555” or “555C” on the chip.
analogReadMilliVolts()uses the chip’s factory calibration, so the dry/wet numbers stay the same across boards better than raw counts.
Code
// Capacitive soil moisture sensor (v1.2/v2.0) on an ESP32-C3 SuperMini.
// VCC → 3V3, GND → GND, AOUT → GPIO3 (ADC1). Only GPIO0–4 are reliable for analog on the C3,
// and its ADC reads up to about 2.5 V — the sensor's output at 3.3 V stays inside that.
// Calibrate: note the mV reading in dry air and in a glass of water, and put them below.
constexpr uint8_t SOIL_PIN = 3;
constexpr int DRY_MV = 2200; // reading in dry air (yours will differ)
constexpr int WET_MV = 1000; // reading with the probe in water up to the line
void setup() {
Serial.begin(115200);
delay(1500); // let the native USB serial port enumerate
analogReadResolution(12);
Serial.println("Soil sensor on GPIO3");
}
void loop() {
uint32_t sum = 0;
for (int i = 0; i < 16; i++) sum += analogReadMilliVolts(SOIL_PIN); // average out noise
int mv = sum / 16;
int pct = constrain(map(mv, DRY_MV, WET_MV, 0, 100), 0, 100);
Serial.printf("Soil: %d mV → %d %% moisture\n", mv, pct);
delay(2000);
}// Capacitive soil moisture sensor (v1.2/v2.0) on an ESP32-C3 SuperMini.
// VCC → 3V3, GND → GND, AOUT → GPIO3 (ADC1). Only GPIO0–4 are reliable for analog on the C3,
// and its ADC reads up to about 2.5 V — the sensor's output at 3.3 V stays inside that.
// Calibrate: note the mV reading in dry air and in a glass of water, and put them below.
constexpr uint8_t SOIL_PIN = 3;
constexpr int DRY_MV = 2200; // reading in dry air (yours will differ)
constexpr int WET_MV = 1000; // reading with the probe in water up to the line
void setup() {
Serial.begin(115200);
delay(1500); // let the native USB serial port enumerate
analogReadResolution(12);
Serial.println("Soil sensor on GPIO3");
}
void loop() {
uint32_t sum = 0;
for (int i = 0; i < 16; i++) sum += analogReadMilliVolts(SOIL_PIN); // average out noise
int mv = sum / 16;
int pct = constrain(map(mv, DRY_MV, WET_MV, 0, 100), 0, 100);
Serial.printf("Soil: %d mV → %d %% moisture\n", mv, pct);
delay(2000);
}Expected serial output
Soil sensor on GPIO3
Soil: 2187 mV → 1 % moisture
Soil: 1544 mV → 54 % moisture
Soil: 1038 mV → 96 % moistureSoil sensor on GPIO3 Soil: 2187 mV → 1 % moisture Soil: 1544 mV → 54 % moisture Soil: 1038 mV → 96 % moisture
Common errors
Reading barely changes between dry and wet
NE555 version at 3.3 V, or the sensor is pushed in past the line. Try another board.
Percentage is negative or over 100
Your DRY_MV/WET_MV don’t match your sensor. Read the mV in air and in water and put those in the sketch (it clamps to 0–100).