A rain sensor is a comb of copper tracks on a plate plus a small comparator board. Water bridges the tracks and the resistance falls, giving you an analog wetness reading on AO and a simple yes/no on DO.
On the NodeMCU, AO goes to A0 — the ESP8266’s only analog pin — and the board must run from 3V3 so the signal stays inside A0’s 0–3.3 V range. DO goes to any free digital pin; D5 is a safe one.
Wiring
| NodeMCU ESP8266 | Rain sensor (FC-37 / YL-83) | Wire | Notes |
|---|---|---|---|
| 3V3 | VCC | red | At 3.3 V, AO can never exceed what A0 accepts on the NodeMCU. |
| GND | GND | black | |
| A0 | AO | green | The NodeMCU’s on-board divider maps 0–3.3 V to 0–1023. |
| D5 | DO | yellow | Goes LOW when wetness passes the blue trimmer’s threshold. |
3.3–5 V part, 3.3 V board. AO and DO swing up to VCC. Power the module from 3.3 V on ESP32/Pico so AO stays within the ADC range.
Board quirks
- The ESP8266 has one analog input. The bare chip reads only 0–1 V, but the NodeMCU adds a 220 kΩ / 100 kΩ divider, so its A0 pin takes 0–3.3 V. That is why the module goes on 3V3, not VIN: at 5 V, a dry plate would push AO above the range.
- Because A0 is the only ADC, a second analog sensor (soil moisture, LDR) can’t share it. Use the rain board’s DO output for one of them, or add an ADS1115 over I2C.
- Don’t call
analogRead(A0)in a tight loop: on the ESP8266 constant ADC reads upset the Wi-Fi radio. The sketch averages 8 spaced samples once a second. - Reading goes down as the plate gets wet: about 1000 dry, a few hundred in steady rain. Every plate is different — note your own dry and wet values before setting thresholds.
- The plate corrodes quickly with DC on it, especially in a monsoon that lasts months. Mount it tilted so water runs off, and replace it each season (₹40–60).
Code
// Rain sensor (FC-37 / YL-83 plate + LM393 board) on a NodeMCU (ESP8266).
// VCC → 3V3, GND → GND, AO → A0, DO → D5 (GPIO14).
// The NodeMCU's own divider maps 0–3.3 V on A0 to 0–1023, so AO goes straight in.
const uint8_t RAIN_DO = D5; // LOW when the plate is wetter than the trimmer setting
void setup() {
pinMode(RAIN_DO, INPUT);
Serial.begin(115200);
Serial.println();
Serial.println("Rain sensor: A0 = wetness, D5 = threshold output");
}
void loop() {
// analogRead(A0) in a tight loop disturbs Wi-Fi on the ESP8266, so take a few
// spaced samples and wait between readings.
uint32_t sum = 0;
for (int i = 0; i < 8; i++) {
sum += analogRead(A0);
delay(2);
}
int raw = sum / 8; // about 1023 = dry, lower = wetter
int wet = constrain(map(raw, 1023, 0, 0, 100), 0, 100); // rough 0–100 % wetness
bool raining = digitalRead(RAIN_DO) == LOW;
Serial.printf("A0 %4d wetness %3d %% DO %s\n", raw, wet, raining ? "RAIN" : "dry");
delay(1000);
}// Rain sensor (FC-37 / YL-83 plate + LM393 board) on a NodeMCU (ESP8266).
// VCC → 3V3, GND → GND, AO → A0, DO → D5 (GPIO14).
// The NodeMCU's own divider maps 0–3.3 V on A0 to 0–1023, so AO goes straight in.
const uint8_t RAIN_DO = D5; // LOW when the plate is wetter than the trimmer setting
void setup() {
pinMode(RAIN_DO, INPUT);
Serial.begin(115200);
Serial.println();
Serial.println("Rain sensor: A0 = wetness, D5 = threshold output");
}
void loop() {
// analogRead(A0) in a tight loop disturbs Wi-Fi on the ESP8266, so take a few
// spaced samples and wait between readings.
uint32_t sum = 0;
for (int i = 0; i < 8; i++) {
sum += analogRead(A0);
delay(2);
}
int raw = sum / 8; // about 1023 = dry, lower = wetter
int wet = constrain(map(raw, 1023, 0, 0, 100), 0, 100); // rough 0–100 % wetness
bool raining = digitalRead(RAIN_DO) == LOW;
Serial.printf("A0 %4d wetness %3d %% DO %s\n", raw, wet, raining ? "RAIN" : "dry");
delay(1000);
}Expected serial output
Rain sensor: A0 = wetness, D5 = threshold output
A0 1012 wetness 1 % DO dry
A0 684 wetness 33 % DO dry
A0 402 wetness 60 % DO RAINRain sensor: A0 = wetness, D5 = threshold output A0 1012 wetness 1 % DO dry A0 684 wetness 33 % DO dry A0 402 wetness 60 % DO RAIN
Common errors
A0 always reads 1023, even when wet
The module is on VIN (5 V) or AO isn’t connected. Power it from 3V3 and check the AO jumper goes to A0, not D0.
DO never changes
Turn the blue trimmer on the LM393 board until its DO LED just switches off when dry.
Wi-Fi drops while reading the sensor
You are calling analogRead(A0) continuously. Read it once a second, as the sketch does.