Una estación meteorológica básica es un sistema que mide variables ambientales y presenta sus valores. En este proyecto leeremos la temperatura y la humedad relativa y las mostraremos en una pantalla LCD.
Aunque es tentador usar el sensor azul barato (DHT11), en este nivel recomendamos encarecidamente el DHT22 (el blanco). La diferencia de precisión y rango es abismal por apenas unos céntimos de diferencia.
Protocolos de comunicación
Aquí nos enfrentamos a dos retos de comunicación distintos:
- El sensor: La familia DHT utiliza un protocolo propietario por un solo cable de datos (no es el bus 1-Wire de Dallas/Maxim). Arduino envía un pulso de inicio y después mide una serie de pulsos que codifican la temperatura y la humedad.
- La Pantalla (I2C): Las pantallas LCD antiguas requerían 6 u 8 cables para funcionar. Nosotros usaremos un módulo I2C. Este protocolo nos permite controlar la pantalla usando solo 2 cables (SDA y SCL), gracias a que cada dispositivo tiene una dirección única (como una IP, pero en hardware).
Componentes
- [1x|blue] Arduino Uno | El cerebro del proyecto
- [1x|green] Sensor DHT22 (AM2302) | Temperatura y humedad {más preciso que DHT11}
- [1x|purple] Pantalla LCD 16x2 con adaptador I2C | Visualización de datos
- [1x|gray] Resistencia 4.7kΩ o 10kΩ | Solo si el DHT22 viene suelto {pull-up}
- [Varios|gray] Protoboard y cables | Conexiones
Esquema de conexión
Vamos a conectar dos dispositivos simultáneamente.
Sensor DHT22
El DHT22 usa un único cable de datos. Si el sensor viene suelto, añadimos una resistencia de pull-up entre VCC y DATA.
[ { “from”: “DHT22 VCC”, “to”: “5V Arduino”, “color”: “red” }, { “from”: “DHT22 GND”, “to”: “GND Arduino”, “color”: “black” }, { “from”: “DHT22 DATA”, “to”: “Pin 2”, “color”: “green”, “note”: “Pull-up 4.7kΩ si viene suelto” } ]
Pantalla LCD I2C
La pantalla comparte el bus I2C del Arduino Uno/Nano: SDA en A4 y SCL en A5.
[ { “from”: “LCD I2C SDA”, “to”: “Pin A4”, “color”: “blue”, “note”: “Bus I2C” }, { “from”: “LCD I2C SCL”, “to”: “Pin A5”, “color”: “purple”, “note”: “Bus I2C” }, { “from”: “LCD I2C VCC”, “to”: “5V Arduino”, “color”: “red” }, { “from”: “LCD I2C GND”, “to”: “GND Arduino”, “color”: “black” } ]
En el Arduino UNO R3, los pines SDA y SCL también están duplicados cerca del botón de reset, etiquetados explícitamente. Son los mismos que el A4 y A5.
El código
Para que esto funcione sin volvernos locos decodificando bits, necesitamos dos librerías estándar que debéis instalar desde el Gestor de Librerías del IDE:
DHT sensor library(de Adafruit).- Una librería
LiquidCrystal_I2Ccompatible con tu adaptador. Existen varias implementaciones con ese nombre, así que comprueba que sus ejemplos usanlcd.init()y el mismo constructor que este código.
El tiempo entre lecturas
Los sensores DHT son “lentos”. El DHT22 tiene una tasa de muestreo de 0.5 Hz (una lectura cada 2 segundos). Si intentamos leerlo más rápido, nos devolverá errores o datos antiguos.
Por eso, no podemos bombardear al sensor en cada ciclo del loop. Usaremos millis() para leer solo cada cierto tiempo, dejando al procesador libre para hacer otras cosas (como actualizar la pantalla o parpadear un LED).
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
// --- Configuración Hardware ---
const int PIN_DHT = 2;
#define TIPO_DHT DHT22 // Si usas el azul, cambia a DHT11
// Dirección I2C del LCD: suele ser 0x27 o 0x3F.
// Si no funciona, pasa un escáner I2C para encontrarla.
LiquidCrystal_I2C lcd(0x27, 16, 2);
DHT dht(PIN_DHT, TIPO_DHT);
// --- Variables de Tiempo ---
unsigned long tiempoAnterior = 0;
const unsigned long INTERVALO_LECTURA = 2500UL; // Leer cada 2.5 segundos
// Icono personalizado para el símbolo de GRADOS (°)
byte simboloGrados[8] = {
0b00110,
0b01001,
0b01001,
0b00110,
0b00000,
0b00000,
0b00000,
0b00000
};
void setup() {
Serial.begin(9600);
// Inicializar Sensor
dht.begin();
// Inicializar Pantalla
lcd.init();
lcd.backlight(); // Encender la luz de fondo
// Crear el carácter personalizado en la memoria del LCD (posición 0)
lcd.createChar(0, simboloGrados);
// Mensaje de bienvenida
lcd.setCursor(0, 0);
lcd.print("Estacion Met.");
lcd.setCursor(0, 1);
lcd.print("Iniciando...");
delay(2000);
lcd.clear();
}
void loop() {
unsigned long tiempoActual = millis();
// Solo leemos si ha pasado el tiempo estipulado
if (tiempoActual - tiempoAnterior >= INTERVALO_LECTURA) {
tiempoAnterior = tiempoActual;
leerYMostrarDatos();
}
}
void leerYMostrarDatos() {
// Leemos humedad y temperatura
float humedad = dht.readHumidity();
float temperatura = dht.readTemperature();
// Comprobamos si la lectura falló (isnan = is not a number)
if (isnan(humedad) || isnan(temperatura)) {
Serial.println("Error leyendo del sensor DHT!");
lcd.setCursor(0, 0);
lcd.print("Error Sensor ");
return;
}
// --- Mostrar en Serial (Debugging) ---
Serial.print("Humedad: ");
Serial.print(humedad);
Serial.print(" %\t");
Serial.print("Temp: ");
Serial.print(temperatura);
Serial.println(" *C");
// --- Mostrar en LCD ---
// Línea 0: Temperatura
lcd.setCursor(0, 0);
lcd.print("Temp: ");
lcd.print(temperatura, 1); // 1 decimal
lcd.write(0); // Escribimos nuestro símbolo de grados
lcd.print("C "); // Espacios extra para limpiar residuos
// Línea 1: Humedad
lcd.setCursor(0, 1);
lcd.print("Hum: ");
lcd.print(humedad, 1);
lcd.print("% ");
}
Análisis
Observa tres detalles importantes en este código:
- Gestión de errores (
isnan): Nunca asumimos que el hardware funciona. Si el cable se suelta, el sensor devuelveNaN. Si no lo detectamos, la pantalla mostraría cosas raras. - Formateo de salida: Al imprimir en LCD, usamos
lcd.print(variable, 1)para limitar a un solo decimal. No tiene sentido físico mostrar “23.4532ºC” con un sensor de 5€. - Refresco limpio: Escribimos espacios en blanco al final de las líneas (
"C "). Esto es un truco muy viejo: si la temperatura baja de “100.0” a “99.0”, los espacios borran el último dígito sobrante sin tener que usarlcd.clear(), que suele provocar un parpadeo molesto.
Siguientes pasos
Esta estación es pasiva: solo muestra lo que mide. Estas son algunas ampliaciones posibles:
- Presión atmosférica: Añadir un sensor BMP280 (también usa I2C) y registrar la tendencia de presión. Una caída puede acompañar cambios meteorológicos, pero por sí sola no permite hacer una predicción fiable.
- Registro de datos (Datalogger): Conectar un módulo de tarjeta MicroSD para guardar los datos en un CSV y analizarlos en Excel después.
- Salto al IoT: Cambiar el Arduino Uno por un ESP32. La idea es similar, aunque tendrás que adaptar pines y librerías para enviar los datos a un servicio o a Home Assistant.