The raindrop sensor is a PCB plate of interleaved tracks plus a small LM393 comparator board. Water bridging the tracks lowers the resistance, which the Pico W reads two ways: AO on GP28 (ADC2) for how wet, and DO on GP21 for a simple yes/no.
Power it from 3V3 so neither output can exceed the Pico’s limit. The script prints the wetness every two seconds and lights the on-board LED when it rains.
Wiring
| Raspberry Pi Pico W | Rain sensor (FC-37 / YL-83) | Wire | Notes |
|---|---|---|---|
| 3V3 | VCC | red | 3V3 is pin 36. Both outputs then stay at or below 3.3 V. |
| GND | GND | black | |
| GP28 | AO | green | GP28 = ADC2, physical pin 34. |
| GP21 | DO | yellow | GP21 is physical pin 27. |
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
- AO falls as more of the plate is wet; the script turns it into a 0–100 % “wet” figure and a rough dry / drizzle / rain / heavy label.
- DO goes LOW when water crosses the pot setting — the on-board LED follows it. Useful to close a window actuator or pull in a clothes line.
- The exposed tracks corrode in a few monsoon weeks if powered all the time. Mount the plate at an angle so water runs off, and only the plate goes outside — keep the comparator board and Pico dry.
- GP28 is the ADC pin next to AGND and ADC_VREF on the right header; GP26–GP28 are the only analog pins.
Code
# Rain / raindrop sensor (FC-37 / YL-83 plate + LM393 board) on a Raspberry Pi Pico W (MicroPython).
# Wiring: VCC -> 3V3 (pin 36), GND -> GND, AO -> GP28 / ADC2 (pin 34), DO -> GP21 (pin 27).
# Powered from 3.3 V, AO and DO can never exceed the Pico's limit.
from machine import ADC, Pin
import time
ao = ADC(28)
do = Pin(21, Pin.IN)
led = Pin("LED", Pin.OUT)
def wetness():
raw = sum(ao.read_u16() for _ in range(8)) // 8
return 100 - raw * 100 // 65535, raw # AO falls as the plate gets wetter
print("Rain sensor: AO on GP28, DO on GP21")
while True:
pct, raw = wetness()
raining = do.value() == 0 # DO goes LOW when water crosses the pot threshold
led.value(raining)
if pct < 10:
state = "dry"
elif pct < 40:
state = "drizzle"
elif pct < 70:
state = "rain"
else:
state = "heavy rain"
print("Wet {:3d} % (raw {:5d}) DO={} {}".format(pct, raw, do.value(), state))
time.sleep(2)# Rain / raindrop sensor (FC-37 / YL-83 plate + LM393 board) on a Raspberry Pi Pico W (MicroPython).
# Wiring: VCC -> 3V3 (pin 36), GND -> GND, AO -> GP28 / ADC2 (pin 34), DO -> GP21 (pin 27).
# Powered from 3.3 V, AO and DO can never exceed the Pico's limit.
from machine import ADC, Pin
import time
ao = ADC(28)
do = Pin(21, Pin.IN)
led = Pin("LED", Pin.OUT)
def wetness():
raw = sum(ao.read_u16() for _ in range(8)) // 8
return 100 - raw * 100 // 65535, raw # AO falls as the plate gets wetter
print("Rain sensor: AO on GP28, DO on GP21")
while True:
pct, raw = wetness()
raining = do.value() == 0 # DO goes LOW when water crosses the pot threshold
led.value(raining)
if pct < 10:
state = "dry"
elif pct < 40:
state = "drizzle"
elif pct < 70:
state = "rain"
else:
state = "heavy rain"
print("Wet {:3d} % (raw {:5d}) DO={} {}".format(pct, raw, do.value(), state))
time.sleep(2)Expected serial output
Rain sensor: AO on GP28, DO on GP21
Wet 3 % (raw 63520) DO=1 dry
Wet 47 % (raw 34612) DO=0 rainRain sensor: AO on GP28, DO on GP21 Wet 3 % (raw 63520) DO=1 dry Wet 47 % (raw 34612) DO=0 rain
Common errors
Reads wet long after the rain stops
The plate stays wet or dirty. Angle it, wipe it, and expect a delay of several minutes as it dries.
DO never changes
Turn the pot on the small board until its DO LED switches when you drip water on the plate.