Componentes · 17 min de lectura

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.

Módulo sensor de lluvia (FC-37 / YL-83) con placa de control LM393
Kit de sensor de lluvia: a la izquierda, la placa sensora YL-83 con pistas entrelazadas; a la derecha, la placa de control con el comparador LM393, el potenciómetro de sensibilidad y los LED PWR y DO; entre ambas, el cable de conexión.

¿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ísticaValor
Placa sensoraUnos 5,4 × 4 cm; pistas entrelazadas sobre FR4, niqueladas en la mayoría de los modelos
Placa de controlUnos 3 × 1,5 cm, comparador LM393
Tensión de alimentación3,3–5 V
ConsumoUnos 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
IndicadoresLED PWR (alimentación) y LED DO (lluvia detectada)
AjustePotenciómetro de sensibilidad (solo cambia el umbral de DO)
Conexiones2 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ísticaDO (digital)AO (analógica)
Qué indicaLlueve / no llueveCuánto se ha mojado la placa (0–1023 en el Uno)
Ajuste del umbralPotenciómetro de la placaEn el código, como quieras
Pin de ArduinoCualquier pin digitalPin analógico (A0–A5)
Distingue la intensidadNoSí (llovizna, lluvia, aguacero)
Uso con interrupcionesSíNo
Ideal paraAlarmas sencillas, señal para despertarMedir niveles, automatización con histéresis

Conexión del sensor de lluvia: Arduino Uno, ESP32 y Pico

Pin del módulo / piezaArduino UnoESP32Raspberry Pi Pico
VCCD7 (para alimentarlo solo al medir) o 5VGPIO 25 o 3V3GP15 o 3V3(OUT)
GNDGNDGNDGND
AOA0GPIO 34 (ADC1)GP26 (ADC0)
DOD2Opcional (p. ej., GPIO 27)GP14
Zumbador activo (+)D8OpcionalGP13
Cable de señal del servoD9OpcionalGP16
Los pines del ESP32 y de la Raspberry Pi Pico admiten como máximo 3,3 V. Si en estas placas alimentas el módulo desde 5V, VIN o VBUS, las salidas AO y DO suben a 5 V con la placa seca y pueden dañar las entradas. Alimenta el módulo con 3,3 V o a través de un pin GPIO. En el ESP32, conecta siempre AO a uno de los pines ADC1 (GPIO 32–39); los pines ADC2 no se pueden leer con el Wi-Fi activado.

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

  1. Seca bien la placa sensora y alimenta el módulo; el LED PWR debe estar encendido y el LED DO apagado.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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".
Si haces las pruebas con agua del grifo, tómate el resultado con cautela: los minerales disueltos hacen que el agua del grifo suela ser varias veces más conductora que el agua de lluvia. Un umbral que funciona perfecto con agua del grifo puede reaccionar tarde ante una llovizna real. El ajuste más preciso se hace el primer día de lluvia, leyendo los valores reales en el Monitor Serie; hasta entonces, rociar gotitas finas con un pulverizador imita la lluvia mucho mejor que poner la placa bajo el grifo.

Paso a paso: tu primera lectura con Arduino

  1. 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.
  2. Abre el código de abajo en el Arduino IDE, elige Arduino Uno como placa y súbelo.
  3. Abre el Monitor Serie a 9600 baudios y anota el valor de AO con la placa seca.
  4. Echa primero unas gotas de agua sobre la placa, luego más, y apunta el valor de AO cada vez.
  5. 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.
C++ (Arduino IDE)
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 placaAO aprox. (Uno, 5 V)DO (placa ajustada)
Seca y limpia1000–1023HIGH
Unas pocas gotas750–950HIGH o LOW según el ajuste
Llovizna, placa mojada en parte500–750LOW
Lluvia intensa300–500LOW
Totalmente mojada, agua del grifo150–350LOW

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?.

C++ (Arduino IDE)
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?.

SG90 servo motor
SG90 servo motor
Zumbador activo
Zumbador activo
C++ (Arduino IDE)
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}
ConstanteFunciónValor inicial
DRY / WETLos valores de placa seca y mojada que mediste tú1015 / 350
RAIN_ONA partir de este porcentaje se considera que "llueve"25 %
RAIN_OFFPor debajo de este porcentaje (incluido) se considera "seco"8 %
CONFIRM_COUNTLecturas mojadas seguidas necesarias para cerrar la ventana3 (unos 6 s)
DRY_MSTiempo que la placa debe seguir seca antes de abrir la ventana10 minutos
OPEN_ANGLE / CLOSED_ANGLEÁngulo del servo en posición abierta y cerrada90° / 0°
Un SG90 puede consumir unos cientos de mA mientras se mueve; si usas varios servos o uno grande como el MG996R, aliméntalos con una fuente de 5 V aparte en lugar del pin 5V del Arduino y une las masas. Para una ventana o un toldo reales un servo no basta: necesitas un motor con reductora o un actuador lineal, finales de carrera en ambos extremos y una protección contra atrapamientos. Este código sirve para aprender la lógica que controla el mecanismo y probarla en una maqueta.

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.

C++ (Arduino IDE)
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.

MicroPython
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?SalidaUso típico
Sensor de lluvia (FC-37, YL-83)Gotas de agua que caen en su superficieAO y DOAlarma de lluvia, automatización de ventanas y toldos
Sensor de humedad del sueloHumedad de la tierraAO y DO (misma placa LM393)Riego de plantas
Sensor de nivel de agua (pistas paralelas)Altura del agua en un recipienteAnalógica (S)Nivel de depósitos y acuarios
Pluviómetro de balancínCantidad de lluvia (mm)Un pulso por cada vuelcoEstación meteorológica
Sensor de humedad del suelo con la misma placa LM393
Sensor de humedad del suelo con la misma placa LM393
Sensor de nivel de agua
Sensor de nivel de agua

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íntomaCausa probableSolución
AO siempre marca 1023 y no cambiaEl cable de la placa sensora está suelto o roto; en A0 está DO en lugar de AORevisa 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 secaLa placa está sucia o aún mojada; algo une las pistas; se lee antes de encender el móduloLimpia y seca la placa; en el código, lee solo después de alimentar y esperar
DO nunca cambiaEl potenciómetro está girado hasta un topeRepite desde el principio los pasos de ajuste de la sensibilidad
Alarma de lluvia con tiempo secoRocío, niebla, placa sucia o umbral demasiado sensibleSube 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 despacioMonta la placa inclinada, ajusta RAIN_OFF y DRY_MS
Los valores se desplazaron en semanas y las pistas se oscurecieronCorrosión por alimentación continuaAlimenta el módulo desde un pin, mide con menos frecuencia, cambia la placa sensora
En el ESP32 las lecturas fallan al activar el Wi-FiAO está en un pin ADC2Pasa AO a un pin entre GPIO 32 y 39
El servo tiembla o el Arduino se reiniciaLa corriente del servo hace caer la línea de 5 VAlimenta el servo con una fuente de 5 V aparte, une las masas y añade un condensador de 470 µF en la alimentación
La forma más fácil de probar tu sistema sin esperar a que llueva es pasar un dedo mojado o un pañuelo húmedo por las pistas de la placa. Para una prueba más realista, rocía la placa varias veces con un pulverizador desde 30–40 cm; en el Monitor Serie verás cómo sube el porcentaje de humedad y cómo baja poco a poco mientras la placa se seca.

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.

Ver todos los proyectos
Uso del zumbador
#13Principiante

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

4.7(89)
161
Temperatura y humedad con DHT11
#55Intermedio

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

4.7(47)
73
Uso del servomotor
#35Principiante
Premium

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

4.7(48)
67
Estación de riego inteligente
#83Avanzado
Premium

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

5.0(42)
57
Uso del sensor de llama
#50Intermedio
Premium

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

4.6(33)
44
Sistema de Alarma de Movimiento ESP32 (PIR + Buzzer + LED + Telegram)
#145Avanzado
Premium

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

0.0(0)
9
ESP32 HTTPClient + API del tiempo (con pantalla LCD)
#133Avanzado
Premium

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

4.7(13)
20