Objetivos
Material requerido.
Un M5Stack | |
Sensor BME280 | Sensor BME280 |
Jugando con M5 JSON y Arduino ESP32
En las últimas sesiones hemos ido jugando con los sensores de Bosch BMP280 y BME280 y vimos que pueden leer temperatura, presión y humedad (BME280), y además calcular la altitud en función de la presión atmosférica, a condición que los calibremos con la presión actual a nivel del mar en una zona próxima a nosotros.
En esta nueva sesión iba a publicar las lecturas del BME280 en una pagina web, de forma similar a como hicimos antes para el sensor BMP280, pero la verdad es que la pagina de lastminuteengineers ha hecho un tutorial insuperable, que os la recomiendo, pero además simplemente copiar es de lo mas aburrido, y se me ha ocurrido que podíamos hacer un tuto un poco más original.
Dado que el problema de calcular la altitud requiere un dato de calibración de partida, la presión a nivel de mar, ¿Porque no conseguir este dato mediante Openweather y JSON como ya vimos en un tuto anterior del M5Stack y usar esto para construir un sencillo altímetro con el M5?
Este va a se un tuto de lo más práctico, porque ya hemos visto todos los conceptos básicos necesarios y basta con juntarlos, pero para quien llegue de nuevo aquí, le recomiendo revisar antes los siguientes tutoriales de Prometec:
Para el M5Stack ESP32 con JSON:
Para manejar BMP / BME280:
Visto así, asusta un montón, pero os prometo que la cosa no es para tanto. Echad una ojeada a los tutos anteriores si os interesa el tema, porque en este tuto voy a dar los temas tratados como ya sabidos (Optimista que es uno) y así esta sesión no se eternizará. Pues nada, poneros cómodos que empezamos.
I2C con M5Stack
Nuestro M5 incluye un ESP32 interno y por tanto dispone de un bus I2C que podemos emplear para leer el Sensor BME280. Bastará con conectar los hilos como es debido y poco más. Como hasta ahora no habíamos hablado del I2C del M5, tendremos que empezar por comentar que se encuentra en un lateral y que por supuesto es un I2C normal y corriente.
Su localización está aquí recuadrada en rojo con el rótulo Groove a la derecha del conector USB C, en uno de los laterales:
Fíjate, que si usas un típico cable Groove para conectarte (Aunque los Dupont normales deberían Valer) que el rojo son 5V, Negro GND, Amarillo es SDA y blanco es SCL (Clock). Aquí puedes ver la conexión que he hecho con un conector Groove y unos cables DuPont Macho – Hembra
Una vez que sabemos donde esta el conector I2C, conectar el sensor BME280 no tiene mas misterio y podemos hacer un pequeño programa para asegurarnos de que esta bien conectado sin mas que usar una variante del I2CScanner para el M5stack. Al ejecutarlo conexión al BME280 verás algo como esto:
Donde se puede apreciar que en bus I2C hay 3 cosas, en las direcciones 10,68 y 75 (Hexadecimales) , que no tengo claro que es qué, porque no lo he encontrado en la documentación, pero sabemos que hay una pantalla LCD, un lector de SD card y un audio así que por ahí andarán los tiros.
Sabemos por lo tutoriales previos que el BME280 está en la dirección I2C 0x76 y si conectamos el sensor al I2C, aparece a la primera. Ni siquiera tienes que apagar:
Y una vez que tenemos el hardware debidamente conectado vamos con el programa.
Altímetro con ESP32 / M5stack y Arduino
Para hacer un pequeño resumen del proyecto, diremos que en principio podemos calcular la altitud en función de la presión barométrica, dado que ésta desciende a medida que ascendemos. Pero como no hay felicidad completa, ocurre que la presión barométrica varia ampliamente no solo con la altitud, sino que también es muy sensible a la humedad ambiente y a la temperatura atmosférica.
Recuerda que cuando ves el parte del tiempo, la presión barométrica baja indica que va a llover, porque la humedad que traen las lluvias hace disminuir la presión, y al contrario, si las altas presiónes indican que no va a llover. Por eso necesitamos calibrar la altitud con un dato como el de la presión a una altura de referencia y la forma mas sencilla es buscar la presión atmosférica a nivel de mar en una playa cerca de donde vives. En mi caso Getxo.
Viviendo al lado del mar es fácil buscar el dato de presión de la playa más próxima, pero si vives en Madrid, lo tienes peor. En ese caso, puedes calcular la presión en tu casa y usarla como referencia. El altímetro te dará la variación de altura con respecto a ese punto ¿Vale?
Si quieres un altímetro con respecto al mar, busca un punto próximo del que conozcas su altitud con exactitud y usas esa presión como referencia base, como hacíamos arriba. Luego solo tienes que sumarle la altura conocida a la lectura que te dé el sensor. Muy bien, Una vez aclarado esto (Espero) vamos a empezar con nuestro programa. Unas cuantas librerías:
#include <M5Stack.h> #include <WiFi.h> #include <HTTPClient.h> #include <ArduinoJson.h>
La primera es un clásico en M5, La segunda incluye el WIFI que usaremos para conectar a Openweather y por último la librería JSON nos permitirá deserializar la respuesta con los datos meteo.
#include <Wire.h> #include <Adafruit_Sensor.h> #include <Adafruit_BME280.h>
Incluimos la librería Wire para poder usar el I2C, y por último cargamos la librería de uso del BME280 que a su vez requiere la librería Sensor.H de Adafruit. Vamos con algunas constantes y variables :
const char *ssid = "TU_SSID"; const char *password = "contraseña";
Como siempre, necesitamos que aquí pongas tus datos WIFI si quieres conectar (Y quieres o todo esto no valdrá de nada)
const String key = "xxxxxxxxxxxxxxxxxxxxxxxx"; const String endpoint = "https://api.openweathermap.org/data/2.5/weather?q=getxo,%20ES,IN&APPID=";
En key necesitas poner tu clave (API key) de acceso a Openweather y en endpoint la cadena de búsqueda de tu punto de referencia.
Por último, de momento:
HTTPClient http; Adafruit_BME280 bme; float temperatura, humedad, presion, altitud ; float SEALEVELPRESSURE_HPA = 1010 ; // Valor por defecto
Arrancamos el servicio HTTP para acceder a Openweather , creamos una instancia del sensor BME280 y definimos unas variables globales para las lecturas que saquemos del sensor y otra que albergue la presión de referencia a nivel de mar, con un valor por defecto, por si por lo que sea no podemos conectar a la WIFI.
void setup() { WiFi.begin(ssid, password); while ( WiFi.status() != WL_CONNECTED ) { M5.Lcd.print ( "." ); delay ( 500 ); } M5.begin(); GetJsonMeteo(); bme.begin(0x76); }
Nos conectamos a la WIFI y vamos escribiendo puntitos hasta que tenemos éxito. Después inicializamos el M5 y llamamos a la función que lee los datos JSON de Openweather y por último arrancamos el sensor BME. Vamos con esta función final GetJsonMeteo() que hemos sacado directamente de uno de los tutoriales que recomendamos al principio, y ligeramentemodificado .
void GetJsonMeteo() { http.begin(endpoint + key); //construct the URL int httpCode = http.GET(); //send request if (httpCode > 0) { String payload = http.getString(); DynamicJsonDocument doc(1024); deserializeJson(doc, payload); presion = doc["main"]["pressure"]; // Definida a nivel global SEALEVELPRESSURE_HPA = presion ; // Guardamos presion a nivel del mar } else M5.Lcd.print("Error on HTTP request"); http.end(); delay(500); }
Básicamente construimos la cadena de búsqueda con http.begin() y mandamos un request con http.Get(). SI la respuesta es válida, recibimos la respuesta de Openweather a la string payload y deserializamos (Leemos) la respuesta de payload a un documento dinámico JSON llamado doc.
Ahora ya podemos leer directamente el valor de la presión en nuestra localidad de referencia y se la asignamos a la variable global SEALEVELPRESSURE_HPA para poder usarla como base de nuestra medida de altitud.
Y finalmente en el loop()
void loop() { temperatura = bme.readTemperature(); humedad = bme.readHumidity(); presion = bme.readPressure() / 100.0F; altitud = bme.readAltitude(SEALEVELPRESSURE_HPA); M5.Lcd.fillScreen(BLACK); // Limpia la pantalla M5.Lcd.setCursor(40, 110); M5.Lcd.setTextColor(BLUE); M5.Lcd.setTextSize(22); M5.Lcd.printf("%.1f m", altitud); // Solo 1 decimal, que si no baila demasiado Delay(500); // para limitar a 2 lecturas / seg }
Programa: BME280__JSON_NOKEYS
Simplemente leemos los valores del sensor y los enviamos a la pantalla.
Para probar el invento me he pillado el cacharrito éste y me he metido en el ascensor (Vivo en un octavo) y para mi sorpresa, el M5 con el sensor BME280, la clava. Vas viendo variar la altitud a medida que el ascensor se mueve.
Incluso he probado a ponerlo en el suelo, en mi cintura y después levantando el brazo, y el tío nota la diferencia. ¡¡ Increíble!!. No esperaba que fuera tan sensible y aun cuando el fabricante dice que la precisión es, poco más o menos, de 1m, no esperaba que fuera tan sensible a algo tan poco tangible como la presión atmosférica.
Da la sensación que no habrá variación por un par de pisos, pero vaya que si la hay, y el cacharro es capaz de medirla. Una sorpresa de lo más divertida que os recomiendo si tenéis niños (O si sois como niños, también Vale)