Tratando de explorar más proyectos con el ESP8266 quise probar creando una especie de monitor con el que pudiera leer algunos datos del ambiente de mi casa y luego consultarlos desde mi teléfono o computador. La idea era usar un ESP8266 y un sensor ambiental BME280, para luego mostrar los datos en una página web. Sin embargo, mientras buscaba otros materiales encontré una pantalla Nextion que había comprado durante la campaña de Indiegogo hace varios años, se me ocurrió que podría usarla como punto de visualización local conectada al ESP8266.
Decidí dividir el proyecto en etapas, para luego hacer la integración de todas las partes. Así que comencé por el diagrama electrónico, luego la lectura del BME280, seguido de la presentación de los datos en una página web, la configuración y comunicación con la pantalla Nextion; para finalizar con el ensamble de todas las piezas en una carcasa hecha con impresión 3D.
El diagrama tiene todas las piezas del monitor, la idea es tener el sensor y la pantalla conectados al ESP8266, la alimentación será con una batería LiPo de 3.7V, así que el circuito también incluye un cargador de baterías con conector USB y un convertidor step-up para proveer los 5V que necesita la pantalla.
El sensor BME280 puede medir humedad, temperatura y presión barométrica, y aunque puede trabajar con comunicación SPI en mi caso usé I2C por los pocos pines disponibles en el ESP-01. Usando la librería de Adafruit para el BME280 es fácil configurar la comunicación con el sensor, sin embargo, tuve algunos inconvenientes para comunicarme con el sensor porque los pines para la comunicación I2C por hardware no están disponibles en el ESP-01, la alternativa fue definir otros pines para la comunicación e implementar I2C por software. Al momento de iniciar la comunicación con la función Wire.begin()
es necesario indicar cuáles serán los pines de comunicación, y cuando se conecta con el sensor usando la función bme.begin()
se debe escribir la dirección y la interfaz por la que se debe comunicar.
Adafruit_BME280 bme;
#define SDA_PIN 0
#define SCL_PIN 2
void setup() {
Wire.begin(SDA_PIN, SCL_PIN);
if (!bme.begin(0x76, &Wire)) {
Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!");
while (1) delay(10);
}
}
Luego de haber establecido la comunicación con el sensor ya se pueden ver datos en el monitor serial de Arduino. La lectura de temperatura es en grados Celsius, la presión se lee en Pascales, pero la forma más común de referirse a la presión barométrica es usando hPa o bar, así que se divide en 100 para convertir las unidades; en el caso de la altura sólo es necesario indicar el valor de la presión a nivel del mar y la librería calcula la altura aproximada, el valor promedio de la presión al nivel del mar es 1013.25 hPa; finalmente, la humedad se lee en porcentaje y sin conversiones adicionales.
El siguiente paso en el proyecto es publicar los valores en una página web, mientras revisaba cómo publicar los datos y hacer que se actualizaran periódicamente se me ocurrió que podría leer otros datos desde un servicio meteorológico para poder presentar algunos datos del clima de mi ciudad; para esta parte se usan las librerías ESP8266WiFi, ESP8266HTTPClient, ESP8266WebServer y Arduino_JSON.
Inicialmente el microcontrolador se conecta a la red WiFi, luego de esto activa el servidor web que debe mostrar los datos de clima y de ambiente; entre la configuración adicional se agregaron dos grupos de eventos con los que se actualizan los datos periódicamente.
AsyncWebServer server(80);
AsyncEventSource events("/events");
AsyncEventSource local_events("/local_events");
void setup() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
}
server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
request->send_P(200, "text/html", index_html, processor);
});
server.addHandler(&events);
server.addHandler(&local_events);
server.begin();
}
El servicio meteorológico usado es OpenWeatherMap, que ofrece una API gratuita (con algunas restricciones). Para obtener los datos del clima sólo es necesario enviar una petición HTTP a la dirección de la API, indicando la ciudad, el código del país, el idioma y la clave API de la cuenta; la respuesta a esta petición es una cadena de texto en formato JSON, así que con la ayuda de la librería de JSON de Arduino se puede traducir la cadena de texto y obtener los datos para presentarlos en la página web.
{
"coord": {
"lon": -74.0817,
"lat": 4.6097
},
"weather": [
{
"id": 802,
"main": "Clouds",
"description": "nubes dispersas",
"icon": "03d"
}
],
"base": "stations",
"main": {
"temp": 12.73,
"feels_like": 12.36,
"temp_min": 12.73,
"temp_max": 12.73,
"pressure": 1030,
"humidity": 88
},
"visibility": 10000,
"wind": {
"speed": 3.09,
"deg": 40
},
"clouds": {
"all": 40
},
"dt": 1631452512,
"sys": {
"type": 1,
"id": 8582,
"country": "CO",
"sunrise": 1631443681,
"sunset": 1631487438
},
"timezone": -18000,
"id": 3688689,
"name": "Bogota",
"cod": 200
}
Luego de trabajar un rato con HTML pude armar una página web que muestra la ubicación, temperatura, sensación térmica, humedad, velocidad del viento y descripción del clima; todos estos datos son leídos cada 15 minutos desde OpenWeatherMap. En la sección de lecturas locales se muestran las mediciones del BME280 que se actualizan cada 30 segundos.
Luego de estos avances era el turno de atacar la pantalla Nextion, afortunadamente se puede encontrar bastante información sobre su programación y comunicación en varios blogs y vídeos de YouTube. La pantalla Nextion que uso es una NX3224T024 de la serie básica, esta pantalla es de 2.4″, con resolución de 320 x 240 pixeles y con 4MB de memoria flash. La pantalla funciona como las HMI industriales que se usan en conjunto con PLCs, al momento de configurar la pantalla se diseñan diferentes displays para presentar los datos, cada dato tiene un nombre o tag único. El controlador, en este caso el ESP8266, se encarga de actualizar las variables en los displays.
El monitor tiene cuatro displays, uno como indicación del arranque (conexión WiFi y del sensor), otro como pantalla principal que muestra el estado del clima, otro que muestra los valores locales y otro de configuración, para poder ingresar el nombre y contraseña de la red WiFi, así como el brillo de la pantalla y la dirección IP para poder ingresar al servidor web.
Existe una librería oficial de Nextion para manejar las pantallas con Arduino, mientras buscaba tutoriales sobre el uso de dicha librería, encontré que la comunicación es más sencilla de lo que pensaba. Básicamente es necesario enviar el ID del objeto, el atributo a cambiar y el valor que se va a asignar, todo esto como una cadena de texto seguida de tres 0xFF. La siguiente es la función que permite escribir comandos o actualizar valores desde el ESP8266 hacia la pantalla, donde String cmd
representa el comando.
void sendCmd(String cmd)
{
Serial.print(cmd);
Serial.print("\xFF\xFF\xFF");
}
Por ejemplo, en la pantalla, el objeto n_temp
es el que muestra la temperatura leída desde OpenWeatherMap, para refrescar este dato en la pantalla, se usaría el siguiente código. El atributo que se modifica es txt
y la cadena que se presentará es el valor de temperature
.
sendCmd("n_temp.txt=\""+ String(temperature) + "\"");
Luego de tener todas las partes y la programación lista, comencé a diseñar una carcasa para ubicar todos los componentes del monitor, diseñé la carcasa con Fusion 360 y fue impresa en PLA. Luego de lijar, pintar, volver a lijar y volver a pintar; pude ensamblar el monitor. El monitor tiene unos imanes de neodimio en la parte posterior, para poder adherirlo a un elemento metálico como la nevera o algo por el estilo.
Las partes dentro del proyecto son las siguientes:
- ESP-01 (ESP8266)
- Sensor BME280
- Pantalla Nextion NX3224T024
- ESP8266 Breakout Board
- Cargador LiPo TC4056A
- Convertidor Step-Up MT3608
- Batería LiPo 900mAh
- Microswitch dos posiciones
Durante las pruebas, al conectar el pin TX del módulo ESP-01 con el pin RX de la pantalla Nextion noté que el controlador no arrancaba, luego de buscar en foros encontré que el pin TX (GPIO 1) del controlador debe estar flotante o en 3.3V para que el ESP8266 pueda arrancar adecuadamente, y al parecer el RX de la pantalla lo estaba llevando a 0V, así que agregué una resistencia de pull-up entre el pin TX y los 3.3V, una resistencia de 10KΩ fue suficiente.
Al final agregué una conexión con un servidor NTP para actualizar la hora en la pantalla Nextion. Un pendiente es implementar la actualización del firmware del ESP8266 usando la red WiFi (OTA), para evitar abrir el monitor cada vez que sea necesario hacer un cambio.
El código completo con comentarios para el ESP8266, al igual que los modelos 3D se pueden encontrar en el repositorio de GitHub.
GitHub: ESPEnvironmentalMonitor
Mas información:
Adafruit BME280 Humidity + Barometric Pressure + Temperature
API de OpenWeatherMap
Nextion
Nextion Editor
Si tienes alguna inquietud no dudes en comentar.
Pingback: Monitor Ambiental – Carcasa – palmacas
Eres un crack, me ha gustado mucho tu trabajo.
Hola Antonio, gracias.
Saludos