arduino

Enviar temperatura y humedad por MQTT usando DHT22 y ESP8266

En este post te mostraré cómo leer la temperatura y humedad del sensor DHT22 usando la tarjeta ESP8266 para más tarde enviarla a un servidor MQTT.

Del mismo modo vamos a suscribirnos a un tópico y encenderemos o apagaremos un led dependiendo del mensaje recibido.

Requisitos

Esto es parte de una serie de posts que vengo haciendo sobre el internet de las cosas con ESP8266.

Te recomiendo leer cómo usar el DHT22 con la ESP8266, y del mismo modo te invito a ver una comunicación simple a través de MQTT con la Raspberry y la tarjeta NodeMCU ESP8266.

Este post es más que nada una unión de ambos posts, así que te recomiendo ampliamente que leas lo anterior mencionado.

Circuito

Debido a que vamos a encender y apagar el LED que la tarjeta ya trae, no necesitamos conectar algo externo. Lo que sí necesitamos es conectar el sensor:

Circuito – Sensor DHT22 con ESP8266

Lo demás se hará por WiFi.

Enviar temperatura y humedad por MQTT

Cada 2 segundos vamos a estar leyendo los valores del sensor y los vamos a publicar así:

// Si han pasado más de 2 segundos desde la última vez, enviar un mensaje
if (millis() - ultimaVez > TIEMPO_ESPERA)
{
  humedad = sensor.readHumidity();
  temperaturaEnGradosCelsius = sensor.readTemperature();
  // En ocasiones puede devolver datos erróneos; por eso lo comprobamos
  if (isnan(temperaturaEnGradosCelsius) || isnan(humedad))
  {
    ultimaVez = millis();
    return;
  }

  // Formatear la temperatura y humedad
  sprintf(mensaje, "Temperatura: %.2f. Humedad: %.2f", temperaturaEnGradosCelsius, humedad);
  clienteMqtt.publish("jardin/temperatura", mensaje);
  ultimaVez = millis();
}

Estoy usando la función sprintf porque necesito concatenar los valores de una forma sencilla, y no quiero usar strcat o cosas de esas.

Encender o apagar led por MQTT

Por otro lado, vamos a ver las funciones que permitirán que, dependiendo del mensaje recibido, se apague o encienda un LED:

/*
No tengo idea, pero parece que está invertido y al escribir un HIGH
se apaga
Relaciondo: https://github.com/nodemcu/nodemcu-devkit-v1.0/issues/16
*/void apagarLed()
{
  digitalWrite(PIN_LED, HIGH);
}

void encenderLed()
{
  digitalWrite(PIN_LED, LOW);
}

// La función que será llamada cuando se reciba un
// mensaje en el tópico al que nos vamos a suscribir
void callback(char *topico, byte *cargaUtil, unsigned int longitudDeDatos)
{
  if (longitudDeDatos <= 0)
    return;

  char primerCaracter = (char)cargaUtil[0];
  if (primerCaracter == '0')
    apagarLed();
  else if (primerCaracter == '1')
    encenderLed();
}

Lo que necesitamos en el mensaje es un 1 o un 0 y dependiendo de ello se apagará o encenderá el LED.

Código fuente completo

Ahora veamos el código fuente completo. Te repito de nuevo que deberías leer los posts que menciono anteriormente, pues aquí solo los estoy uniendo:

/*

  ____          _____               _ _           _       
 |  _ \        |  __ \             (_) |         | |      
 | |_) |_   _  | |__) |_ _ _ __ _____| |__  _   _| |_ ___ 
 |  _ <| | | | |  ___/ _` | '__|_  / | '_ \| | | | __/ _ \
 | |_) | |_| | | |  | (_| | |   / /| | |_) | |_| | ||  __/
 |____/ \__, | |_|   \__,_|_|  /___|_|_.__/ \__, |\__\___|
         __/ |                               __/ |        
        |___/                               |___/         
    
    Blog:       https://parzibyte.me/blog
    Ayuda:      https://parzibyte.me/blog/contrataciones-ayuda/
    Contacto:   https://parzibyte.me/blog/contacto/
    
    Copyright (c) 2020 Luis Cabrera Benito
    Licenciado bajo la licencia MIT
    
    El texto de arriba debe ser incluido en cualquier redistribucion
*/#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"

#define NOMBRE_RED "parzibyte"
#define PASSWORD_RED "hunter2"
#define DIRECCION_SERVIDOR_MQTT "192.168.1.79"
#define PUERTO_SERVIDOR_MQTT 1883
#define USUARIO_MQTT ""    // En mi caso es vacío
#define PASSWORD_MQTT ""   // En mi caso es vacío
#define TIEMPO_ESPERA 2000 // Cada cuánto leer del sensor

/*
Nota importante: si usas el pin D8 (como lo recomiendo)
  recuerda desconectar el lector del mismo cada vez que reinicies
  o quieras subir el código, pues el mismo "interfiere" con el
  monitor serial
*/
#define PIN_CONEXION D8   // A cuál pin está conectado el lector
#define TIPO_SENSOR DHT22 // Puede ser DHT11 también

#define PIN_LED LED_BUILTIN

DHT sensor(PIN_CONEXION, TIPO_SENSOR);
WiFiClient clienteWiFi;
PubSubClient clienteMqtt(clienteWiFi);
// El mensaje que se envía al servidor. Debe ser lo suficientemente
// grande
char mensaje[500] = "";
int ultimaVez = millis(); // Para enviar cada X segundos pero sin usar delay
float humedad, temperaturaEnGradosCelsius = 0;

/*
No tengo idea, pero parece que está invertido y al escribir un HIGH
se apaga
Relacionado: https://github.com/nodemcu/nodemcu-devkit-v1.0/issues/16
*/void apagarLed()
{
  digitalWrite(PIN_LED, HIGH);
}

void encenderLed()
{
  digitalWrite(PIN_LED, LOW);
}

// La función que será llamada cuando se reciba un
// mensaje en el tópico al que nos vamos a suscribir
void callback(char *topico, byte *cargaUtil, unsigned int longitudDeDatos)
{
  if (longitudDeDatos <= 0)
    return;

  char primerCaracter = (char)cargaUtil[0];
  if (primerCaracter == '0')
    apagarLed();
  else if (primerCaracter == '1')
    encenderLed();
}

void setup()
{
  pinMode(PIN_LED, OUTPUT);
  apagarLed();

  sensor.begin();

  // Conexión WiFi
  WiFi.begin(NOMBRE_RED, PASSWORD_RED);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
  }

  // Y ahora intentamos conectarnos al servidor MQTT
  clienteMqtt.setServer(DIRECCION_SERVIDOR_MQTT, PUERTO_SERVIDOR_MQTT);
  // Establecer la función que se invoca al recibir mensajes
  clienteMqtt.setCallback(callback);
  while (!clienteMqtt.connected())
  {
    if (!clienteMqtt.connect("ClienteESP8266", USUARIO_MQTT, PASSWORD_MQTT))
    {
      delay(2000);
    }
  }
  // Después de habernos conectado al servidor MQTT nos suscribimos
  clienteMqtt.subscribe("casa/sala/iluminacion");
}

// Ahora viene el loop, al cual se entra en caso de que en el setup
// todo haya ido bien

void loop()
{
  // Procesar los mensajes entrantes en caso de que existan
  clienteMqtt.loop();

  // Si han pasado más de 2 segundos desde la última vez, enviar un mensaje
  if (millis() - ultimaVez > TIEMPO_ESPERA)
  {
    humedad = sensor.readHumidity();
    temperaturaEnGradosCelsius = sensor.readTemperature();
    // En ocasiones puede devolver datos erróneos; por eso lo comprobamos
    if (isnan(temperaturaEnGradosCelsius) || isnan(humedad))
    {
      ultimaVez = millis();
      return;
    }

    // Formatear la temperatura y humedad
    sprintf(mensaje, "Temperatura: %.2f. Humedad: %.2f", temperaturaEnGradosCelsius, humedad);
    clienteMqtt.publish("jardin/temperatura", mensaje);
    ultimaVez = millis();
  }
  delay(10);
}

Los tópicos son:

Para recibir mensajes casa/sala/iluminacion

Para enviar mensajes jardin/temperatura

Probando

En caso de que todo vaya bien, podemos controlar el LED desde el servidor. Se enciende con:

mosquitto_pub -h localhost -t "casa/sala/iluminacion" -m "1"

Y se apaga con:

mosquitto_pub -h localhost -t "casa/sala/iluminacion" -m "0"

Por otro lado, si nos suscribimos al tópico de la temperatura, debemos ver algo así:

Recibiendo temperatura de DHT22 por MQTT en la Raspberry Pi

Y así es como podemos conectar todavía más cosas usando este protocolo.

Por cierto, si no sabes cómo configurar mosquitto en la Raspberry mira este post.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.
parzibyte

Programador freelancer listo para trabajar contigo. Aplicaciones web, móviles y de escritorio. PHP, Java, Go, Python, JavaScript, Kotlin y más :) https://parzibyte.me/blog/software-creado-por-parzibyte/

Ver comentarios

  • Hola, gracias por el articulo, segui los pasos que mencionas en este articulo y la verdad que el esp8266 funciona de maravillas, ahora bien,

    Como se soluciona, el inconveniente de:
    /*
    Nota importante: si usas el pin D8 (como lo recomiendo)
    recuerda desconectar el lector del mismo cada vez que reinicies
    o quieras subir el código, pues el mismo "interfiere" con el
    monitor serial
    */
    Ya que cada cierto tiempo debo desconectar el pin D8 para que vuelva a comunicarse, lo que representa un inconveniente. Muchas Gracias

Entradas recientes

Desplegar PWA creada con Vue 3, Vite y SQLite3 en Apache

Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…

6 días hace

Arquitectura para wasm con Go, Vue 3, Pinia y Vite

En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…

6 días hace

Vue 3 y Vite: crear PWA (Progressive Web App)

En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…

6 días hace

Errores de Comlink y algunas soluciones

Al usar Comlink para trabajar con los workers usando JavaScript me han aparecido algunos errores…

6 días hace

Esperar promesa para inicializar Store de Pinia con Vue 3

En este artículo te voy a enseñar cómo usar un "top level await" esperando a…

6 días hace

Solución: Apache – Server unable to read htaccess file

Ayer estaba editando unos archivos que son servidos con el servidor Apache y al visitarlos…

7 días hace

Esta web usa cookies.