Cómo construir una Estación meteorológica con ESP8266 usando el IDE de Arduino Leave a comment

Comparte este Post

Estación meteorológica ESP8266 usando el IDE de Arduino

En este artículo vamos a ver como fabricar unaa estación meteorológica realmente genial usando ESP8266 (NodeMCU) y el DHT11, el sensor de lluvia. En este proyecto, aprenderemos a hacer una estación meteorológica completa DIY usando un ESP8266 y varios sensores. Hay dos tipos de estaciones meteorológicas, una que tiene sus propios sensores y el segundo tipo de estación meteorológica es donde obtenemos los datos de los servidores de la estación meteorológica. En este tutorial vamos a ver ambos tipos de estaciones meteorológicas.

Componentes requeridos

Introducción

¿Qué es una estación meteorológica?

Una estación meteorológica es un dispositivo que recoge datos relacionados con el tiempo y el medio ambiente utilizando muchos sensores diferentes. Las estaciones meteorológicas también se denominan centros meteorológicos, estaciones meteorológicas personales, estaciones meteorológicas profesionales, estaciones meteorológicas domésticas, meteorólogos y pronosticadores.

Los sensores de las estaciones meteorológicas pueden incluir un termómetro, LM35 o DHT11, para tomar lecturas de temperatura, un barómetro (BMP180) para medir la presión en la atmósfera, así como otros sensores para medir la lluvia, el viento, la humedad y más. Las estaciones meteorológicas van desde la simple tecnología analógica a la digital. Algunas incluso se conectan a un ordenador o a Internet, por lo que los datos recogidos pueden ser analizados con el software de la estación meteorológica.

Tipos de sensores utilizados para la estación meteorológica

La siguiente es una lista de los dispositivos de medición que se utilizan en las estaciones meteorológicas:

  • Termómetro (LM35). Un termómetro mide la temperatura. Puede medir la temperatura tanto en el interior como en el exterior, registrar las altas y bajas, mostrar las flechas de tendencia para indicar el aumento o la disminución de la temperatura, e incluso predecir los rangos de temperatura futuros a corto plazo.Una estación meteorológica basándonos en ESP8266

    En la primera parte vamos a hacer la estación meteorológica usando el DHT-11 y el sensor de lluvia. Así que estos datos se envían al cliente (navegador web). En esto montamos el servidor web en ESP8266.

    Diagrama de circuito de la estación meteorológica

    Conecta el sensor de lluvia al pin A0 del NodeMCU a través de un divisor de voltaje, el ESP8266 tiene una entrada de 1V en el ADC. Conecta el DHT11 al D5 del NodeMCU.

    /* * ESP8266 NodeMCU DHT11 and Rain Sensor - Weather Station Example * https://descubrearduino.com * */ #include #include #include #include "index.h" //Our HTML webpage contents with javascripts #include "DHTesp.h" //DHT11 Library for ESP #define LED 2 //On board LED #define DHTpin 14 //D5 of NodeMCU is GPIO14 DHTesp dht; //SSID and Password of your WiFi router const char* ssid = "Your-SSID"; const char* password = "Your-Password"; ESP8266WebServer server(80); //Server on port 80 //=============================================================== // This routine is executed when you open its IP in browser //=============================================================== void handleRoot() { String s = MAIN_page; //Read HTML contents server.send(200, "text/html", s); //Send web page } float humidity, temperature; void handleADC() { int rain = analogRead(A0); //Create JSON data String data = "{"Rain":""+String(rain)+"", "Temperature":""+ String(temperature) +"", "Humidity":""+ String(humidity) +""}"; digitalWrite(LED,!digitalRead(LED)); //Toggle LED on data request ajax server.send(200, "text/plane", data); //Send ADC value, temperature and humidity JSON to client ajax request //Get Humidity temperatue data after request is complete //Give enough time to handle client to avoid problems delay(dht.getMinimumSamplingPeriod()); humidity = dht.getHumidity(); temperature = dht.getTemperature(); Serial.print("H:"); Serial.println(humidity); Serial.print("T:"); Serial.println(temperature); //dht.toFahrenheit(temperature)); Serial.print("R:"); Serial.println(rain); } //============================================================== // SETUP //============================================================== void setup() { Serial.begin(115200); Serial.println(); // Autodetect is not working reliable, don't use the following line // dht.setup(17); // use this instead: dht.setup(DHTpin, DHTesp::DHT11); //for DHT11 Connect DHT sensor to GPIO 17 //dht.setup(DHTpin, DHTesp::DHT22); //for DHT22 Connect DHT sensor to GPIO 17 WiFi.begin(ssid, password); //Connect to your WiFi router Serial.println(""); //Onboard LED port Direction output pinMode(LED,OUTPUT); // Wait for connection while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } //If connection successful show IP address in serial monitor Serial.println(""); Serial.print("Connected to "); Serial.println(ssid); Serial.print("IP address: "); Serial.println(WiFi.localIP()); //IP address assigned to your ESP server.on("/", handleRoot); //Which routine to handle at root location. This is display page server.on("/readADC", handleADC); //This page is called by java Script AJAX server.begin(); //Start server Serial.println("HTTP server started"); } //============================================================== // LOOP //============================================================== void loop() { server.handleClient(); //Handle client requests }

    index.h

    const char MAIN_page[] PROGMEM = R"=====(
    
    
    
    Estación Meteorológica
    %MINIFYHTML99a2d1b672150cbeea5c8b49f5afcff446%
    
    
    
    21 March
    Temperature
    23 °C
    • TEMPERATURE

      21 °C
    • WEATHER

      Sunny

    • RAIN

      0%
    • HUMIDITY

      23%
    %MINIFYHTML99a2d1b672150cbeea5c8b49f5afcff414%%MINIFYHTML99a2d1b672150cbeea5c8b49f5afcff415% )=====";

    Resultados y pruebas

    Después de subir el código abrir el monitor serial y obtendrás la dirección ip.

    ¿Cómo funciona el programa de la Estación Meteorológica?

    Ahora veamos el funcionamiento completo del programa y el circuito de la estación meteorológica.

    El proyecto completo consiste en la parte de hardware y software. Primero veremos la parte de hardware.

    Hardware de la Estación Meteorológica

    La parte del hardware es simple, estamos usando sólo dos sensores DHT11 y el sensor de lluvia. Puedes añadir más sensores como el sensor de presión barométrica BMP180.

    La salida analógica del sensor de lluvia se conecta a la entrada analógica del ESP8266 a través de un divisor de voltaje. que deja caer la salida del sensor de lluvia para adaptarse al rango máximo de la entrada analógica del ESP8266.

    El DHT11 nos da lecturas de humedad y temperatura. Es el sensor digital da salida en un flujo de datos en serie. Para esta interfaz de sensores estamos usando la biblioteca DHTesp que se encarga de toda la comunicación con el sensor DHT11. DHT11 está conectado al pin D5 de la NodeMCU que es el GPIO14.

    #include "index.h" //Our HTML webpage contents with javascripts
    #include "DHTesp.h"  //DHT11 Library for ESP
      
    #define LED 2        //On board LED
    #define DHTpin 14    //D5 of NodeMCU is GPIO14
    
    DHTesp dht;

    El software de la estación meteorológica

    El software consiste en las siguientes partes.

    • Conexión a WiFi
    • Creación de servidores
    • Obtención de datos de los sensores
    • Envío de la GUI al usuario
    • Actualizando los valores de los sensores en la página web

    Conectando a WiFi

    La conexión a tu wifi se hace por ESP8266 usando el siguiente código. Primero definimos el wifi ssid y la contraseña.

    //SSID and Password of your WiFi router
    const char* ssid = "Your-SSID";
    const char* password = "Your-Password";

    Entonces intentamos conectarnos con wifi usando WiFi.begin(ssid, password) y esperamos hasta que la conexión tenga éxito usando while (WiFi.status() != WL_CONNECTED).

    WiFi.begin(ssid, password);     //Connect to your WiFi router
      Serial.println("");
     
      //Onboard LED port Direction output
      pinMode(LED,OUTPUT); 
      
      // Wait for connection
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
    
      //If connection successful show IP address in serial monitor
      Serial.println("");
      Serial.print("Connected to ");
      Serial.println(ssid);
      Serial.print("IP address: ");
      Serial.println(WiFi.localIP());  //IP address assigned to your ESP

    Una vez que nos conectamos al wifi con éxito imprimimos la dirección IP asignada por tu router WiFi en el monitor serial usando la función WiFi.localIP().

    La siguiente parte es crear un servidor web en ESP8266. Para ello incluimos la librería de servidores web #include

    Luego creamos la instancia del servidor usando la función de abajo. La web usa el puerto 80 por defecto, así que lo definimos como el puerto 80.

    ESP8266WebServer server(80); //Server on port 80

     

    Después de esto en setup() creamos funciones de manejo de solicitudes de clientes, una para mostrar la GUI y otra que envía los datos del sensor al usuario usando AJAX y JSON. AJAX es parte de la página web.

     server.on("/", handleRoot);      //Which routine to handle at root location. This is display page
      server.on("/readADC", handleADC); //This page is called by java Script AJAX
     
      server.begin();                  //Start server
      Serial.println("HTTP server started");
    }

    Cuando el usuario entra en ESP8266 IP solicita una página raíz. Esa solicitud es atendida por la función handleRoot(). Envía la página web (HTML) al usuario (navegador web).

    //===============================================================
    // This routine is executed when you open its IP in browser
    //===============================================================
    void handleRoot() {
     String s = MAIN_page; //Read HTML contents
     server.send(200, "text/html", s); //Send web page
    }

    Una vez que la página web se carga, contiene javascript con código AJAX que envía la solicitud de datos al servidor web ESP8266 en /readADC. Si introduces IP con readADC solicita como se muestra a continuación. ESP envía los datos del sensor en formato JSON.

    float humidity, temperature; void handleADC() { int rain = analogRead(A0); //Create JSON data String data = "{"Rain":""+String(rain)+"", "Temperature":""+ String(temperature) +"", "Humidity":""+ String(humidity) +""}"; digitalWrite(LED,!digitalRead(LED)); //Toggle LED on data request ajax server.send(200, "text/plane", data); //Send ADC value, temperature and humidity JSON to client ajax request //Get Humidity temperatue data after request is complete //Give enough time to handle client to avoid problems delay(dht.getMinimumSamplingPeriod()); humidity = dht.getHumidity(); temperature = dht.getTemperature(); Serial.print("H:"); Serial.println(humidity); Serial.print("T:"); Serial.println(temperature); //dht.toFahrenheit(temperature)); Serial.print("R:"); Serial.println(rain); }

    Ahora pasemos a la página web, es decir, a la parte del código HTML y JavaScript. Que está presente en el archivo index.h. En el Java Script accedemos a los elementos HTML usando identificaciones.

    //Get Humidity Temperature and Rain Data var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var txt = this.responseText; var obj = JSON.parse(txt); //Ref: https://www.w3schools.com/js/js_json_parse.asp document.getElementById("rain").innerHTML = obj.Rain + "%"; document.getElementById("temperature").innerHTML = Math.round(obj.Temperature) + "°C"; document.getElementById("temp").innerHTML = Math.round(obj.Temperature) + "°C"; document.getElementById("humidity").innerHTML = Math.round(obj.Humidity) + "%"; } }; xhttp.open("GET", "readADC", true); //Handle readADC server on ESP8266 xhttp.send(); }

    En la función DrawClock() tenemos la parte AJAX que envía la petición GET al ESP en readADC. cuando el navegador web (programa java) recibe el texto de respuesta, es decir, JSON. llama a la función readystatechange. en la que confirmamos que la petición está bien (200). si está bien, entonces obtenemos el texto de respuesta, es decir, JSON y luego usando javascript json parsing JSON.parse(txt); obtenemos todos nuestros datos del sensor en objetos json. Estos datos de los objetos json se actualizan en la página web dinámicamente (sin actualización de la página) usando document.getElementById(“id of html element”).innerHTML = sensor data.

    Así es como funciona todo. La interfaz gráfica de usuario se crea usando CSS y HTML. que no se cubre aquí por ser un tema más relacionado con el desarrollo web.

    Estación meteorológica basada en el ESP8266 usando los datos del servidor

    En este no estamos usando ningún sensor, pero obtenemos datos meteorológicos del servidor de la estación meteorológica local. Para visualizarlos necesitamos una pantalla. Este tipo de aplicación es como si tuvieras un pequeño dispositivo sobre la mesa que solicita datos meteorológicos a las estaciones meteorológicas y se actualiza continuamente en una pequeña pantalla. La ventaja de este tipo de estación meteorológica es que se obtiene el pronóstico del tiempo.

    Conexiones de la estación meteorológica

    • En esto sólo tenemos una pantalla OLED 0.96″ y NodeMCU.Código para IDE de Arduino para la Estación Meteorológica usando NodeMCU

      Antes de empezar a codificar necesitamos instalar algunas bibliotecas en nuestro Arduino IDE.

      /* * ESP8266 Weather Station Data Rading * */ #include #include #include #include #include //#include // Only needed for Arduino 1.6.5 and earlier #include "SSD1306Wire.h" // legacy include: `#include "SSD1306.h"` const char* wifiName = "Your-SSID"; const char* wifiPass = "Your-Password"; //Web Server address to read from const char *host = "fcc-weather-api.glitch.me"; //Enter you lat long here String Link = "/api/current?lat=18.53&lon=73.86"; const int httpsPort = 443; //HTTPS= 443 and HTTP = 80 //SHA1 finger print of certificate use web browser to view and copy const char fingerprint[] PROGMEM = "8E 68 78 DD 47 8F 03 BF 8B 51 DB 62 FE 5A CB 6E E9 20 82 A1"; // Initialize the OLED display using Wire library SSD1306Wire display(0x3c, D2, D1); //D2=SDK D1=SCK As per labeling on NodeMCU //======================================================================= // SETUP //======================================================================= void setup() { Serial.begin(115200); delay(1000); Serial.println(); Serial.println("Initializing OLED Display"); display.init(); display.flipScreenVertically(); display.setFont(ArialMT_Plain_10); Serial.print("Connecting to "); Serial.println(wifiName); WiFi.begin(wifiName, wifiPass); display.clear(); display.setFont(ArialMT_Plain_16); display.drawString(0, 10, "Connecting WiFi"); display.display(); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } display.clear(); display.setFont(ArialMT_Plain_16); display.drawString(0, 10, "Connected"); display.display(); Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); //You can get IP address assigned to ESP } //======================================================================= // LOOP //======================================================================= void loop() { WiFiClientSecure httpsClient; //Declare object of class WiFiClient Serial.println(host); Serial.printf("Using fingerprint '%s'n", fingerprint); httpsClient.setFingerprint(fingerprint); httpsClient.setTimeout(15000); // 15 Seconds delay(1000); Serial.print("HTTPS Connecting"); int r=0; //retry counter while((!httpsClient.connect(host, httpsPort)) && (r < 30)){ delay(100); Serial.print("."); r++; } if(r==30) { Serial.println("Connection failed"); } else { Serial.println("Connected to web"); } //Get weather data Serial.print("requesting URL: "); Serial.println("GET " + Link + " HTTP/1.1rn" + "Host: " + host + "rn" + "Connection: closernrn"); httpsClient.print(String("GET ") + Link + " HTTP/1.1rn" + "Host: " + host + "rn" + "Connection: closernrn"); Serial.println("request sent"); while (httpsClient.connected()) { String line = httpsClient.readStringUntil('n'); if (line == "r") { Serial.println("headers received"); break; } } Serial.println("reply was:"); Serial.println("=========="); String payload; while(httpsClient.available()){ payload = httpsClient.readStringUntil('n'); //Read Line by Line Serial.println(payload); //Print response } int str_len = payload.length() + 1; Serial.println(str_len); // Prepare the character array (the buffer) char json[str_len]; // Copy it over payload.toCharArray(json, str_len); StaticJsonDocument<1000> doc; //Refere to calculate size https://arduinojson.org/v6/assistant/ deserializeJson(doc, json); float coord_lon = doc["coord"]["lon"]; // 73.86 float coord_lat = doc["coord"]["lat"]; // 18.53 JsonObject weather_0 = doc["weather"][0]; int weather_0_id = weather_0["id"]; // 800 const char* weather_0_main = weather_0["main"]; // "Clear" const char* weather_0_description = weather_0["description"]; // "clear sky" const char* weather_0_icon = weather_0["icon"]; // "https://cdn.glitch.com/6e8889e5-7a72-48f0-a061-863548450de5%2F01d.png?1499366022009" const char* base = doc["base"]; // "stations" JsonObject main = doc["main"]; float main_temp = main["temp"]; // 34.44 float main_pressure = main["pressure"]; // 1010.6 float main_humidity = main["humidity"]; // 22 float main_temp_min = main["temp_min"]; // 34.44 float main_temp_max = main["temp_max"]; // 34.44 float main_sea_level = main["sea_level"]; // 1010.6 float main_grnd_level = main["grnd_level"]; // 937.58 float wind_speed = doc["wind"]["speed"]; // 2.43 float wind_deg = doc["wind"]["deg"]; // 287.5 int clouds_all = doc["clouds"]["all"]; // 0 long dt = doc["dt"]; // 1553248419 JsonObject sys = doc["sys"]; float sys_message = sys["message"]; // 0.0031 const char* sys_country = sys["country"]; // "IN" long sys_sunrise = sys["sunrise"]; // 1553216850 long sys_sunset = sys["sunset"]; // 1553260540 long id = doc["id"]; // 6943660 const char* location = doc["name"]; // "Shivaji Nagar" int cod = doc["cod"]; // 200 Serial.println(main_temp); Serial.println(main_pressure); Serial.println(main_humidity); Serial.println(location); display.clear(); display.setFont(ArialMT_Plain_16); display.drawString(0, 0, "T:"); display.drawString(15, 0, String(main_temp)); display.drawString(0, 15, "P:"); display.drawString(15, 15, String(main_pressure)); display.drawString(0, 30, "H:"); display.drawString(15, 30, String(main_humidity)); display.drawString(0, 45, "L:"); display.drawString(15, 45, location); display.display(); delay(5000); //GET Data at every 5 seconds }

      Resultados y pruebas

      Última actualización el 2020-06-15 / Enlaces de afiliados / Imágenes de la API para Afiliados


Comparte este Post

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Abrir chat
0

Tu carrito