El DHT11 es un sensor bastante económico que permite realizar mediciones de temperatura y humedad. En esta entrada te presentamos nuestro código en C para leer este sensor y un ejemplo práctico con un PIC16F88 que también debería adaptarse sin problemas al PIC16F628A y a otros micros similares de 8 bits como el PIC18F4550. Nuestro programa se comunica con el sensor y muestra las mediciones en una pantalla LCD. Cabe aclarar que usaremos MPLAB X y el compilador XC8 como plataforma de desarrollo en este ejemplo.

En la foto de portada vemos un sensor DHT11 conectado a un PIC16F88 que muestra la lectura de temperatura y humedad en una pantalla LCD de 16×2.

Funcionamiento del DHT11.

El DHT11 no utiliza una interfaz serial estándar como I2C, SPI o 1Wire. En cambio requiere su propio protocolo para comunicarse a través de un solo hilo. Afortunadamente el protocolo es simple y puede implementarse tranquilamente usando los pines de I/O en un PIC o cualquier otro microcontrolador (un AVR vestido de azul y blanco viene a nuestra mente).

Gracias a la amabilidad de la gente de embedded-lab.com tenemos las siguientes imágenes que he traducido y que explican en detalle la comunicación. Dicen por ahí que una imagen vale más que mil palabras y para nuestro caso, llevan razón con este dicho:

Para iniciar la comunicación con el DHT11 el micro “jala” la linea de datos a tierra por al menos 18 mS

El microcontrolador debe iniciar la comunicación con el DHT11 manteniendo la linea de datos en estado bajo durante al menos 18 ms. Luego el DHT11 envía una respuesta con un pulso a nivel bajo de 80 uS y luego deja “flotar” la linea de datos por otros 80 uS. En la figura de arriba, el pulso de inicio enviado por el microcontrolador esta coloreado en rojo, mientras que la respuesta desde el sensor esta coloreada en azul.

La codificación de datos esta basada en un esquema de ancho de pulso: Un pulso ancho representa un 1 lógico, un pulso corto representa un 0 lógico.

Los datos binarios se codifican según la longitud del pulso alto. Todos los bits comienzan con un pulso bajo de 50 uS. En nuestra librería aprovechamos el pulso bajo en cada bit para sincronizar con la señal del DHT11. Luego viene un pulso alto que varía según el estado lógico o el valor del bit que el DHT11 desea transmitir. Se utilizan pulsos de 26-28 microsegundos para un “0” y pulsos de 70 microsegundos para un “1”. Los pulsos se repiten hasta un total de 40 bits.

Una transmisión completa comienza como ya describimos y se compone de 40 bits (5 bytes) que incluyen todos los datos que el sensor puede proporcionar.

En cuanto a los datos que se transmiten, su interpretación es como sigue:

  • Se transmiten 40 bits (5 bytes) en total
  • El primer byte que recibimos es la parte entera de la humedad relativa (RH)
  • El segundo byte es la parte decimal de la humedad relativa (no se utiliza en el DHT11, siempre es 0)
  • El tercer byte es la parte entera de la temperatura
  • El cuarto byte es la parte decimal de la temperatura (no se utiliza en el DHT11, siempre es 0)
  • El ultimo byte es la suma de comprobación (checksum), resultante de sumar todos los bytes anteriores

Comunicación con el DHT11 en el mundo real

La trama del DHT11 se ve así en el osciloscopio, recordemos que cada “cuadrito” en la pantalla del instrumento equivale a 100 uS.

De izquierda a derecha se observa lo siguiente:

  1. Fin de la señal de inicio seguida de un “glitch” a nivel alto que ocurre mientras el microcontrolador libera el bus y el DHT11 toma el control de la linea.
  2. Pulso de respuesta bajo del DHT11 de alrededor de 80 uS.
  3. Pulso de respuesta alto del DHT11 de alrededor de 80 uS.
  4. Primer bit “0” compuesto de un pulso bajo de 50 uS y otro alto de alrededor de 25 uS
  5. Segundo bit “0”
  6. Tercer bit “1” compuesto de un pulso bajo de 50 uS y otro alto de alrededor de 70 uS
  7. La secuencia continua (0 0 0 1 … etc. )
Captura de comunicaciones con el DHT11

Pulsos de respuesta del DHT11 y primeros bits en la trama del DHT11.

Captura de comunicaciones DHT11

Secuencia de inicio de comunicación con el DHT11. Se muestra el pulso de 20 ms y los datos que van mucho más rápido se ven como la barra naranja a la derecha.

Librería para el DHT11

Descarga e instalación

Nuestra librería para el DHT11 se encuentra alojada en Github, como siempre, agradeceremos cualquier contribución, corrección o ejemplo que quieras aportar. Puedes obtener la librería con los ultimos cambios y novedades desde nuestra página en github.com:

github_logohttps://github.com/geekfactory/DHTLib

Para obtener la ultima versión de la librería podemos usar git con el siguiente comando:

git clone --recursive https://github.com/geekfactory/DHTLib.git

La librería básica para el DHT11 consiste en 3 archivos de código fuente:

  • DHTLib.h – Contiene la declaración y documentación de las funciones (prototipos).
  • DHTLib.c – Implementación de las funciones para la lectura de los sensores de humedad y temperatura
  • DHTLibPort.h – Contiene los macros de preprocesador de C que permiten acceder a los puertos de entrada / salida
  • Config.h – Este archivo es incluido por todas las liberías que requieren ajustes en tiempo de compilación, aqui se definen los pines de entrada / salida a utilizar con el DHT11 y la velocidad del reloj.

Si no tienes instalado Git o no deseas utilizar esta herramienta, aquí esta el paquete de MPLAB X con el proyecto completo, listo para compilarse.

Configuración de pines en la librería

Para cambiar los pines asociados al DHT11 o la velocidad de reloj editamos el contenido del archivo Config.h que se encuentra en la carpeta “project_conf” dentro del proyecto de MPLAB X. El contenido del archivo en nuestro ejemplo es el siguiente:

#ifndef CONFIG_H
#define	CONFIG_H

/**
 * Configures here the processor speed
 */
#define CONFIG_TIMING_MAIN_CLOCK 2000000

/**
 * Configure here the registers and pins associated with the DHT11 sensor
 */
#define CONFIG_DHTLIB_OUTPIN		PORTBbits.RB2
#define CONFIG_DHTLIB_PORTPIN           PORTBbits.RB2
#define CONFIG_DHTLIB_TRIS		TRISBbits.TRISB2

#endif
// End of Header file

Uso básico para leer el sensor

Usar la librería para el DHT11 es bastante sencillo: Solamente debemos incluir el archivo DHTLib.h y luego, en alguna parte del comienzo de nuestro programa debemos llamar a la función dhtlib_init(). Posteriormente cuando deseemos obtener el valor de la temperatura deberemos llamar a la función dhtlib_read(). Esta ultima acepta como parámetro dos apuntadores a variables de tipo “uint8_t” donde se guardarán las medidas de humedad y temperatura. La función retorna un valor de tipo enumeración que nos informa si la comunicación con el sensor se pudo llevar a cabo de forma exitosa.

Dejamos aquí el código de la función principal de nuestro programa para el PIC que ilustra el uso de la librería para el DHT11. Hemos destacado las partes que todo programa que use la librería DHTLib debe tener:

#include <xc.h>
#include <stdio.h>
#include "../Tick/Tick.h"
#include "../LCD/LCD.h"
#include "../DHTLib.h"

// Configuración del dispositivo
// CONFIG1
#pragma config FOSC = INTOSCIO	// Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON       // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off)
#pragma config CCPMX = RB0      // CCP1 Pin Selection bit (CCP1 function on RB0)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
// CONFIG2
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal External Switchover bit (Internal External Switchover mode disabled)

// Buffer para trabajar sobre el texto que se envía a la pantalla LCD
char buf[20];

// Prototipos de las funciones definidas en este archivo
void dht11_task(); // Actualiza la pantalla con la temperatura y humedad
void led_task(); // Hace parpadear el led de estado en el pin 4 del puerto A

/**
 * Implementación de la funcionalidad principal del programa
 */
void main()
{
	//OSCCON = 0x6C;	// Para usar el oscilador interno PIC16F88 4 Mhz
	OSCCON = 0x7C; // Para usar el oscilador interno PIC16F88 8 Mhz
	ANSEL = 0x00; // Configuracion de pines analogicos y digitales
	TRISA = 0xE0;
	TRISB = 0xFF;

	// Preparamos las librerías para su uso
	lcd_init(0, 16, 2); // Iniciar el controlador de pantalla
	tick_init(); // Iniciar el contador / temporizador del sistema
	dhtlib_init(); // Preparar la comunicación con el sensor DHT11

	// Encendemos la pantalla LCD y escribimos titulo
	lcd_on();
	lcd_puts("  PRUEBA DHT11  ");

	// Ciclo principal de nuestra aplicación
	for (;;) {
		led_task();
		dht11_task();
	}
}

/**
 * Código para leer el sensor de temperatura y mostrar en pantalla
 */
void dht11_task()
{
	// Variables locales
	static uint32_t ltick = 0;
	uint8_t tb = 0, hb = 0;

	// La lectura de la temperatura y la humedad se realiza cada 5 segundos
	if (tick_get() - ltick >= TICK_SECOND * 5) {
		// Recordar el tiempo en el que se toma la lectura
		ltick = tick_get();
		// Colocar el cursor en la segunda linea
		lcd_goto(0, 1);
		// EN ESTA LINEA REALIZAMOS LA LECTURA DEL SENSOR
		enum dht_status result = dhtlib_read11(&tb, &hb);
		// Preparamos la cadena a mostrar
		if (result == E_DHTLIB_OK)
			sprintf(buf, "T: %02d C H: %02d%%  ", tb, hb);
		else
			sprintf(buf, "Sensor error: %02d    ", result);
		// Escribimos la cadena a la pantalla
		lcd_puts(buf);
	}
}

/**
 * Esta funcion alterna el estado del led cada 1/2 segundo
 */
void led_task()
{
	// Guarda el valor del tick en el que se alterno el pin del led
	static uint32_t ltime = 0;

	if (tick_get() - ltime >= TICK_SECOND / 2) {
		ltime = tick_get();
		PORTA ^= 0x10;
	}
}

/**
 *  Implementación del vector de interrupción (único)
 */
void interrupt isr(void)
{
	// Actualizar el conteo del tiempo
	tick_update();
	// Otras interrupciones deben manejarse aqui
}

Conexiones para el programa de prueba

El programa permite medir y desplegar la temperatura y humedad en una pantalla LCD de 16 x 2. Utilizamos la pantalla en modo de 4 bits y realizamos las conexiones como sigue:

  • RA0 – RA3 – Bus de datos para el display LCD (4 bits)
  • RA4 – Luz led indicadora de actividad del micro (parpadea una vez por segundo).
  • RB0 – Enable del chip controlador del LCD.
  • RB1 – RS (Register Select) del chip controlador del LCD.
  • RB2 – Conexión al pin de datos del sensor DHT11
Podemos personalizar esta configuración según nuestras necesidades, e incluso llevarla fácilmente a otros microcontroladores de esta misma familia como el PIC16F877A o incluso el PIC18F4550 que es mucho más potente. El hardware para la pueba nos quedó de la siguiente forma utilizando nuestra entrenadora con PIC16F88:
tutorial_dht11_montaje_2La velocidad de reloj en este caso es de 8 Mhz y todas las funciones que dependen del tiempo funcionan a esta velocidad. En caso de querer compilar este programa para un cristal más veloz o para el PIC18F4550 hay que modificar el archivo Config.h.
Hemos usado el oscilador interno del PIC16F88 a 8 Mhz (2 MIPS)  ya que la placa entrenadora tiene soldado un cristal de 4 Mhz y nos resultó insuficiente para implementar el protocolo requerido para el DHT11.

Conclusión

A fin de cuentas observamos que implementar la comunicación con el DHT11 es bastante sencillo y nuestra pequeña librería nos puede servir para varios microcontroladores más. Por ejemplo, nosotros ya la probamos en un ATMEGA8 y un PIC24HJ128GP504. Para migrar nuestra librería a otro microcontrolador, basta con escribir de nueva cuenta los macros de preprocesador que se encuentran en el archivo DHT11Port.h y definir los pines correctos en el archivo Config.h.

En la ultima versión de nuestra librería hemos incluido soporte para el sensor DHT22, que es similar al DHT11 pero ofrece mejor desempeño que este. Las funciones para leer datos desde el DHT22 se encuentran documentadas en el archivo DHTLib.h y pueden ser usadas de manera similar a las presentadas en este artículo

 

¡Compra en nuestra tienda virtual y apoyanos!