En este tutorial aprenderás lo básico para construir tu propia estación meteorológica conectada a internet usando un ESP32.
Descargaremos datos meteorológicos de OpenWeather, analizaremos datos JSON usando ArduinoJson para extraer la temperatura, la humedad, la ubicación y la descripción del clima, y mostraremos esta información en una pantalla OLED.
¡Vamos a empezar!
Componentes necesarios
A continuación encontrarás los componentes necesarios para este proyecto. Para este tutorial, estoy usando una placa ESP32 antigua (ESP32 lite), que ya está descatalogada pero aún se puede conseguir. Es la que aparece listada abajo. Existe un modelo sucesor con mejores especificaciones, que puedes encontrar here . Pero cualquier otro ESP32, ESP8266 o Arduino con Wi-Fi también funcionará.

ESP32 lite

Cable de datos USB

Juego de cables Dupont

Protoboard

Pantalla OLED
Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.
OpenWeather
Para nuestra estación meteorológica conectada necesitaremos descargar datos del clima de internet. Hay varias formas de hacerlo, pero la más sencilla es usar OpenWeather .
OpenWeather es un servicio que proporciona datos meteorológicos actuales y pronósticos a través de una API que los desarrolladores pueden usar en sus proyectos. Tienen un plan gratuito que te permite hacer 1000 llamadas a la API por día. Eso es una llamada a la API cada 60* 60* 24/1000 = 86,4 segundos, más que suficiente, ya que actualizar el clima cada 5 o 10 minutos es más que rápido.
Además, incluso el plan gratuito proporciona información sobre Current Weather , 3-hour Forecast 5 days , Basic weather maps , Air Pollution y Geocoding . Más que suficiente para la mayoría de aplicaciones de hobby.
Crear una cuenta en OpenWeather
Antes de poder usar cualquiera de las APIs de OpenWeather, necesitas una clave API, y para eso necesitas una cuenta. Para crear una cuenta ve a la página de sign-up e introduce tus datos allí.

Crear clave API de OpenWeather
Una vez que tengas una cuenta y hayas iniciado sesión, ve a la página de creación de api-key y crea una clave API. La clave API es esa cadena larga «sdfd87fakeby6apikeysf4z» que ves en la captura de pantalla de abajo. Tu clave será diferente a la mía, y la que se muestra obviamente es falsa ; )

Puedes darle un nombre a la clave, pero no es obligatorio. Los nombres son útiles si tienes varias aplicaciones que usan diferentes claves y quieres mantenerlas separadas.
Descargar datos meteorológicos de OpenWeather
Con tu clave API ya puedes obtener datos meteorológicos de las distintas APIs construyendo la URL correspondiente. Por ejemplo, si vas a la API de Current Weather , la documentación te dice que la URL debe tener este formato:
https://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={API key}
Así que necesitarás saber la latitud y longitud de tu ubicación, y tu clave API, y reemplazar los marcadores entre llaves ( {lat} , {lon} , {API key} ) por los valores reales. Esto funciona, pero averiguar la latitud y longitud de varias ciudades que te interesan puede ser un poco engorroso.
Por suerte, existe la Geocoding API que nos permite obtener los datos del clima más fácilmente proporcionando una cadena con el nombre de la ciudad y el código del país. El patrón de la URL es así:
https://api.openweathermap.org/data/2.5/weather?q={city name},{country code}&appid={API key}
Por ejemplo, para obtener el clima en Melbourne, Australia (AU), donde vivo, escribirías:
http://api.openweathermap.org/data/2.5/weather?q=Melbourne,AU&APPID=sdfd87fakeby6apikeysf4z
Si pegas esta URL en la barra de búsqueda de tu navegador verás la siguiente salida. Asegúrate de marcar la casilla «Pretty print» en la parte superior.

Si miras la temperatura notarás un valor altísimo. En el ejemplo anterior el valor reportado es 283.38. Esto es porque por defecto OpenWeather devuelve las temperaturas en Kelvin. Si quieres unidades métricas (Celsius) o imperiales (Fahrenheit), puedes especificarlo en la URL.
Por ejemplo, para obtener la temperatura en Celsius tienes que usar:
https://api.openweathermap.org/data/2.5/weather?q={city name},{country code}&appid={API key}&units=metric
y para Fahrenheit escribirías units=imperial . Para más información consulta la documentación de OpenWeather sobre units of measurement .
Eso es todo lo que necesitas saber para empezar con OpenWeather. Pero te recomiendo que explores las otras APIs mencionadas arriba. Hay muchos datos interesantes que puedes usar para que tu estación meteorológica sea realmente útil.
Analizando datos JSON con ArduinoJson
Por defecto OpenWeather devuelve los datos en formato JSON . JSON es un formato de texto estructurado que necesitamos analizar para extraer los datos que queremos. Hacer esto manualmente es bastante complicado, así que usaremos la excelente biblioteca ArduinoJson en su lugar.
Documento JSON
Pero primero veamos qué información queremos extraer de los datos meteorológicos. La captura de pantalla de abajo muestra los datos completos que obtengo al pedir el clima de Melbourne a OpenWeather.

Para nuestra sencilla estación meteorológica conectada, voy a extraer cuatro datos. La descripción corta del clima bajo weather -> main ( "Clouds" ), la temperatura actual bajo main -> temp ( 10.29 ), la humedad relativa actual bajo main -> humidity ( 82 ), y el nombre de la ubicación bajo name ( "Melbourne" ).
Extrayendo datos con ArduinoJson
Un fragmento de código usando ArduinoJson para extraer estos cuatro valores del clima sería así:
StaticJsonDocument<4096> doc; String json = http.getString(); deserializeJson(doc, json); const char* name = doc["name"]; const char* weather = doc["weather"][0]["main"]; float temp = doc["main"]["temp"]; int hum = doc["main"]["humidity"];
Primero, necesitas reservar algo de memoria para cargar los datos JSON. La línea StaticJsonDocument<4096> doc; reserva 4KB de memoria. Si descargas más datos meteorológicos, como pronósticos, puede que necesites aumentar este valor.
Después descargamos los datos del clima y los escribimos (deserializamos) en el documento. El fragmento de código no muestra el cliente HTTP que usamos para la descarga, pero lo encontrarás en el código completo más abajo.
String json = http.getString(); deserializeJson(doc, json);
Si los datos JSON devueltos por OpenWeather fueran sintácticamente incorrectos (faltan corchetes, …), la deserialización fallará.
Deserializar simplemente significa que el texto plano de la cadena json se analiza y convierte en una estructura de datos que nos permite acceder a los campos y valores del documento JSON doc más fácilmente. Para más información sobre deserialización consulta la excelente ArduinoJson tutorial on deserialization .
Las siguientes cuatro líneas de código extraen la información que queremos del doc que contiene la cadena json deserializada.
const char* name = doc["name"]; const char* weather = doc["weather"][0]["main"]; float temp = doc["main"]["temp"]; int hum = doc["main"]["humidity"];
La primera línea extrae el nombre de la ubicación meteorológica ( "Melbourne" ), que está almacenado bajo doc["name"] . Como está almacenado como una cadena (fíjate en las comillas), debemos guardarlo en una variable de tipo const char* name .
La descripción corta del clima ( "Clouds" ) está bajo doc["weather"][0]["main"] . Ten en cuenta que bajo doc["weather"] , tenemos una lista [] y queremos el primer (y único) elemento de esa lista. Por eso escribimos doc["weather"][0] . Luego obtenemos la descripción bajo main , y la ruta completa es doc["weather"][0]["main"] . De nuevo, esto devuelve una cadena y hay que guardarla como const char* weather .
La temperatura actual es un valor decimal (10.29), que se encuentra bajo doc["main"]["temp"] . Como es un valor decimal, hay que guardarlo en una variable de tipo float .
Por último, extraemos la humedad actual ( 82 ) de doc["main"]["humidity"] y la guardamos en una variable de tipo int .
Debes tener mucho cuidado de que los tipos de datos coincidan con los usados en el documento JSON y de usar las rutas correctas para extraer esos valores. Si no, acabarás con errores de memoria muy difíciles de depurar. Si quieres extraer otros valores, ve poco a poco y añade nuevos valores paso a paso, así sabrás cuándo algo falla.
Conectando el ESP32 y la pantalla OLED
Conectar el ESP32 a la pantalla OLED es muy sencillo, ya que la OLED tiene una interfaz I2C. Primero conecta tierra (G) del ESP32 a GND de la OLED. Después conecta 3V del ESP32 a VCC de la OLED.

Luego hay que conectar SCL y SDA. Cualquier pin sirve, pero los pines I2C por defecto en el ESP32-lite son el 23 para SCL y el 19 para SDA. Así que conecta los pines correspondientes de la OLED a esos. La imagen de arriba muestra el cableado completo. Si tienes dificultades con esto, consulta el tutorial How to Interface the SSD1306 I2C OLED Graphic Display With Arduino
Si no sabes cuáles son los pines I2C por defecto de tu ESP32, no te preocupes. Es fácil averiguarlo. Simplemente ejecuta el siguiente código y tu ESP32 te lo dirá.
void print(const char* name, int pin) {
Serial.print(name);
Serial.println(pin);
}
void setup() {
Serial.begin(9600);
}
void loop() {
print("SDA: ", SDA);
print("SCL: ", SCL);
delay(5000);
}
Para más información, lee nuestro post sobre cómo Find I2C and SPI default pins . Alternativamente, puedes definir los pines que quieras usar. El código en las siguientes secciones te muestra cómo hacerlo.
Código para la estación meteorológica conectada
En esta sección vamos a escribir el código para descargar datos meteorológicos de OpenWeather, extraer la ubicación, temperatura, humedad y descripción del clima, y mostrarlos en una pantalla OLED. Echa un vistazo al código completo a continuación y luego comentaremos los detalles.
#include "WiFi.h"
#include "HTTPClient.h"
#include "ArduinoJson.h"
#include "Adafruit_SSD1306.h"
#define WIFI_SSID "YOURSSID"
#define WIFI_PASSWORD "YOURPASSWORD"
#define URL "http://api.openweathermap.org/data/2.5/weather?q=Melbourne,AU&APPID=YOURAPIKEY&units=metric"
HTTPClient http;
Adafruit_SSD1306 oled(128, 64, &Wire, -1);
StaticJsonDocument<4096> doc;
void downloadWeather() {
http.begin(URL);
if (http.GET() > 0) {
String json = http.getString();
auto err = deserializeJson(doc, json);
if (err) {
Serial.printf("Deserializion error: %s\n", err.f_str());
}
} else {
Serial.println("Could not get data!");
}
http.end();
}
void displayWeather() {
const char* name = doc["name"];
const char* weather = doc["weather"][0]["main"];
float temp = doc["main"]["temp"];
int hum = doc["main"]["humidity"];
oled.clearDisplay();
oled.setCursor(0, 0);
oled.printf(" %s\n", name);
oled.printf(" %s\n", weather);
oled.printf(" T: %.1f C\n", temp);
oled.printf(" H: %d %%\n", hum);
oled.display();
}
void oled_init() {
Wire.begin(19, 23); // sda, scl
oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
oled.clearDisplay();
oled.setTextSize(2);
oled.setTextColor(WHITE);
}
void wifi_init() {
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED)
delay(500);
}
void setup(void) {
Serial.begin(115200);
oled_init();
wifi_init();
}
void loop() {
downloadWeather();
displayWeather();
delay(10*60*1000); // 10min
}
Librerías
El código comienza incluyendo las librerías necesarias. WiFi.h para acceso WiFi, HTTPClient.h para descargar datos vía HTTP, ArduinoJson.h para analizar los datos descargados y Adafruit_SSD1306.h para mostrar los datos en la pantalla OLED.
WiFi.h y HTTPClient.h son librerías estándar, pero ArduinoJson.h y Adafruit_SSD1306.h tendrás que instalarlas desde el Library Manager.
Constantes
A continuación definimos algunas constantes. Específicamente, nuestras credenciales WiFi y la URL de la API de OpenWeather, desde donde descargamos los datos meteorológicos. Puedes cambiar la URL para obtener datos de otra ubicación o en otra unidad, pero no olvides usar tu clave API.
#define WIFI_SSID "YOURSSID" #define WIFI_PASSWORD "YOURPASSWORD" #define URL "http://api.openweathermap.org/data/2.5/weather?q=Melbourne,AU&APPID=YOURAPIKEY&units=metric"
Consulta la documentación de la API de Current Weather , que te muestra todas las formas de construir una URL. También revisa el Geocoding API , que simplifica el uso de ubicaciones.
Objetos
Para el resto del código necesitaremos tres objetos. Un HTTPClient que nos permite descargar datos de una web, un StaticJsonDocument para almacenar los datos deserializados y un objeto oled para mostrar los datos en la pantalla OLED.
HTTPClient http; Adafruit_SSD1306 oled(128, 64, &Wire, -1); StaticJsonDocument<4096> doc;
Para la OLED tienes que especificar las dimensiones, en mi caso son 128×64 píxeles, y para el documento JSON hay que reservar la máxima cantidad de memoria que podamos necesitar. Yo he reservado generosamente 4kB (4069 Bytes), suficiente para los datos meteorológicos actuales. Si descargas el pronóstico, que es más grande, puede que necesites reservar más espacio.
downloadWeather
La función downloadWeather descarga los datos meteorológicos de OpenWeather vía http.GET() , los deserializa y los almacena en el StaticJsonDocument mediante deserializeJson ().
void downloadWeather() {
http.begin(URL);
if (http.GET() > 0) {
String json = http.getString();
auto err = deserializeJson(doc, json);
if (err) {
Serial.printf("Deserializion error: %s\n", err.f_str());
}
} else {
Serial.println("Could not get data!");
}
http.end();
}
Si algo sale mal, mostramos un mensaje de error en el Serial Monitor.
displayWeather
Para mostrar el clima, primero extraemos las cuatro piezas de información meteorológica del doc como se describió antes. Luego limpiamos la pantalla, colocamos el cursor y simplemente mostramos el nombre de la ubicación, la descripción corta del clima, la temperatura actual y la humedad relativa.
void displayWeather() {
const char* name = doc["name"];
const char* weather = doc["weather"][0]["main"];
float temp = doc["main"]["temp"];
int hum = doc["main"]["humidity"];
oled.clearDisplay();
oled.setCursor(0, 0);
oled.printf(" %s\n", name);
oled.printf(" %s\n", weather);
oled.printf(" T: %.1f C\n", temp);
oled.printf(" H: %d %%\n", hum);
oled.display();
}
En la pantalla OLED la información meteorológica se mostrará como en la imagen de abajo.

oledInit
Antes de poder usar la OLED hay que inicializarla. Lo más importante es especificar los pines usados para la interfaz I2C (SDA, SCL) y la dirección I2C de la pantalla.
Si usas los pines I2C por defecto de tu microcontrolador, no hace falta llamar a Wire.begin(), si no, sí debes hacerlo.
La dirección I2C de la OLED que estoy usando es 0x3C, que es común, pero la tuya podría ser diferente. Consulta el tutorial How to Interface the SSD1306 I2C OLED Graphic Display With Arduino si tienes dificultades.
void oled_init() {
Wire.begin(19, 23); // sda, scl
oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
oled.clearDisplay();
oled.setTextSize(2);
oled.setTextColor(WHITE);
}
Aparte de eso, simplemente limpiamos la pantalla y configuramos el tamaño y color del texto.
wifiInit
De forma similar a la OLED, también necesitamos inicializar la conexión WiFi. Asegúrate de usar el ssid y la contraseña correctos, si no el cliente WiFi no se conectará.
void wifi_init() {
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED)
delay(500);
}
setup
Con las funciones auxiliares anteriores, la función setup se ha vuelto muy sencilla. Solo inicializamos la comunicación serie, la OLED y el WiFi, y listo.
void setup(void) {
Serial.begin(115200);
oled_init();
wifi_init();
}
loop
La función loop también es simple. Descargamos los datos meteorológicos, los mostramos en la OLED y luego esperamos 10 minutos antes de repetir el proceso.
void loop() {
downloadWeather();
displayWeather();
delay(10*60*1000); // 10min
}
Cuando implementes y pruebes, asegúrate de que el retardo al descargar los datos meteorológicos sea suficientemente grande. Si superas las 1000 llamadas por día, te bloquearán ese día.
¡Y eso es todo! Ahora tienes una pequeña estación meteorológica conectada a internet.
Conclusión
En este tutorial has aprendido cómo construir una estación meteorológica conectada a internet. Aunque es muy básica, es un gran punto de partida para una estación mucho más avanzada.
Explora las otras APIs que ofrece OpenWeather y mira qué datos quieres extraer. Los datos que devuelve OpenWeather incluso incluyen identificadores de iconos que puedes usar para mostrar iconos meteorológicos.
Quizá quieras pasar a una pantalla más grande que la pequeña OLED que usamos aquí. Algunas pantallas de Elecrow con ESP32 integrado y pantalla táctil pueden ser una buena opción. Consulta el CrowPanel 2.8″ ESP32 Display : Easy Setup Guide para saber cómo usar una de esas.
Además de los datos meteorológicos de internet, también podrías recoger datos locales usando sensores de temperatura, humedad y calidad del aire.
Por último, reaccionar activamente a los cambios del clima y encender aspersores, cerrar ventanas o activar el aire acondicionado son proyectos muy divertidos.
¡Disfruta ; )

