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:

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.

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.

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:
- 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.
- Pulso de respuesta bajo del DHT11 de alrededor de 80 uS.
- Pulso de respuesta alto del DHT11 de alrededor de 80 uS.
- Primer bit “0” compuesto de un pulso bajo de 50 uS y otro alto de alrededor de 25 uS
- Segundo bit “0”
- Tercer bit “1” compuesto de un pulso bajo de 50 uS y otro alto de alrededor de 70 uS
- La secuencia continua (0 0 0 1 … etc. )

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:
https://github.com/geekfactory/DHTLib
Para obtener la ultima versión de la librería podemos usar git con el siguiente comando:
1 | 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.
[wpdm_file id=1 title=”true” desc=”true” template=”facebook drop-shadow curved curved-hz-2″ ]
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | #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

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