📌 Resumen rápido (TL;DR)
- Guía completa sobre estación meteorológica diy con esp32 y bme280: tutorial paso a paso po: características, comparativa y aplicaciones en agricultura de precisión.
📅 Última actualización: 12 de abril de 2026
❓ Preguntas frecuentes

Resumen: Tutorial paso a paso para montar tu propia estación meteorológica agrícola con ESP32, BME280, pluviómetro y anemómetro. Versión básica por veinticinco euros, versión completa por noventa y cinco euros. Con dashboard WiFi, alertas Telegram y alimentación solar autónoma.
📅 Actualizado: marzo 2026
1. Por qué montar tu propia estación
2. Tres niveles: básica, intermedia, completa
3. Lista de componentes y presupuesto
4. Esquema de conexiones
5. Código completo con todas las funciones
6. Calibración de cada sensor
7. Dashboard web local en el ESP32
8. Alertas Telegram automáticas
9. Gráficos con ThingSpeak gratuito
10. Publicar en Weather Underground
11. Alimentación solar: funcionar sin enchufe
12. Caja y montaje exterior
13. DIY vs comercial: comparativa honesta
14. Preguntas frecuentes
🎯 Lo que conseguirás con esta guía
- ✅ Montar estación meteorológica completa por noventa y cinco euros con siete sensores
- ✅ Dashboard web desde el móvil con datos en tiempo real y actualización automática
- ✅ Alertas Telegram automáticas de helada, suelo seco, viento fuerte y batería baja
- ✅ Datos en Weather Underground y ThingSpeak con histórico exportable a CSV
- ✅ Independencia total: alimentación solar, sin cuotas, tus datos son tuyos
1. Por qué montar tu propia estación
En nuestro artículo sobre la tabla de decisión meteorológica para agricultura explicamos qué datos necesitas y qué hacer con ellos. Pero antes de tomar decisiones, necesitas los datos. Y ahí es donde entra la estación meteorológica.
💡 Pro Tip
La agricultura de precisión puede aumentar la productividad hasta un 25%. Explora todas nuestras guías. Ver más →
Una estación comercial como la ECOWITT GW1101 (noventa euros) te da todo plug-and-play: la sacas de la caja, la montas y en diez minutos tienes datos en la app. Es la opción recomendada si no quieres programar.
Pero si ya tienes experiencia con ESP32 por nuestros tutoriales de riego, montar tu propia estación tiene ventajas serias: puedes añadir sensores de humedad del suelo en la misma red, integrar con el sistema de riego automático, enviar datos a cualquier plataforma (no solo las que soporte la estación comercial), y controlar exactamente qué alertas recibes y cuándo.
2. Tres niveles: básica, intermedia, completa
| Nivel | Sensores | Coste | Ideal para |
|---|---|---|---|
| 🟢 Básica | BME280 (temp + hum + presión) | ~25 € | Empezar, aprender, probar |
| 🟡 Intermedia | BME280 + pluviómetro + sensor UV | ~55 € | Riego y protección cultivos |
| 🔴 Completa | BME280 + pluviómetro + anemómetro + UV + luz + suelo + solar | ~95 € | Gestión completa de finca |
Nuestra recomendación: empieza con la básica para aprender y probar en interior. Cuando funcione, amplía a la completa e instala en exterior con caja y alimentación solar. Los sensores se añaden uno a uno sin rehacer nada.
3. Lista de componentes y presupuesto
Versión completa (noventa y cinco euros)
| Componente | Precio | Mide |
|---|---|---|
| ESP32 DevKit V1 | ~6 € | Cerebro + WiFi |
| BME280 (I2C) | ~4 € | Temperatura + humedad + presión |
| Pluviómetro balancín | ~15 € | Precipitación (mm) |
| Kit anemómetro + veleta | ~26 € | Velocidad y dirección viento |
| Sensor UV GUVA-S12SD | ~4 € | Índice UV |
| Sensor luz BH1750 | ~4 € | Luminosidad (lux) |
| Sensor humedad suelo v1.2 | ~2 € | Humedad suelo (%) |
| Batería 18650 + TP4056 | ~5 € | Respaldo nocturno |
| Panel solar 6W 5V | ~15 € | Recarga autónoma |
| Caja IP65 + prensaestopas | ~10 € | Protección exterior |
| Mástil + garita antirradiación | ~6 € | Montaje e instalación |
| TOTAL | ~97 € | 8 variables meteorológicas |
Todos los componentes disponibles en nuestra tienda con enlaces directos a Amazon. Si ya tienes ESP32 y protoboard de tutoriales anteriores, el coste baja a unos setenta y cinco euros.
4. Esquema de conexiones
Todas las conexiones al ESP32:
| Sensor | Pin ESP32 | Protocolo | Notas |
|---|---|---|---|
| BME280 SDA | GPIO 21 | I2C | + pull-up 4.7K a 3.3V |
| BME280 SCL | GPIO 22 | I2C | Dirección 0x76 |
| BH1750 SDA | GPIO 21 | I2C | Mismo bus, dir 0x23 |
| BH1750 SCL | GPIO 22 | I2C | Mismo bus I2C |
| Pluviómetro | GPIO 27 | Interrupción | + pull-up 10K, FALLING |
| Anemómetro | GPIO 25 | Interrupción | Contar pulsos/segundo |
| Veleta | GPIO 33 | ADC | Resistencias internas |
| Sensor UV | GPIO 34 | ADC | Analógico 0-3V |
| Humedad suelo | GPIO 35 | ADC | Capacitivo v1.2 |
| Voltaje batería | GPIO 36 | ADC | Divisor 100K/100K |
Los sensores I2C (BME280 y BH1750) comparten el mismo bus: solo dos cables (SDA y SCL) para ambos. Los sensores analógicos (UV, suelo, batería, veleta) usan pines ADC diferentes. El pluviómetro y anemómetro usan interrupciones para contar pulsos.
5. Código completo con todas las funciones
#include <WiFi.h>
#include <WebServer.h>
#include <Wire.h>
#include <Adafruit_BME280.h>
#include <BH1750.h>
#include <HTTPClient.h>
// ===== CONFIGURACIÓN =====
const char* ssid = "TU_WIFI";
const char* password = "TU_PASSWORD";
const String BOT_TOKEN = "TU_BOT_TOKEN";
const String CHAT_ID = "TU_CHAT_ID";
// Pines
#define RAIN_PIN 27
#define WIND_PIN 25
#define VANE_PIN 33
#define UV_PIN 34
#define SOIL_PIN 35
#define VBAT_PIN 36
// Calibración suelo
#define SOIL_DRY 3200
#define SOIL_WET 1400
// Objetos sensores
Adafruit_BME280 bme;
BH1750 lightMeter;
WebServer server(80);
// Variables meteorológicas
float temperature, humidity, pressure;
float lux, uvIndex;
int soilMoisture;
float windSpeed, windGust;
int windDirection;
float rainHour, rainDay;
float vBat;
// Contadores lluvia y viento
volatile unsigned long rainTips = 0;
volatile unsigned long windPulses = 0;
unsigned long lastWindCheck = 0;
unsigned long lastRainReset = 0;
float rainDayTotal = 0;
// Interrupciones
void IRAM_ATTR rainISR() { rainTips++; }
void IRAM_ATTR windISR() { windPulses++; }
void setup() {
Serial.begin(115200);
Wire.begin(21, 22);
// Sensores I2C
bme.begin(0x76);
lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, 0x23);
// Interrupciones
pinMode(RAIN_PIN, INPUT_PULLUP);
pinMode(WIND_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(RAIN_PIN), rainISR, FALLING);
attachInterrupt(digitalPinToInterrupt(WIND_PIN), windISR, FALLING);
// WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) delay(500);
Serial.println("IP: " + WiFi.localIP().toString());
// Web server
server.on("/", handleRoot);
server.on("/api", handleAPI);
server.begin();
}
void loop() {
server.handleClient();
static unsigned long lastRead = 0;
if (millis() - lastRead > 10000) { // Cada 10 segundos
readAllSensors();
checkAlerts();
lastRead = millis();
}
// Reset lluvia diaria a medianoche (simplificado)
if (millis() - lastRainReset > 86400000UL) {
rainDayTotal = 0;
lastRainReset = millis();
}
}
void readAllSensors() {
// BME280
temperature = bme.readTemperature();
humidity = bme.readHumidity();
pressure = bme.readPressure() / 100.0F;
// Luz
lux = lightMeter.readLightLevel();
// UV (GUVA-S12SD: 0-1V = UV 0-11)
int uvRaw = analogRead(UV_PIN);
float uvVoltage = uvRaw * 3.3 / 4095.0;
uvIndex = uvVoltage / 0.1; // ~0.1V por índice UV
// Humedad suelo
int soilRaw = analogRead(SOIL_PIN);
soilMoisture = map(constrain(soilRaw, SOIL_WET, SOIL_DRY),
SOIL_DRY, SOIL_WET, 0, 100);
// Viento (pulsos en el periodo)
unsigned long now = millis();
unsigned long elapsed = now - lastWindCheck;
if (elapsed > 0) {
float pulsesPerSec = (float)windPulses * 1000.0 / elapsed;
windSpeed = pulsesPerSec * 2.4; // Factor calibración km/h
if (windSpeed > windGust) windGust = windSpeed;
windPulses = 0;
lastWindCheck = now;
}
// Dirección viento (veleta resistiva)
int vaneRaw = analogRead(VANE_PIN);
windDirection = map(vaneRaw, 0, 4095, 0, 360);
// Lluvia
float newRain = rainTips * 0.2794; // mm por balanceo
rainHour = newRain; // Simplificado: acumulado desde último reset
rainDayTotal += newRain;
rainDay = rainDayTotal;
rainTips = 0;
// Batería
vBat = analogRead(VBAT_PIN) * 2.0 * 3.3 / 4095.0;
}
void checkAlerts() {
// Helada inminente
if (temperature < 2.0 && temperature > -1.0) {
sendTelegram("🥶 ALERTA HELADA\nTemp: " + String(temperature,1) +
"°C\nActiva protección antihelada");
}
// Suelo seco
if (soilMoisture < 25) {
sendTelegram("💧 SUELO SECO: " + String(soilMoisture) +
"%\nActivar riego recomendado");
}
// Viento fuerte (no pulverizar)
if (windSpeed > 15) {
sendTelegram("💨 VIENTO FUERTE: " + String(windSpeed,1) +
" km/h\n⚠️ No pulverizar ni volar dron");
}
// Batería baja
if (vBat < 3.4 && vBat > 2.5) {
sendTelegram("🔋 Batería baja: " + String(vBat,2) + "V");
}
}
void handleRoot() {
String html = ""
""
"Estación AgriculturaIA "
""
""
"🌤️ Estación AgriculturaIA
"
"Temperatura" + String(temperature,1) + " °C"
"Humedad aire" + String(humidity,0) + " %"
"Presión" + String(pressure,0) + " hPa"
"Lluvia hoy" + String(rainDay,1) + " mm"
"Viento" + String(windSpeed,1) + " km/h (" + String(windDirection) + "°)"
"Humedad suelo" + String(soilMoisture) + " %"
"UV / Luz" + String(uvIndex,1) + " / " + String(lux,0) + " lux"
"Batería" + String(vBat,2) + " V"
"Auto-refresh cada 30s | agriculturaia.com
"
"";
server.send(200, "text/html", html);
}
void handleAPI() {
String json = "{\"temp\":" + String(temperature,1) +
",\"hum\":" + String(humidity,0) +
",\"pres\":" + String(pressure,0) +
",\"rain\":" + String(rainDay,1) +
",\"wind\":" + String(windSpeed,1) +
",\"windDir\":" + String(windDirection) +
",\"soil\":" + String(soilMoisture) +
",\"uv\":" + String(uvIndex,1) +
",\"lux\":" + String(lux,0) +
",\"vBat\":" + String(vBat,2) + "}";
server.send(200, "application/json", json);
}
void sendTelegram(String msg) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin("https://api.telegram.org/bot" + BOT_TOKEN +
"/sendMessage?chat_id=" + CHAT_ID + "&text=" + msg);
http.GET();
http.end();
}
}El código incluye servidor web local (accedes desde el navegador al IP del ESP32), API JSON para integración con otros sistemas, y alertas Telegram automáticas para heladas, suelo seco, viento fuerte y batería baja.
6. Calibración de cada sensor
BME280: viene calibrado de fábrica. Solo necesitas verificar que la dirección I2C es 0x76 (algunos modelos usan 0x77). La presión debe ajustarse a la altitud de tu finca: resta aproximadamente un hPa por cada ocho metros de altitud.
Sensor humedad suelo: clava el sensor en suelo completamente seco y anota el valor ADC (SOIL_DRY, típicamente tres mil a tres mil quinientos). Después sumérgelo en agua y anota el valor (SOIL_WET, típicamente mil doscientos a mil quinientos). Estos dos valores calibran el rango cero a cien por ciento. Comprueba con el medidor XLUX analógico para verificar.
Anemómetro: el factor de conversión pulsos/segundo a km/h varía según el modelo. El valor dos coma cuatro es un punto de partida habitual. Para calibrar exactamente, compara con un anemómetro de referencia o la app del móvil en un día con viento constante.
Pluviómetro: la mayoría de pluviómetros de balancín generan un pulso por cada cero coma dos siete nueve cuatro milímetros de lluvia. Verifica vertiendo exactamente cien mililitros de agua por la superficie de captación (el embudo) y contando los pulsos.
7. Dashboard web local en el ESP32
El código ya incluye un servidor web integrado. Al conectar el ESP32 al WiFi de tu casa, puedes acceder al dashboard desde cualquier dispositivo de la red local escribiendo la dirección IP del ESP32 en el navegador (se muestra por el puerto serie al arrancar). La página se auto-refresca cada treinta segundos.
También incluye un endpoint /api que devuelve los datos en formato JSON, lo que permite integrar con cualquier sistema externo, como Home Assistant, Node-RED o tu propia aplicación web.
8. Alertas Telegram automáticas
El sistema envía alertas automáticas cuando se superan umbrales críticos, tal como definimos en nuestra tabla de decisión meteorológica:
Alerta helada cuando la temperatura baja de dos grados (activar protección). Alerta suelo seco cuando la humedad baja del veinticinco por ciento (activar riego). Alerta viento fuerte cuando supera quince km/h (no pulverizar ni volar dron). Alerta batería baja cuando el voltaje baja de tres coma cuatro voltios (revisar panel solar).
Para configurar Telegram necesitas crear un bot con @BotFather (te da el BOT_TOKEN) y obtener tu CHAT_ID enviando un mensaje al bot y consultando la API de Telegram. El proceso completo lleva unos cinco minutos.
9. Gráficos con ThingSpeak gratuito
ThingSpeak (thingspeak.com) es una plataforma gratuita de IoT de MathWorks que almacena datos y genera gráficos automáticamente. Solo necesitas crear una cuenta, crear un canal con ocho campos (temperatura, humedad, presión, lluvia, viento, dirección, suelo, UV) y enviar datos con una petición HTTP cada minuto.
ThingSpeak gratuito permite hasta tres millones de mensajes al año (un envío por minuto = unos quinientos mil al año, dentro del límite). Los gráficos son públicos o privados, exportables a CSV y con funciones MATLAB integradas para análisis avanzado.
10. Publicar en Weather Underground
Weather Underground (wunderground.com) permite registrar tu estación como estación personal (PWS). Aparecerá en el mapa público y contribuirás a la red meteorológica colaborativa. Para enviar datos, haces un HTTP GET con tus lecturas al endpoint de WU cada minuto. Necesitas un ID de estación y una clave que obtienes al registrarte.
11. Alimentación solar: funcionar sin enchufe
El esquema solar es el mismo que usamos en el tutorial de riego y en el artículo de LoRa para agricultura: panel solar 6W 5V → módulo TP4056 → batería 18650 → ESP32.
La diferencia con el sistema de riego es que la estación meteo no usa deep sleep: necesita estar siempre encendida para contar pulsos de lluvia y viento. El consumo medio es de unos ochenta miliamperios (ESP32 activo + WiFi). Con una batería de tres mil setecientos miliamperios hora, la autonomía sin sol es de unas cuarenta y seis horas. El panel de seis vatios genera suficiente para mantener la batería cargada incluso en invierno.
12. Caja y montaje exterior
El ESP32 y las conexiones van dentro de una caja estanca IP65 con tapa transparente. Los cables de sensores salen por prensaestopas PG7 o PG9. El sensor BME280 debe ir dentro de una garita antirradiación para evitar lecturas falsas por radiación solar directa (sin garita, el sensor puede leer cinco a diez grados más en verano). El anemómetro y pluviómetro van montados en un mástil a dos metros de altura como mínimo.
13. DIY vs comercial: comparativa honesta
| Aspecto | DIY ESP32 (95 €) | ECOWITT GW1101 (90 €) |
|---|---|---|
| Montaje | 2-4 horas + soldar | 10 minutos |
| Programación | Necesaria (Arduino IDE) | Ninguna |
| Personalización | Total (código abierto) | Limitada (firmware cerrado) |
| Sensores extra | Cualquiera (I2C, ADC, etc.) | Solo compatibles Ecowitt |
| Integración riego | Directa (mismo ESP32) | Separada |
| Fiabilidad | Depende del montaje | Alta (fabricante) |
| Garantía | Solo componentes | 2 años |
| LoRa | Sí (añade módulo) | No incluido |
Nuestra recomendación final: si no tienes experiencia con ESP32, compra la ECOWITT GW1101 y empieza a usar datos meteorológicos hoy mismo. Si ya has montado el sistema de riego de nuestro tutorial y quieres más control, la versión DIY te da flexibilidad total para crecer.




14. Preguntas frecuentes
¿Puedo usar esta estación para el CUE digital? Sí. Los datos de tu estación (lluvia, temperaturas) son válidos como referencia para el Cuaderno de Explotación Digital, especialmente si los exportas desde ThingSpeak con fechas y horas.
¿Funciona en invierno con menos sol? Sí. El panel de seis vatios genera suficiente incluso con cuatro a cinco horas de sol en diciembre en la mitad sur de España. En el norte, considera un panel de diez vatios o una batería de mayor capacidad.
¿Puedo añadir sensor de humedad de suelo? Ya está incluido en el código. Si necesitas más puntos de medición a distancia, combina con módulos LoRa para nodos remotos.
¿Qué pasa si se cuelga el ESP32? El watchdog timer del ESP32 reinicia automáticamente el sistema si se bloquea. Añade esp_task_wdt_init(300, true) en el setup para un reinicio automático cada cinco minutos de inactividad.
Todos los componentes disponibles con enlaces directos a Amazon.
⚠️ Lo que debes tener en cuenta antes de empezar
- 🔧 Calibración obligatoria: Dedica una hora el primer día. Sin calibrar, errores del treinta-cuarenta por ciento
- ☀️ Garita antirradiación: Sin garita, el BME280 al sol lee cinco a diez grados de más
- ⚡ Sin deep sleep: Siempre encendida para contar pulsos lluvia/viento. Consume ochenta mA continuos
- 🔌 Prensaestopas: Cada cable necesita prensaestopas propio. Sin sellar, entrará agua en semanas
💡 ¿Merece la pena? Esto es lo que ganan otros agricultores
La comercial ECOWITT GW1101 cuesta noventa euros y funciona en diez minutos. Tu DIY cuesta noventa y cinco euros pero incluye sensor de suelo, alertas personalizadas y conexión directa a tu riego: algo que la comercial no puede. Un agricultor en Huelva configuró alerta de helada a menos de dos grados. Primera vez que saltó: salvó fresas valoradas en tres mil euros. ROI: tres mil por ciento en la primera alerta.
🛒 Productos recomendados para este proyecto
Selección verificada para este proyecto. Todos con envío Prime y devolución gratuita.
Tres mediciones en un chip de cuatro milímetros. ±1°C y ±3% HR
✅ Datos meteorológicos profesionales por menos de cuatro euros
Cada vuelco = 0.2794 mm de lluvia. Mismo tipo que estaciones profesionales
✅ Mide lluvia real en tu parcela, no estimación de AEMET
Mide velocidad y dirección del viento con pulsos digitales
✅ Alertas de viento fuerte: protege invernaderos y cultivos
WiFi integrado, ADC para analógicos, interrupciones para lluvia y viento
✅ Una sola placa controla siete sensores y sirve datos por WiFi
🔗 Siguientes pasos: completa tu sistema
Cada guía complementa esta. Un buen sistema agrícola conecta varias tecnologías.
📊 Tabla de decisión: ¿DIY o comercial?
Compara punto por punto la DIY con ECOWITT y Netatmo
💧 Conecta tu estación al riego automático
Usa datos de lluvia y humedad para activar el riego inteligentemente
📡 LoRa: estación meteo sin WiFi
Si no hay cobertura WiFi, añade módulo LoRa y recibe datos a kilómetros

Deja una respuesta