Predicción Precisa de Lluvia: Construye un Sistema con Arduino, Python y Keras
Componentes y materiales
| Componente | Cantidad |
|---|---|
| Caja plástica pequeña con tapas desmontables (la mía tiene tornillos) | 1 |
| Portapilas para 3 pilas AAA | 1 |
| 3 pilas AAA recargables (NiMH) | 1 |
| Panel solar pequeño 6V | 1 |
| Arduino Pro Mini 328 – 5V/16MHz | 1 |
| Diodo 1N4004 | 1 |
| Transistor NPN de uso general + resistencia 1kΩ | 1 |
| Sensor de lluvia | 1 |
| Módulo comunicación serie HC-12 | 1 |
| Módulo USB serie HC-12 (para estación base) | 1 |
| Sensor atmosférico BME280 (SparkFun) | 1 |
| Sensor de luz BH1750 | 1 |
| PCB, cables, estaño, conector KF301-2P, conectores macho/hembra PCB, pegamento | 1 |
| Regulador 3.3V | 1 |
Herramientas necesarias
- Adaptador USB-serie FTDI FT232RL (para programar el Pro Mini)
- Taladro
- Soldador
- Destornilladores
Sobre el proyecto
El objetivo principal es predecir si lloverá en las próximas 6 horas (sí/no). No encontré tutoriales completos, así que este proyecto abarca todos los aspectos:
- Construir la estación meteorológica: totalmente off-grid con panel solar y consumo ultrabajo (unas decenas de µA/h).
- Programar la estación para que recoja datos y los transmita cada 10 minutos a una estación base.
- Recopilar los datos en la base y almacenarlos en una base de datos.
- Usar redes neuronales (Keras) y librerías Python (pandas) para filtrar, limpiar, preprocesar los datos y entrenar un modelo de predicción.
- Predecir si lloverá en las próximas 6 horas y notificar por email.


Con unos 600 días de datos, el sistema alcanza ~80 % de precisión (depende de parámetros). Este tutorial os guiará paso a paso para predecir lluvia desde cero, sin APIs externas de meteorología ni machine learning. Aprenderéis a construir una estación práctica (bajo consumo, off-grid), programarla con Arduino IDE, recopilar datos en una base de datos en la estación base (servidor), y procesarlos con Pandas y Keras.
Paso 1: Piezas y herramientas para construir la estación
Piezas: (listadas en la tabla anterior). La caja debe tener unos 11x7x5 cm. La estación base puede ser un PC o placa de desarrollo siempre encendida.
Herramientas: adaptador FTDI, Arduino IDE, taladro, sierra de hoja fina, destornilladores, soldador, cortaalambres.
Habilidades: soldadura, programación básica Arduino, configuración de servicios Linux, instalación de paquetes, algo de programación.
Paso 2: Construcción de la estación meteorológica
La estación consta de: caja con panel solar pegado, PCB con electrónica, portapilas, y sensores BME280, luz y lluvia en el exterior.
- Taladrad 4 agujeros en la caja: uno para cables del panel, tres para sensores exteriores. Pegad el panel y pasad sus cables al interior.
- En el PCB: soldad conectores hembra para el Arduino, soldad conectores macho al Arduino y colocadlo. Importante: quitad el LED del Arduino (o al menos un pin) porque consume mucha energía. Soldad transistor, resistencia, regulador 3.3V, dos conectores KF301-2P (panel y baterías), tres conectores hembra para sensores, y cables pequeños según fotos y esquema Fritzing.
- Colocad 3 pilas AAA NiMH cargadas en el portapilas, conectad a su conector KF301-2P.
- Conectad BME280 y sensor de luz desde fuera a sus conectores macho. Para el sensor de lluvia, soldad 3 cables (GND, VCC, señal) y al otro lado pines macho para conectar dentro.
- Colocad la estación en su posición final: protegida de lluvia/nieve. Usad cables más largos para el sensor de lluvia y colocadlo aparte en un soporte estable. Fijad la caja con cinta adhesiva fuerte.
sketch.fzz (archivo Fritzing)
Paso 3: Código Arduino
La estación transmite datos de sensores cada 10 minutos. El programa:
- Lee sensores: humedad, temperatura, presión, lluvia, luz, voltaje.
- Transmite datos codificados por puerto serie software. Formato:
H1:78|T1:12|PS1:1022|L1:500|R1:0|V1:4010|(humedad 78 %, temp 12 °C, presión 1022 hPa, luz 500 lux, lluvia 0, voltaje 4010 mV). - Apaga componentes auxiliares (sensores y módulo comunicación).
- Pone el Arduino en modo sleep 10 minutos (<50 µA).
- Reactiva componentes y repite.
Extra: si voltaje > 4.2 V usa delay() normal (consumo alto) para bajar voltaje rápido y evitar sobrecarga de baterías por el panel solar.
Código completo en GitHub: repositorio. Eliminad la línea transmitSenzorData("V", sensors.voltage); antes de subir.
Librerías necesarias (instalad desde el Gestor de librerías o GitHub):
Paso 4: Preparar la estación base
Ordenador Linux (escritorio, portátil o placa de desarrollo) con módulo HC-12 USB conectado. Debe estar siempre encendido para recoger datos cada 10 min.
- Instalar Anaconda (gestor de paquetes Python). Tutorial: DigitalOcean (pasos 1-8).
- Instalar MongoDB (base de datos principal). Guía: MongoDB 3.4. Opcional: índice en campo
date:db.weather_station.createIndex({"date": 1}). - Descargar proyecto:
git clone https://github.com/danionescu0/home-automation.git(carpetaweather-predict). - Crear entorno Anaconda e instalar dependencias:
Paquetes clave: Keras, pandas, pymongo, scikit-learn.cd weather-predict conda create --name weather python=3.6.2 conda activate weather pip install -r requirements.txt
Configurar el proyecto
Archivo config.py en weather-predict:
- Si MongoDB está en otro host/puerto, cambiad
mongodb.hostymongodb.port. - Conectad el adaptador HC-12 USB. Ejecutad
ls -l /dev/tty*antes y después de enchufar para identificar el puerto (ej./dev/ttyUSB0). Actualizadserial.portyserial.baud_rate(9600).
Paso 5: Usar la estación en la práctica



Importar mis datos de prueba (MongoDB):
mongoimport -d weather -c weather_station --file sample_data/weather_station.json
Advertencia: combinar mis datos con los vuestros puede bajar precisión por diferencias de hardware y clima local.
Recopilar nuevos datos (escucha puerto serie y guarda en BD):
conda activate weather
python serial_listener.py
# Cada 10 min veréis: [Sensor: type(temperature), value(14.3)] ...
Generar modelo de predicción:
conda activate weather
python train.py --days_behind 600 --test-file-percent 10 --datapoints-behind 8 --hour-granularity 6
--days_behind: días hacia atrás para entrenar.--test-file-percent: % datos para test.--hour-granularity: horas a futuro para predecir (6).--datapoints-behind: puntos de datos pasados a considerar (ver siguiente sección).
Ver gráficos de sensores (últimos 10 días):
conda activate weather
python graphs --days-behind 10
Predecir lluvia y enviar email:
conda activate weather
python predict.py --datapoints-behind 8 --hour-granularity 6 --from-addr tu_gmail --from-password pass --to-addr destino
Para predicción en lote sobre datos de test:
python predict_batch.py -f sample_data/test_data.csv
Importante: usar mismos parámetros que en train.py. Para email, activad «Acceso de apps menos seguras» en Gmail. Necesitáis dos direcciones: una Gmail con esa opción y otra para recibir notificaciones. Para automatizar, añadid a crontab.
Paso 6: ¿Cómo funciona? (Arquitectura y Machine Learning)
1. Visión general
Dos partes separadas: estación meteorológica (solo recolecta y transmite) y estación base (recopila, entrena, predice).
Ventajas de la separación: menores requisitos de energía en la estación, portabilidad, escalabilidad (múltiples estaciones), bajo coste.
Base de datos: MongoDB (schemaless, gratis, API fácil). Cada entrada:
{ "_id": "04_27_2017_06_17", "humidity": 65, "date": ISODate("2017-04-27T06:17:18Z"), "pressure": 1007, "temperature": 9, "rain": 0, "light": 15 }
Agregado por minuto. La estación envía un datapunto cada 10 min.
Procesamiento y red neuronal: Python (ecosistema ML). Pandas para manipulación de datos; Keras (wrapper alto nivel sobre TensorFlow) para red neuronal en pocas líneas.
2. Conceptos básicos de Machine Learning
Redes neuronales imitan neuronas biológicas. Cada neurona tiene un «punto de activación» (bias) y cada conexión un peso. Proceso de «aprendizaje» en bucle: estimular entradas, propagar, comparar salida con objetivo, ajustar pesos (backpropagation), repetir.
Usamos aprendizaje supervisado: enseñamos entradas y salidas para que dada nueva entrada prediga la salida.
3. Preparación de datos (paso crucial)
- Obtener datos crudos de MongoDB (fácil con PyMongo).
- Limpieza: eliminar valores nulos (
dataframe.dropna()). - Agrupación y enriquecimiento: agrupar datapuntos en intervalos de 6 horas. Calcular para cada sensor (humedad, lluvia, temp, luz, presión): min, max, media, percentiles 10/30/70/90, nº subidas, bajadas, estables.
- Añadir columna
has_rain(0/1) segúnrain_avg > 0.1. - Eliminar columna
datey filas contemperature_min < 0(no hay sensor de nieve). - Enriquecimiento temporal: para cada fila, añadir columnas de filas pasadas (ej.
temperature_1,temperature_2…). Óptimo: 8 datapuntos pasados (48 horas). - Eliminar filas iniciales con NaN y datos del datapunto actual (excepto
has_rain). - Dividir train/test (sklearn
train_test_split). - Separar inputs (X) y output (y).
- Reescalar a [0,1] con
StandardScalery guardar scaler (joblib.dump).
4. Red neuronal con Keras
from keras.models import Sequential
from keras.layers import Dense, Dropout
input_dimensions = X.shape[1]
model = Sequential()
inner_nodes = int(input_dimensions / 2)
model.add(Dense(inner_nodes, activation='relu', input_dim=input_dimensions, kernel_initializer='uniform'))
model.add(Dropout(0.05))
model.add(Dense(inner_nodes, activation='relu', kernel_initializer='uniform'))
model.add(Dropout(0.05))
model.add(Dense(1, activation='sigmoid', kernel_initializer='uniform'))
model.compile(optimizer='rmsprop', loss='mean_absolute_error', metrics=['accuracy'])
model.fit(X, y, batch_size=1, epochs=50)
model.save('file_model_name')
Capas: entrada, dos ocultas con Dropout (evita overfitting), salida sigmoide (binaria). Parámetros ajustables: funciones activación, loss, optimizador, batch_size, epochs. No hay configuración óptima universal; hay que tunear.
5. Mejoras futuras
- Estación: añadir sensor viento velocidad/dirección, UV, gases, partículas; más estaciones; años de datos.
- Procesamiento: incorporar datos externos (ej. Weather Underground), optimizar arquitectura Keras (capas, neuronas, dropout, métricas, optimizador, loss, batch, epochs), probar LSTM.
- Búsqueda de hiperparámetros:
python train.py ... --grid-search(explora batch_size, epochs, optimizer, dropout).
Paso 7: Bonus – Usar dataset meteorológico oficial (Dark Sky API)
Probado con datos de Dark Sky (más sensores: viento, rachas, UV, visibilidad). Precisión sube de ~80 % a ~90 %. Pasos: descargar datos (API key + coordenadas) o importar mi colección MongoDB (mongoimport -d weather -c darksky --file sample_data/darksky.json), entrenar con --data-source darksky, evaluar con predict_batch.py. El dataset marca la diferencia.
Código
Incluye snippets de Arduino, Python (entrenamiento, predicción), PHP (listener serie), y comandos de consola. Ver repositorio GitHub: home-automation.
Esquemáticos

Sketch Arduino: GitHub
Proceso de manufactura
- Construya un sensor de temperatura remoto con Raspberry Pi y Python – Guía paso a paso
- Construye una consola de control DIY para Photoshop con Arduino Nano RP2040
- Sistema de Asistencia RFID Fiable con Arduino y Python
- Mando universal Android con Arduino, 1Sheeld y control IR
- Construye un Voltímetro Inteligente con Arduino y Smartphone – Proyecto DIY Fácil
- Construye un Sensor de Ritmo Cardíaco por Infrarrojos Fiable con Arduino: Guía Paso a Paso
- Medición precisa de frecuencia y ciclo de trabajo con Arduino UNO
- Construye un voltímetro DIY con Arduino y pantalla Nokia 5110 – Guía paso a paso
- Medición de Distancia en Tiempo Real con Sonar Arduino y Visualización en Processing
- Control de brillo LED sin interrupciones con Bolt IoT y Arduino UNO
- Cómo renombrar archivos y directorios en Python con os.rename() – Guía paso a paso