Sensor de lluvia Arduino: conexión, código y ventana automática
Sensor de lluvia con Arduino: conexión del FC-37/YL-83, salidas AO y DO, ajuste del umbral, evitar la corrosión, alarma, ventana con servo, código ESP32 y Pico.
Un sensor de lluvia permite que tu Arduino detecte gotas de agua y avise de que "ha empezado a llover" en cuestión de milisegundos; es uno de los sensores más baratos y divertidos que existen. Está formado por una placa sensora donde cae el agua y una pequeña placa de control con un comparador LM393, y se conecta al Arduino con solo cuatro cables. Un aviso para recoger la ropa antes de que se moje, una ventana o un toldo que se cierra solo cuando llueve, un riego de jardín que se salta los días de lluvia o una pequeña estación meteorológica empiezan con este módulo.
En esta guía verás qué hay dentro del módulo sensor de lluvia que se vende como FC-37, YL-83 o MH-RD, en qué se diferencian la salida analógica (AO) y la digital (DO), cómo ajustar el umbral con el potenciómetro y el tema que más se pasa por alto: cómo evitar que la placa se corroa. Después montaremos paso a paso una alarma de lluvia con niveles de intensidad en Arduino, un cierre automático de ventana con un servomotor, avisos al móvil con el ESP32 y un ejemplo en MicroPython para la Raspberry Pi Pico.

¿Qué es un sensor de lluvia y cómo funciona?
La placa sensora tiene dos pistas conductoras entrelazadas como los dientes de dos peines, pero que nunca se tocan. Con la placa seca, la resistencia entre ellas es del orden de megaohmios, así que el circuito está prácticamente abierto. Cuando una gota cae entre dos pistas, el agua forma un puente entre ellas y la resistencia baja. Cuantas más gotas caen y más superficie se moja, menor es la resistencia. En la placa de control, la placa sensora forma un divisor de tensión junto con una resistencia, de 10 kΩ en la mayoría de los modelos: con la placa seca, la tensión del pin AO está cerca de la alimentación (VCC) y va bajando a medida que se moja. Puedes comprobar cómo cambia la salida con distintas resistencias en la calculadora de divisor de tensión.
El LM393 de la placa es un circuito integrado comparador que compara dos tensiones. A una entrada le llega la tensión de la placa sensora y a la otra una tensión de referencia que ajustas con el potenciómetro. En el momento en que la tensión de la placa cae por debajo de la referencia, es decir, cuando se detecta suficiente agua, la salida DO pasa a LOW y se enciende el LED DO de la placa. El LM393 tiene salida de colector abierto; gracias a una resistencia pull-up de la placa, DO se mantiene en HIGH cuando no llueve. El otro LED (PWR) solo indica que el módulo recibe alimentación.
| Característica | Valor |
|---|---|
| Placa sensora | Unos 5,4 × 4 cm; pistas entrelazadas sobre FR4, niqueladas en la mayoría de los modelos |
| Placa de control | Unos 3 × 1,5 cm, comparador LM393 |
| Tensión de alimentación | 3,3–5 V |
| Consumo | Unos 8 mA (a 5 V con los dos LED encendidos) |
| Salida analógica (AO) | Entre 0 V y VCC; baja cuando la placa se moja |
| Salida digital (DO) | HIGH en seco, LOW al superar el umbral |
| Indicadores | LED PWR (alimentación) y LED DO (lluvia detectada) |
| Ajuste | Potenciómetro de sensibilidad (solo cambia el umbral de DO) |
| Conexiones | 2 pines en el lado de la placa sensora (sin polaridad), 4 pines hacia el Arduino: VCC, GND, DO, AO |
FC-37, YL-83 y MH-RD: ¿hay alguna diferencia?
En resumen, no. FC-37, YL-83 y MH-RD son nombres que distintos fabricantes dan al mismo circuito; todos tienen una placa sensora y una placa de control con LM393, y funcionan con el mismo código. Las diferencias suelen estar en el tamaño de la placa, en pequeños cambios del dibujo de las pistas y en la calidad del recubrimiento. La placa de control es casi idéntica a la del sensor de humedad del suelo, así que las placas de ambos módulos son intercambiables. Los dos pines entre la placa sensora y la de control no tienen positivo ni negativo, así que da igual en qué sentido conectes el cable. Cuando la placa sensora se desgaste con el tiempo, basta con cambiar solo esa pieza.
Diferencia entre la salida analógica (AO) y la digital (DO)
Qué salida usar depende de tu proyecto. DO solo dice "llueve" o "no llueve"; el umbral lo fijas con el potenciómetro de la placa y en Arduino basta con un digitalRead(). AO, en cambio, da un número de 0 a 1023 que indica lo mojada que está la placa, así que puedes distinguir una llovizna de un aguacero, cambiar el umbral en el código y decidir cuándo empieza o termina la lluvia mirando lecturas consecutivas. También puedes usar las dos salidas a la vez.
| Característica | DO (digital) | AO (analógica) |
|---|---|---|
| Qué indica | Llueve / no llueve | Cuánto se ha mojado la placa (0–1023 en el Uno) |
| Ajuste del umbral | Potenciómetro de la placa | En el código, como quieras |
| Pin de Arduino | Cualquier pin digital | Pin analógico (A0–A5) |
| Distingue la intensidad | No | Sí (llovizna, lluvia, aguacero) |
| Uso con interrupciones | Sí | No |
| Ideal para | Alarmas sencillas, señal para despertar | Medir niveles, automatización con histéresis |
Conexión del sensor de lluvia: Arduino Uno, ESP32 y Pico
| Pin del módulo / pieza | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| VCC | D7 (para alimentarlo solo al medir) o 5V | GPIO 25 o 3V3 | GP15 o 3V3(OUT) |
| GND | GND | GND | GND |
| AO | A0 | GPIO 34 (ADC1) | GP26 (ADC0) |
| DO | D2 | Opcional (p. ej., GPIO 27) | GP14 |
| Zumbador activo (+) | D8 | Opcional | GP13 |
| Cable de señal del servo | D9 | Opcional | GP16 |
Seguramente te has fijado en que en la tabla VCC va a un pin digital en lugar de a 5V. El módulo solo consume unos 8 mA a 5 V, así que un pin de Arduino lo alimenta sin problema (el límite recomendado es de 20 mA por pin). Así enciendes el módulo solo durante los pocos milisegundos que dura la medición y lo mantienes apagado el resto del tiempo. Veremos por qué es tan importante en el apartado sobre la corrosión. Los pines de la Pico vienen configurados por defecto con una intensidad de salida de 4 mA; como el módulo consume solo unos pocos mA a 3,3 V suele bastar, pero si las lecturas son inestables puedes alimentarlo desde el pin 3V3(OUT).
Ajuste de la sensibilidad: el umbral con el potenciómetro
- Seca bien la placa sensora y alimenta el módulo; el LED PWR debe estar encendido y el LED DO apagado.
- Gira despacio el potenciómetro con un destornillador pequeño hasta que se encienda el LED DO. Si con la placa seca ya está encendido, gira en sentido contrario.
- Vuelve justo al punto en el que el LED se apaga. Es el ajuste más sensible con el que DO sigue en HIGH con la placa seca.
- Gira un poco más en el mismo sentido para dejar margen de seguridad; si no, hasta el aire húmedo o el rocío pueden disparar la alarma.
- Deja caer dos o tres gotas de agua sobre la placa con el dedo. El LED DO debe encenderse; si no lo hace, sube un poco la sensibilidad.
- Seca la placa y observa cuánto tarda en apagarse el LED; así te harás una idea de cuánto debe esperar tu sistema antes de decidir que "ha dejado de llover".
Paso a paso: tu primera lectura con Arduino
- Conecta VCC del módulo a D7, GND a GND, AO a A0 y DO a D2. Une la placa sensora a la de control con el cable de dos hilos.
- Abre el código de abajo en el Arduino IDE, elige Arduino Uno como placa y súbelo.
- Abre el Monitor Serie a 9600 baudios y anota el valor de AO con la placa seca.
- Echa primero unas gotas de agua sobre la placa, luego más, y apunta el valor de AO cada vez.
- Anota también el valor con la placa totalmente mojada; estos valores serán las constantes DRY y WET que usarás en los siguientes programas.
1// Yağmur sensörü: AO ve DO okuma / Rain sensor: reading AO and DO
2const int SENSOR_POWER = 7; // modülün VCC'si bu pinden beslenir / module VCC is fed from this pin
3const int RAIN_AO = A0; // analog çıkış / analog output
4const int RAIN_DO = 2; // dijital çıkış / digital output
5
6void setup() {
7 Serial.begin(9600);
8 pinMode(SENSOR_POWER, OUTPUT);
9 digitalWrite(SENSOR_POWER, LOW); // başlangıçta kapalı / off at start-up
10 pinMode(RAIN_DO, INPUT);
11}
12
13void loop() {
14 digitalWrite(SENSOR_POWER, HIGH); // modülü aç / power the module
15 delay(50); // değerin oturmasını bekle / let the reading settle
16 int analogValue = analogRead(RAIN_AO); // 0-1023: kuruyken yüksek / high when dry
17 bool raining = digitalRead(RAIN_DO) == LOW; // yağmurda DO = LOW / DO goes LOW in rain
18 digitalWrite(SENSOR_POWER, LOW); // modülü kapat / power it off
19
20 Serial.print(F("AO: "));
21 Serial.print(analogValue);
22 Serial.print(F(" DO: "));
23 Serial.println(raining ? F("YAGMUR / RAIN") : F("KURU / DRY"));
24 delay(2000); // 2 sn'de bir ölç / measure every 2 s
25}Antes de cada medición, el código pone D7 en HIGH para encender el módulo, espera 50 ms a que se carguen los condensadores de la placa y se estabilice la lectura, lee AO y DO y apaga el módulo enseguida. Así el módulo solo está alimentado 50 ms de cada ciclo de 2 segundos, es decir, el 2,5 % del tiempo. Como DO pasa a LOW con lluvia, escribimos la condición como digitalRead(RAIN_DO) == LOW. Las palabras en turco de los mensajes van sin caracteres especiales porque algunos terminales los muestran mal.
| Estado de la placa | AO aprox. (Uno, 5 V) | DO (placa ajustada) |
|---|---|---|
| Seca y limpia | 1000–1023 | HIGH |
| Unas pocas gotas | 750–950 | HIGH o LOW según el ajuste |
| Llovizna, placa mojada en parte | 500–750 | LOW |
| Lluvia intensa | 300–500 | LOW |
| Totalmente mojada, agua del grifo | 150–350 | LOW |
Estas cifras son solo orientativas: el tamaño de la placa, el estado del recubrimiento, la pureza del agua y el polvo acumulado las cambian bastante. Incluso los valores del mismo módulo se desplazan después de tener la placa unos meses a la intemperie. Por eso, en los siguientes programas no usamos el valor bruto, sino que lo convertimos en un porcentaje de humedad de 0 a 100 con los valores en seco (DRY) y mojado (WET) que mediste tú; así solo tienes que actualizar esas dos constantes sin tocar los umbrales.
Alarma de lluvia con Arduino: niveles de intensidad y zumbador
Ahora vamos a convertir la medición en una alarma útil. El código toma 8 lecturas seguidas de AO, calcula la media, la convierte en porcentaje de humedad con map() y la clasifica en uno de cuatro niveles: seco, llovizna, lluvia y aguacero. Cuando la lluvia se intensifica, el zumbador activo pita tantas veces como el número del nivel: una vez con llovizna, dos con lluvia y tres con aguacero. Conecta la patilla positiva del zumbador a D8 y la negativa a GND; la diferencia entre zumbador activo y pasivo la tienes en ¿Qué es un buzzer?.
1// Yağmur şiddeti seviyeleri ve sesli alarm / Rain intensity levels and audible alarm
2const int SENSOR_POWER = 7; // modülün VCC'si / module VCC
3const int RAIN_AO = A0; // analog çıkış / analog output
4const int BUZZER = 8; // aktif buzzer / active buzzer
5const int DRY = 1015; // kuru panel değeri / dry pad reading (kendin ölç / measure yours)
6const int WET = 350; // tamamen ıslak panel / fully wet pad (kendin ölç / measure yours)
7
8const char* const LEVEL_NAMES[] = {"Kuru / Dry", "Ciseleme / Drizzle", "Yagmur / Rain", "Saganak / Downpour"};
9int lastLevel = 0;
10
11int readWetness() {
12 digitalWrite(SENSOR_POWER, HIGH);
13 delay(50);
14 long sum = 0;
15 for (int i = 0; i < 8; i++) sum += analogRead(RAIN_AO); // 8 ölçümün ortalaması / average of 8 readings
16 digitalWrite(SENSOR_POWER, LOW);
17 return constrain(map(sum / 8, DRY, WET, 0, 100), 0, 100); // % ıslaklık / % wetness
18}
19
20void beep(int count) {
21 for (int i = 0; i < count; i++) {
22 digitalWrite(BUZZER, HIGH);
23 delay(150);
24 digitalWrite(BUZZER, LOW);
25 delay(150);
26 }
27}
28
29void setup() {
30 Serial.begin(9600);
31 pinMode(SENSOR_POWER, OUTPUT);
32 pinMode(BUZZER, OUTPUT);
33}
34
35void loop() {
36 int wet = readWetness();
37 int level;
38 if (wet < 10) level = 0; // kuru / dry
39 else if (wet < 40) level = 1; // çiseleme / drizzle
40 else if (wet < 75) level = 2; // yağmur / rain
41 else level = 3; // sağanak / downpour
42
43 Serial.print(F("Islaklik / Wetness: %"));
44 Serial.print(wet);
45 Serial.print(F(" "));
46 Serial.println(LEVEL_NAMES[level]);
47
48 if (level > lastLevel) beep(level); // şiddet artınca seviye kadar bip / beep once per level when it gets heavier
49 lastLevel = level;
50 delay(3000); // 3 sn'de bir ölç / measure every 3 s
51}Este porcentaje indica qué parte de la placa está mojada; no es una medida de precipitación en milímetros por hora como la que usan los meteorólogos. Aun así, en la práctica es muy útil: una llovizna ligera solo une unas pocas pistas, mientras que un aguacero cubre casi toda la superficie. Puedes cambiar los límites de nivel (10, 40 y 75) según tus propias observaciones. Como el zumbador solo suena cuando el nivel sube, no oirás un pitido cada 3 segundos mientras la lluvia se mantenga igual.
Corrosión: ¿por qué se oxida la placa y cómo alargar su vida?
El mayor problema de los sensores de lluvia es que se desgastan con el tiempo. Si la placa recibe corriente continua (CC) de forma permanente, el agua entre las pistas actúa como electrolito y comienza la electrólisis: el metal de la pista conectada al positivo se disuelve poco a poco, el niquelado se adelgaza y el cobre de debajo se ennegrece o se vuelve verde. Como resultado, la resistencia en seco baja, los valores se desplazan y al final las pistas se cortan. Una placa que se deja a la intemperie con 5 V constantes puede desgastarse de forma visible en pocas semanas. La buena noticia es que el desgaste es proporcional al tiempo que la placa está alimentada, y ese tiempo lo controlas tú.
- Aliméntalo solo al medir: Saca VCC de un pin digital y deja el módulo encendido solo 50 ms en cada lectura. En un sistema que mide cada 2 segundos, la placa está alimentada el 2,5 % del tiempo, lo que frena el desgaste unas 40 veces.
- Mide con menos frecuencia: La lluvia no cambia en segundos. Para proyectos de ventanas o avisos basta con una lectura cada 5–30 segundos; un sistema que mide cada 30 segundos mantiene la placa alimentada solo un 0,2 % del tiempo.
- Invierte la polaridad (nivel avanzado): Si conectas la placa sensora directamente a dos pines digitales y en cada lectura cambias qué extremo está en HIGH, el desgaste se reparte por igual entre las dos pistas. Con este método no usas la placa de control: montas tú mismo el divisor de tensión con una resistencia y haces una lectura en cada sentido.
- Mantén limpia la placa: El polvo, el polen y los excrementos de pájaro aumentan la conductividad y bajan el valor en seco. Límpiala de vez en cuando con alcohol isopropílico y un pincel suave; el papel de lija o un estropajo rayan el recubrimiento.
- Protege la placa de control, no la sensora: Mete la placa de control en una caja estanca o aplícale barniz protector. La placa sensora, en cambio, nunca la cubras con barniz, silicona ni cinta: el agua tiene que tocar las pistas.
- Ten una placa de repuesto: La placa sensora es un consumible barato. Cuando los valores se desplacen mucho o las pistas se oscurezcan, cambia solo esa placa y vuelve a medir DRY y WET.
Cierre automático de ventana o toldo con un servomotor
La aplicación más popular del sensor de lluvia es un sistema que cierra solo una ventana, un toldo o el techo de un invernadero cuando empieza a llover. Puedes montarlo en una maqueta con un servomotor SG90. Aquí importan dos reglas. La primera es la confirmación: una sola gota o un insecto sobre la placa no deben cerrar la ventana, así que esperamos 3 lecturas mojadas seguidas antes de cerrar. La segunda es la histéresis: cuando para de llover, la placa no se seca al instante y el valor oscila alrededor del umbral. Para que la ventana no se abra y se cierre sin parar, usamos dos umbrales distintos para "llueve" y "seco", y solo abrimos la ventana cuando la placa lleva 10 minutos seguidos seca. Para la conexión del servo y el control del ángulo, consulta ¿Qué es un servomotor?.


1// Yağmurda pencereyi servo ile kapatan sistem / Closes a window with a servo when it rains
2#include <Servo.h>
3
4const int SENSOR_POWER = 7; // modülün VCC'si / module VCC
5const int RAIN_AO = A0; // analog çıkış / analog output
6const int BUZZER = 8; // aktif buzzer / active buzzer
7const int SERVO_PIN = 9; // servo sinyal kablosu / servo signal wire
8
9const int DRY = 1015; // kuru panel / dry pad (kendin ölç / measure yours)
10const int WET = 350; // ıslak panel / wet pad (kendin ölç / measure yours)
11const int RAIN_ON = 25; // %25 ve üstü: yağıyor / 25% and above: raining
12const int RAIN_OFF = 8; // %8 ve altı: panel kurudu / 8% and below: pad is dry
13const int CONFIRM_COUNT = 3; // art arda 3 ıslak ölçüm / 3 wet readings in a row
14const unsigned long SAMPLE_MS = 2000UL; // 2 sn'de bir ölç / measure every 2 s
15const unsigned long DRY_MS = 600000UL; // 10 dk kuru kalmalı / must stay dry for 10 min
16
17const int OPEN_ANGLE = 90; // pencere açık / window open
18const int CLOSED_ANGLE = 0; // pencere kapalı / window closed
19
20Servo windowServo;
21bool closed = false;
22int wetCount = 0;
23unsigned long lastSample = 0;
24unsigned long drySince = 0;
25
26int readWetness() {
27 digitalWrite(SENSOR_POWER, HIGH);
28 delay(50); // değerin oturmasını bekle / let it settle
29 int raw = analogRead(RAIN_AO);
30 digitalWrite(SENSOR_POWER, LOW);
31 return constrain(map(raw, DRY, WET, 0, 100), 0, 100); // % ıslaklık / % wetness
32}
33
34void beep(int count) {
35 for (int i = 0; i < count; i++) {
36 digitalWrite(BUZZER, HIGH);
37 delay(150);
38 digitalWrite(BUZZER, LOW);
39 delay(150);
40 }
41}
42
43void setup() {
44 Serial.begin(9600);
45 pinMode(SENSOR_POWER, OUTPUT);
46 pinMode(BUZZER, OUTPUT);
47 windowServo.write(OPEN_ANGLE); // attach'tan önce açı ver, servo zıplamasın / set the angle before attach to avoid a jump
48 windowServo.attach(SERVO_PIN);
49}
50
51void loop() {
52 unsigned long now = millis();
53 if (now - lastSample < SAMPLE_MS) return; // ölçüm zamanı gelmedi / not time to measure yet
54 lastSample = now;
55
56 int wet = readWetness();
57 Serial.print(F("Islaklik / Wetness: %"));
58 Serial.println(wet);
59
60 if (wet >= RAIN_ON) {
61 drySince = now; // kuruma sayacını sıfırla / reset the drying timer
62 if (wetCount < CONFIRM_COUNT) wetCount++;
63 if (!closed && wetCount >= CONFIRM_COUNT) {
64 closed = true;
65 beep(3);
66 windowServo.write(CLOSED_ANGLE); // pencereyi kapat / close the window
67 Serial.println(F("Yagmur: pencere kapandi / Rain: window closed"));
68 }
69 } else {
70 wetCount = 0;
71 if (wet > RAIN_OFF) {
72 drySince = now; // ara bölge kuru sayılmaz / the middle zone does not count as dry
73 } else if (closed && now - drySince >= DRY_MS) {
74 closed = false;
75 windowServo.write(OPEN_ANGLE); // 10 dk kuruysa aç / open after 10 dry minutes
76 Serial.println(F("Kuru: pencere acildi / Dry: window opened"));
77 }
78 }
79}| Constante | Función | Valor inicial |
|---|---|---|
| DRY / WET | Los valores de placa seca y mojada que mediste tú | 1015 / 350 |
| RAIN_ON | A partir de este porcentaje se considera que "llueve" | 25 % |
| RAIN_OFF | Por debajo de este porcentaje (incluido) se considera "seco" | 8 % |
| CONFIRM_COUNT | Lecturas mojadas seguidas necesarias para cerrar la ventana | 3 (unos 6 s) |
| DRY_MS | Tiempo que la placa debe seguir seca antes de abrir la ventana | 10 minutos |
| OPEN_ANGLE / CLOSED_ANGLE | Ángulo del servo en posición abierta y cerrada | 90° / 0° |
Avisos de lluvia en el móvil con el ESP32
Para enterarte de que ha empezado a llover cuando no estás en casa, puedes usar un ESP32. El código siguiente envía por Telegram el mensaje "recoge la ropa" cuando empieza a llover y "ha dejado de llover" cuando la placa lleva 15 minutos seca. Necesitas instalar las bibliotecas UniversalTelegramBot y ArduinoJson desde el Gestor de bibliotecas. Cómo crear el bot y encontrar tu chat ID lo explicamos paso a paso en Bot de Telegram con ESP32.
1// ESP32 yağmur bildirimi (Telegram) / ESP32 rain notification (Telegram)
2#include <WiFi.h>
3#include <WiFiClientSecure.h>
4#include <UniversalTelegramBot.h> // ArduinoJson kütüphanesi de gerekir / also needs the ArduinoJson library
5
6const char* WIFI_SSID = "WIFI_ADI"; // Wi-Fi ağının adı / your Wi-Fi name
7const char* WIFI_PASS = "WIFI_SIFRESI"; // Wi-Fi şifren / your Wi-Fi password
8#define BOT_TOKEN "1234567890:ABCdefGhIJKlmNoPQRstuVWXyz" // BotFather'dan / from BotFather
9#define CHAT_ID "123456789" // senin chat ID'n / your chat ID
10
11const int SENSOR_POWER = 25; // modülün VCC'si (3,3 V) / module VCC (3.3 V)
12const int RAIN_AO = 34; // ADC1 pini, Wi-Fi ile çalışır / ADC1 pin, works with Wi-Fi
13const int DRY = 4095; // kuru panel / dry pad (kendin ölç / measure yours)
14const int WET = 1500; // ıslak panel / wet pad (kendin ölç / measure yours)
15const int RAIN_ON = 25; // %25 ve üstü: yağıyor / 25% and above: raining
16const int RAIN_OFF = 8; // %8 ve altı: kuru / 8% and below: dry
17const unsigned long SAMPLE_MS = 5000UL; // 5 sn'de bir ölç / measure every 5 s
18const unsigned long DRY_MS = 900000UL; // 15 dk kuru: yağmur bitti / 15 dry minutes: rain is over
19
20WiFiClientSecure client;
21UniversalTelegramBot bot(BOT_TOKEN, client);
22
23bool raining = false;
24int wetCount = 0;
25unsigned long lastSample = 0;
26unsigned long drySince = 0;
27
28int readWetness() {
29 digitalWrite(SENSOR_POWER, HIGH);
30 delay(50); // değerin oturmasını bekle / let it settle
31 int raw = analogRead(RAIN_AO); // 0-4095
32 digitalWrite(SENSOR_POWER, LOW);
33 return constrain(map(raw, DRY, WET, 0, 100), 0, 100);
34}
35
36void connectWiFi() {
37 WiFi.mode(WIFI_STA);
38 WiFi.begin(WIFI_SSID, WIFI_PASS);
39 unsigned long start = millis();
40 while (WiFi.status() != WL_CONNECTED && millis() - start < 15000) { // en fazla 15 sn bekle / wait up to 15 s
41 delay(500);
42 }
43}
44
45void notify(const String& text) {
46 if (WiFi.status() != WL_CONNECTED) connectWiFi(); // bağlantı koptuysa yeniden bağlan / reconnect if dropped
47 if (WiFi.status() == WL_CONNECTED) {
48 bot.sendMessage(CHAT_ID, text, "");
49 }
50}
51
52void setup() {
53 Serial.begin(115200);
54 pinMode(SENSOR_POWER, OUTPUT);
55 digitalWrite(SENSOR_POWER, LOW);
56 client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // api.telegram.org kök sertifikası / root certificate
57 connectWiFi();
58 notify("Yagmur sensoru devrede / Rain sensor is online");
59}
60
61void loop() {
62 unsigned long now = millis();
63 if (now - lastSample < SAMPLE_MS) return;
64 lastSample = now;
65
66 int wet = readWetness();
67 Serial.printf("Islaklik / Wetness: %%%d\n", wet);
68
69 if (!raining) {
70 wetCount = (wet >= RAIN_ON) ? wetCount + 1 : 0;
71 if (wetCount >= 2) { // art arda 2 ıslak ölçüm (~10 sn) / 2 wet readings in a row (~10 s)
72 raining = true;
73 drySince = now;
74 String msg = "Yagmur basladi, camasirlari topla! / It's raining, bring in the laundry! %";
75 msg += wet;
76 notify(msg);
77 }
78 } else {
79 if (wet > RAIN_OFF) {
80 drySince = now; // hâlâ ıslak / still wet
81 } else if (now - drySince >= DRY_MS) {
82 raining = false;
83 wetCount = 0;
84 notify("Yagmur durdu / The rain has stopped");
85 }
86 }
87}El ADC del ESP32 es de 12 bits, así que los valores van de 0 a 4095; con el módulo alimentado a 3,3 V, una placa seca suele leer casi 4095, aunque igualmente debes medir tú los valores DRY y WET. Como enviar un mensaje puede tardar uno o dos segundos, dejamos el intervalo de medición en 5 segundos, y usamos la variable raining para que un mismo chaparrón no dispare un mensaje tras otro. Si quieres que el sistema funcione con pilas, puedes poner el ESP32 en deep sleep entre lecturas, y si usas Home Assistant puedes enviar los datos por MQTT.
Sensor de lluvia con Raspberry Pi Pico y MicroPython
En la Raspberry Pi Pico la lógica es la misma. Alimenta el módulo a 3,3 V a través de GP15 y conecta AO a GP26, DO a GP14, el zumbador activo a GP13 y el cable de señal del servo a GP16. El ADC de la Pico devuelve valores de 0 a 65535 con read_u16(). El código siguiente pita tres veces al detectar lluvia y recoge un toldo con el servo; cuando la placa lleva 10 minutos seca, vuelve a abrirlo.
1# Raspberry Pi Pico yağmur sensörü + servo tente / Raspberry Pi Pico rain sensor + servo awning
2from machine import Pin, ADC, PWM
3import time
4
5power = Pin(15, Pin.OUT, value=0) # modülün VCC'si (3,3 V) / module VCC (3.3 V)
6rain_ao = ADC(26) # GP26 = ADC0, AO çıkışı / AO output
7rain_do = Pin(14, Pin.IN) # DO: yağmurda 0 / DO: 0 in rain
8buzzer = Pin(13, Pin.OUT, value=0) # aktif buzzer / active buzzer
9servo = PWM(Pin(16))
10servo.freq(50) # servolar 50 Hz ister / servos expect 50 Hz
11
12DRY, WET = 65000, 24000 # kendi değerlerinle değiştir / replace with your readings
13RAIN_ON, RAIN_OFF = 25, 8 # % eşikler / % thresholds
14DRY_MS = 10 * 60 * 1000 # 10 dk kuru kalmalı / must stay dry for 10 min
15OPEN_ANGLE, CLOSED_ANGLE = 90, 0
16
17def set_angle(deg):
18 us = 544 + deg * (2400 - 544) // 180 # Arduino Servo ile aynı aralık / same range as Arduino Servo
19 servo.duty_u16(us * 65535 // 20000) # 20 ms periyodun oranı / share of the 20 ms period
20
21def read_sensor():
22 power.value(1)
23 time.sleep_ms(50) # değerin oturmasını bekle / let it settle
24 raw = rain_ao.read_u16() # 0-65535
25 do_wet = rain_do.value() == 0
26 power.value(0)
27 pct = (DRY - raw) * 100 // (DRY - WET)
28 return max(0, min(100, pct)), do_wet
29
30def beep(count):
31 for _ in range(count):
32 buzzer.value(1)
33 time.sleep_ms(150)
34 buzzer.value(0)
35 time.sleep_ms(150)
36
37closed = False
38wet_count = 0
39dry_since = time.ticks_ms()
40set_angle(OPEN_ANGLE) # tente açık başlar / awning starts open
41
42while True:
43 wet, do_wet = read_sensor()
44 print("Islaklik / Wetness: %", wet, " DO:", "YAGMUR / RAIN" if do_wet else "KURU / DRY")
45 now = time.ticks_ms()
46 if wet >= RAIN_ON:
47 dry_since = now # kuruma sayacını sıfırla / reset the drying timer
48 wet_count += 1
49 if not closed and wet_count >= 3: # art arda 3 ıslak ölçüm / 3 wet readings in a row
50 closed = True
51 beep(3)
52 set_angle(CLOSED_ANGLE) # tenteyi kapat / retract the awning
53 else:
54 wet_count = 0
55 if wet > RAIN_OFF:
56 dry_since = now
57 elif closed and time.ticks_diff(now, dry_since) >= DRY_MS:
58 closed = False
59 set_angle(OPEN_ANGLE) # 10 dk kuruysa aç / open after 10 dry minutes
60 time.sleep(2)MicroPython no trae una clase para servos, así que convertimos el ángulo en ancho de pulso nosotros mismos: los servos se posicionan con pulsos de unos 0,5–2,5 ms que llegan cada 20 ms. La función set_angle() convierte 0–180 grados al mismo rango de 544–2400 microsegundos que usa la biblioteca Servo de Arduino y, después, ese tiempo a una proporción de 0–65535 para duty_u16(). Si guardas el código en la Pico como main.py con Thonny, se ejecutará automáticamente cada vez que la enciendas.
Instalación en exterior: consejos para colocarlo bien
- Monta la placa inclinada: Una inclinación de 20–45 grados hace que las gotas escurran y que la placa se seque antes cuando para de llover. En una placa plana el agua se encharca y el sistema puede decir "llueve" durante horas.
- Elige un sitio a cielo abierto: No la pongas bajo un alero, un árbol o el goteo de un aire acondicionado; ahí se pierde la lluvia real y además se activa con gotas que no son de lluvia.
- Deja la electrónica a cubierto: Fuera solo debe quedar la placa sensora. Mete la placa de control y el Arduino en una caja estanca y sella la entrada del cable con un prensaestopas o silicona.
- Usa cables cortos: El cable entre la placa sensora y la de control se puede alargar hasta unos pocos metros; con cables más largos aumenta el ruido. Promediar las lecturas reduce esas oscilaciones.
- Cuidado con el rocío y la niebla: En noches frescas, la humedad que se condensa sobre la placa puede dar un pequeño valor de humedad. Un umbral RAIN_ON algo más alto y la confirmación con lecturas consecutivas evitan la mayoría de estas falsas alarmas.
- Detecta tarde la nieve: La nieve seca no conduce la electricidad; el sensor solo reacciona cuando se funde y se convierte en agua. En climas fríos, considéralo fiable solo para la lluvia.
Sensor de lluvia, de humedad del suelo y de nivel de agua: diferencias
| Sensor | ¿Qué mide? | Salida | Uso típico |
|---|---|---|---|
| Sensor de lluvia (FC-37, YL-83) | Gotas de agua que caen en su superficie | AO y DO | Alarma de lluvia, automatización de ventanas y toldos |
| Sensor de humedad del suelo | Humedad de la tierra | AO y DO (misma placa LM393) | Riego de plantas |
| Sensor de nivel de agua (pistas paralelas) | Altura del agua en un recipiente | Analógica (S) | Nivel de depósitos y acuarios |
| Pluviómetro de balancín | Cantidad de lluvia (mm) | Un pulso por cada vuelco | Estación meteorológica |


Un sensor de lluvia no puede responder a la pregunta "¿cuánto ha llovido?"; para eso necesitas el pluviómetro de balancín (de cubeta basculante) que usan las estaciones meteorológicas. El agua de un embudo llena una pequeña cubeta que vuelca al alcanzar una cantidad fija (en los kits de estación meteorológica habituales, cada vuelco equivale a 0,2794 mm de lluvia), y en cada vuelco un imán cierra brevemente un interruptor reed. El Arduino cuenta estos pulsos con una interrupción y multiplica el número por el valor de la cubeta para obtener la lluvia en milímetros. También tiene sentido usar los dos sensores juntos: el sensor de lluvia avisa al instante de que empieza a llover y el pluviómetro registra el total. Si lo que quieres es medir la altura del agua acumulada en un recipiente, un sensor de nivel de agua es mejor opción.
Ideas de proyectos con el sensor de lluvia
- Aviso para recoger la ropa: Un zumbador que suena y un LED que se enciende cuando empieza a llover; con un ESP32 también te llega un mensaje al móvil.
- Techo de invernadero inteligente: Cierra la ventana del techo con un servo cuando llueve y ábrela según la temperatura para ventilar. Tienes los detalles en el proyecto de invernadero inteligente.
- Saltarse el riego si llueve: Haz que el riego automático que montaste con un sensor de humedad del suelo no encienda la bomba mientras llueve.
- Mini estación meteorológica: Muestra el estado de la lluvia en una pantalla OLED junto con la temperatura, la humedad y la presión que mides con un BME280.
- Maqueta de limpiaparabrisas: Un proyecto divertido que imita el limpiaparabrisas automático de un coche moviendo un servo más rápido cuanto más fuerte llueve.
- Escenario de casa inteligente: Para un sistema que cierre las ventanas, recoja el toldo y te avise cuando empiece a llover, apóyate en la guía del proyecto de casa inteligente con Arduino.
Errores frecuentes y cómo solucionarlos
| Síntoma | Causa probable | Solución |
|---|---|---|
| AO siempre marca 1023 y no cambia | El cable de la placa sensora está suelto o roto; en A0 está DO en lugar de AO | Revisa los dos hilos entre la placa sensora y la de control, y la conexión en A0 |
| AO es muy bajo incluso con la placa seca | La placa está sucia o aún mojada; algo une las pistas; se lee antes de encender el módulo | Limpia y seca la placa; en el código, lee solo después de alimentar y esperar |
| DO nunca cambia | El potenciómetro está girado hasta un tope | Repite desde el principio los pasos de ajuste de la sensibilidad |
| Alarma de lluvia con tiempo seco | Rocío, niebla, placa sucia o umbral demasiado sensible | Sube RAIN_ON, confirma con lecturas consecutivas, limpia la placa |
| Ha parado de llover pero el sistema sigue diciendo "llueve" | La placa está en horizontal y se seca despacio | Monta la placa inclinada, ajusta RAIN_OFF y DRY_MS |
| Los valores se desplazaron en semanas y las pistas se oscurecieron | Corrosión por alimentación continua | Alimenta el módulo desde un pin, mide con menos frecuencia, cambia la placa sensora |
| En el ESP32 las lecturas fallan al activar el Wi-Fi | AO está en un pin ADC2 | Pasa AO a un pin entre GPIO 32 y 39 |
| El servo tiembla o el Arduino se reinicia | La corriente del servo hace caer la línea de 5 V | Alimenta el servo con una fuente de 5 V aparte, une las masas y añade un condensador de 470 µF en la alimentación |
El sensor de lluvia es un módulo barato pero muy didáctico que te enseña a la vez divisores de tensión, comparadores, histéresis y problemas reales como la corrosión. Si recuerdas alimentar la placa solo al medir y ajustar los umbrales con tus propias lecturas, te durará mucho tiempo. En la app BlueGrays encontrarás proyectos paso a paso con esquemas y código que usan las piezas de este artículo, como el zumbador, el servomotor, una estación de riego inteligente y una alarma por Telegram con ESP32, y podrás añadirles el sensor de lluvia fácilmente.
Preguntas frecuentes
¿Cómo funciona un sensor de lluvia?
Las dos pistas conductoras entrelazadas de la placa sensora están aisladas entre sí cuando están secas. Cuando las gotas de lluvia las unen, la resistencia de la placa baja y la salida (AO) del divisor de tensión de la placa de control disminuye. El comparador LM393 compara esa tensión con el umbral ajustado en el potenciómetro y pone la salida DO en LOW cuando se supera.
¿Un sensor de lluvia mide la cantidad de lluvia?
No. Un sensor de lluvia indica qué parte de la placa está mojada; eso basta para saber que ha empezado a llover y, aproximadamente, con qué intensidad, pero no da la precipitación en milímetros. Para medir la cantidad se usa un pluviómetro de balancín, que genera un pulso con un interruptor reed cada vez que vuelca.
¿Por qué se corroe un sensor de lluvia y cuánto dura?
Cuando la placa recibe corriente continua de forma permanente, se produce electrólisis en el agua entre las pistas y el metal de la pista del lado positivo se disuelve. Una placa a la intemperie con 5 V constantes puede desgastarse de forma visible en pocas semanas. Si alimentas el módulo desde un pin digital y solo lo enciendes unos milisegundos en cada lectura, la placa dura mucho más, a menudo muchos meses sin problemas.
¿El sensor de lluvia da LOW o HIGH cuando llueve?
En los módulos LM393 habituales, la salida DO está en HIGH en seco; cuando el agua de la placa supera el umbral ajustado con el potenciómetro, pasa a LOW y se enciende el LED DO. La salida AO está en su valor máximo en seco y baja a medida que la placa se moja; en un Arduino Uno, una placa seca suele leer más de 1000.
¿El sensor de lluvia funciona con ESP32 y 3,3 V?
Sí, el módulo funciona entre 3,3 y 5 V. En el ESP32 y la Raspberry Pi Pico debes alimentarlo a 3,3 V para que las salidas AO y DO tampoco pasen de 3,3 V. En el ESP32, conecta AO a uno de los pines ADC1 (GPIO 32–39), que siguen funcionando con el Wi-Fi activado.
¿El sensor de lluvia detecta nieve, rocío o niebla?
La nieve seca no conduce la electricidad, así que el sensor solo la detecta cuando se funde. El rocío y la niebla densa, en cambio, pueden dejar una fina película de humedad en la placa que produce un valor pequeño y, a veces, una falsa alarma. Para evitarlo, mantén el umbral algo más alto, confirma la alarma con varias lecturas seguidas y monta la placa inclinada.
Proyectos para hacer después de leer esto
Ver todos los proyectos
Uso del zumbador
¿Alguna vez te has preguntado cómo suena un timbre o una alarma? El Arduino hace pitar un pequeño zumbador a intervalos cortos: pip, silencio, pip, silencio. Ves cómo se crea sonido con electricidad y

Temperatura y humedad con DHT11
¿Qué temperatura hace en tu habitación, y el aire está húmedo o seco? El sensor DHT11 mide la temperatura y la humedad, y el Arduino escribe los valores en una pantalla LCD de dos líneas, actualizándo

Uso del servomotor
El brazo de un pequeño servomotor gira por turnos a tres posiciones: al principio del todo, justo al centro y al final del todo, esperando dos segundos en cada parada. El Arduino le dice al motor en q

Estación de riego inteligente
Un jardinero que riega solo tus plantas para que no se sequen mientras estás de vacaciones. Un sensor de humedad mide lo mojada que está la tierra; cuando se seca, el Arduino enciende la bomba de agua

Uso del sensor de llama
Un pequeño vigilante que detecta el fuego antes que tú, en la cocina o en el taller. El sensor de llama capta la luz invisible que desprende el fuego; si todo va bien se enciende el LED verde, y cuand

Sistema de Alarma de Movimiento ESP32 (PIR + Buzzer + LED + Telegram)
Un sistema inteligente de alarma de seguridad que activa el buzzer y el LED cuando el sensor PIR detecta movimiento, y envía simultáneamente una notificación instantánea al propietario vía Telegram. Cuenta con un tiempo de espera de 30 segundos para limitar la frecuencia de las alarmas repetidas; este mecanismo no comprueba la validez de las detecciones del sensor PIR ni elimina las falsas detecciones. Ideal para seguridad del hogar, vigilancia de garajes, almacenes o salas de trabajo. Con ESP32

ESP32 HTTPClient + API del tiempo (con pantalla LCD)
En este proyecto, utilizamos el ESP32 para realizar una llamada a la API REST de la página web de información meteorológica (wttr.in) a través de Internet, utilizando HTTPClient.h. Analizamos la respuesta JSON devuelta con ArduinoJson v7 y mostramos la información sobre la ciudad, la temperatura, la humedad, el tiempo y el viento en una pantalla LCD I2C, tanto en turco como en inglés. wttr.in es gratuito y no requiere clave API: basta con escribir el nombre de cualquier ciudad para obtener su
Más artículos
App BlueGrays
Monta este circuito paso a paso en tu teléfono
Esquema, código y lista de piezas en una sola pantalla. Más de 200 proyectos de Arduino, ESP32 y Pico listos para montar.
Escanea con tu teléfono
Apunta la cámara al código y se abrirá la tienda de apps de tu teléfono.
o ábrela en la tienda

