La app del tiempo en el celular te dice el pronóstico del aeropuerto, que puede estar a 20 km de tu casa. Si vives en Santiago sabes que la temperatura del centro no tiene nada que ver con la de la precordillera. La solución de maker es simple: mide tú mismo el clima dentro (o justo afuera) de tu casa y súbelo a la nube para consultarlo desde donde estés.
En este tutorial vas a construir una estación meteorológica de interior con un ESP32 que mide temperatura, humedad, presión barométrica e intensidad de luz, muestra todo en una pantalla OLED y publica los datos cada 5 segundos en la nube gratuita de CircuitDigest. Como bonus, dispara una alerta por SMS cuando la temperatura supera un umbral y usa la tendencia de presión para adelantar un pronóstico simple de lluvia. Al terminar vas a entender cómo se combinan varios sensores I2C en un mismo bus, cómo funciona la histéresis en un sistema de alertas y cómo enviar datos a un dashboard en la nube.
Cómo funciona el sistema
El ESP32 lee cada 2 segundos los cuatro sensores y refresca el OLED; cada 5 segundos empuja las lecturas a la nube. Hay tres detalles que elevan este proyecto por sobre un simple "leer y mostrar":
- Pronóstico por barómetro, no por valor absoluto. No importa cuánta presión hay ahora, sino cómo cambia. Una caída de 1,5 hPa o más en unas 3 horas es la firma clásica de un frente de baja presión acercándose, es decir, lluvia probable. El código guarda un historial circular de presión y compara el valor actual contra el más antiguo de la ventana.
- Contraste automático del OLED. El sensor de luz BH1750 mide los lux del ambiente y el firmware mapea ese valor al contraste de la pantalla: de noche baja el brillo, de día lo sube. Es el mismo principio del brillo automático de tu teléfono.
- Alerta con histéresis. El SMS se dispara al pasar 40 °C, pero el sistema no vuelve a "armarse" hasta que la temperatura baja de 38 °C. Ese margen de 2 °C evita que el ruido de la medición te inunde de mensajes cuando la temperatura queda oscilando justo en el umbral.
Hardware y conexiones
Todo el montaje gira en torno a un bus I2C compartido. El BME/BMP280, el BH1750 y el OLED cuelgan de los mismos pines SDA (GPIO 21) y SCL (GPIO 22) del ESP32, cada uno con su propia dirección. El DHT11 va aparte, en el GPIO 23 (es un sensor digital de un solo hilo, no I2C), y el buzzer en el GPIO 4.

Resumen del cableado:
- SDA de BMP280, BH1750 y OLED → GPIO 21 del ESP32
- SCL de BMP280, BH1750 y OLED → GPIO 22 del ESP32
- Datos del DHT11 → GPIO 23
- Señal del buzzer → GPIO 4
- VCC/3.3V y GND comunes a todos, tomados del ESP32
- El pin ADDR del BH1750 y el SDO del BMP280 van a GND (fijan su dirección I2C baja); el CSB del BMP280 va a 3.3V para forzar modo I2C
Dato técnico: al colgar tres dispositivos del mismo bus conviene bajar la velocidad I2C a 100 kHz. A 400 kHz, con cables de protoboard largos y varias cargas, aparecen errores de comunicación intermitentes. Si el módulo que usas no trae las resistencias pull up de 4,7 kΩ en SDA y SCL, tendrás que agregarlas tú.
El software
El proyecto se compila en el Arduino IDE. Empieza por instalar las librerías: Adafruit SSD1306, Adafruit GFX, BH1750 de Christopher Laws, Adafruit BMP280 y la librería CircuitDigestCloud (que maneja el WiFi y el TLS por dentro). Las cabeceras que incluye el sketch son:
#include <WiFi.h> // only used here for the plain SMS HTTP request
#include <DHT.h>
#include <DHT_U.h>
#include <CircuitDigestCloud.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <BH1750.h>
#include <Adafruit_BMP280.h>
Al arrancar el bus I2C fijas los pines y la velocidad:
Wire.begin(21, 22); // SDA on GPIO 21, SCL on GPIO 22 (ESP32 Defaults)
Wire.setClock(100000); // Set standard 100kHz I2C clock speed
El corazón del pronóstico compara la presión actual contra la más vieja del historial y clasifica la tendencia:
int oldestIndex = (pressureHistoryIndex + PRESSURE_HISTORY_LEN - pressureHistoryCount) % PRESSURE_HISTORY_LEN;
float oldest = pressureHistory[oldestIndex];
float trend = pressureHpa - oldest; // hPa change over the buffered window
if (trend >= 1.5) {
forecastText = "Rising";
} else if (trend <= -1.5) {
forecastText = "Falling";
} else {
forecastText = "Steady";
}
El brillo del OLED se ajusta mapeando los lux a un valor de contraste (invertido: menos luz ambiente, pantalla más brillante):
float clamped = constrain(luxLevel, LUX_MIN_FOR_SCALE, LUX_MAX_FOR_SCALE);
uint8_t contrast = map((long)clamped, (long)LUX_MIN_FOR_SCALE, (long)LUX_MAX_FOR_SCALE,
OLED_CONTRAST_MAX, OLED_CONTRAST_MIN);
display.ssd1306_command(SSD1306_SETCONTRAST);
display.ssd1306_command(contrast);
Y la lógica de alerta con histéresis, que evita el spam de SMS:
// --- SMS alert logic with hysteresis ---
if (!alertActive && temperature >= SMS_TRIGGER_TEMP) {
sendSMS();
alertActive = true; // Locks the alert state
} else if (alertActive && temperature < SMS_RESET_TEMP) {
alertActive = false; // Re-arms the system for the next trip
smsStatusText = "Monitoring...";
updateDisplay();
}
Finalmente, cada 5 segundos se publican las cuatro variables al dashboard en la nube:
if (now - lastPublish >= PUBLISH_INTERVAL) {
lastPublish = now;
cd.publish({{TEMPERATURE_SLOT, temperature}, {LUX_SLOT, luxLevel}, {HUMIDITY_SLOT, humidity}, {PRESSURE_SLOT, pressureHpa}});
}
Configurar la nube de CircuitDigest
La parte IoT vive en un dashboard gratuito. El flujo es: crear una cuenta, registrar el dispositivo, definir las variables y armar los widgets que las visualizan.
1. Registra el dispositivo. Entra a tu cuenta de CircuitDigest Cloud, ve a Device en el menú izquierdo y presiona Add New Device. Ponle un nombre (por ejemplo, ESP32_Weather_Station).

2. Crea las variables. En Variables, agrega cuatro: temperatura (temperature-1), humedad (humidity-1), intensidad de luz (analog-input-1) y presión (level-1). Estas keys son las que el código usa para publicar, así que deben coincidir exactamente.

3. Arma los widgets. En el Dashboard, agrega un widget por variable: medidores tipo gauge para temperatura y humedad, y value display para luz y presión.

4. Activa las alertas SMS. Baja a la sección API del sitio, vincula tu número y copia tu API key y Template ID al código. Con eso, cuando salte el umbral de 40 °C te llega el mensaje al celular.

Prueba y resultado
Con el código cargado y el dashboard listo, el OLED empieza a mostrar temperatura, presión, pronóstico, lux y el estado del SMS, mientras las mismas lecturas aparecen en la nube en tiempo real. Si la temperatura llega al umbral, suena el buzzer y sale el SMS una sola vez, hasta que baje de 38 °C.

Solución de problemas rápida
- El buzzer no suena: confirma que es un módulo activo y que la señal va al GPIO 4. Algunos módulos se activan en HIGH y otros en LOW; si suena solo al encender, invierte
BUZZER_ON_LEVEL. - No conecta al WiFi: revisa el SSID y la clave al inicio del sketch.
- El OLED queda en blanco: verifica que SDA esté en GPIO 21 y SCL en GPIO 22, y que la dirección I2C (0x3C, a veces 0x3D) sea la de tu módulo.
- No llega el SMS: confirma el número con prefijo de país y que la API key y el Template ID coincidan con tu cuenta.
Variantes y mejoras
Algunas ideas para llevar este proyecto más lejos, que no están en el diseño original:
- Alertas por Telegram en vez de SMS. Si no quieres depender de un gateway de SMS, crea un bot de Telegram y usa la librería
UniversalTelegramBot. Reemplazas la función de envío por una llamada al bot y recibes las alertas (con gráfico incluido) gratis y sin límite de mensajes. - Registro histórico en microSD. Agrega un módulo microSD por SPI y guarda cada lectura con marca de tiempo (usando un RTC DS3231). Así puedes graficar después la evolución del clima de tu casa por semanas.
- Cambia el DHT11 por un BME280 y elimina un sensor. El BME280 mide temperatura, humedad y presión en un solo chip I2C. Usándolo, te ahorras el DHT11 y el BMP280 por separado, reduces el cableado y ganas precisión (el DHT11 es el eslabón más impreciso de la cadena).
Personalización para Chile
En Chile puedes conseguir todo lo necesario en MechatronicStore. Estos son los componentes en stock que arman este proyecto:
- ESP32 (ESP WROOM-32, USB-C) (SKU X2-10V2). $7.990 CLP
- Módulo sensor DHT-11 (SKU GO3-11). $1.990 CLP
- Sensor de intensidad luminosa BH1750 (GY-302) (SKU GN1-6). $3.990 CLP
- Módulo buzzer activo (SKU X10-9). $1.190 CLP
- Sensor BME280 I2C (SKU GR1-10). $8.690 CLP · el catálogo no trae el BMP280 exacto; el BME280 es de la misma familia Bosch, comparte el bus I2C y las direcciones 0x76/0x77, y mide presión igual (además de humedad). Solo cambia
Adafruit_BMP280porAdafruit_BME280en el código. - Pantalla OLED I2C 0.91" 128x32 SSD1306 (SKU D-112). $3.990 CLP · el tutorial usa una de 0.96" 128x64; esta usa el mismo driver SSD1306 por I2C, pero deberás ajustar
SCREEN_HEIGHTa 32 y compactar el diseño en pantalla.
Con esta combinación, el costo total ronda los $27.840 CLP. Si el módulo BME280 ya te entrega humedad y presión, puedes prescindir del DHT11 y bajar aún más el conteo de piezas.
Recursos
- Tutorial original (inglés): IoT Indoor Weather Station Using ESP32 & CircuitDigest Cloud
- Repositorio GitHub: ESP32_Weather_Station
- Plataforma en la nube: CircuitDigest Cloud
Versión chilena con componentes en stock local en MechatronicStore, inspirada en el proyecto de Mohammed Shaheen K S para Circuit Digest.




