![]() |
Fig1. Circuito con Sensor DHT11 |
El objetivo de esta entrada es realizar la lectura adecuada del sensor DHT con un microcontrolador PIC16F en la que se establece una comunicación serial asíncrona por un solo cable, con un protocolo similar a 1-Wire conforme a las especificaciones técnicas del sensor.
Es un sensor digital para medir la Humedad relativa y Temperatura ambiental, cuenta con un procesador interno que realiza la medición de un elemento capacitivo y un termistor, proporcionando el resultado a través de una señal digital. La interfaz de comunicación con el PIC utiliza una linea bidireccional en modo half-duplex. Seguidamente describiremos los dos modelos identificados como DHT11 y DHT22 que trabajan entre 3.3 a 5.0V y poseen un encapsulado y disposición de pines compatible con las siguientes diferencias técnicas:
Fig2. Descripción de pines DHT11/22 |
DHT11: Trabaja con un rango de medición de temperatura de 0 a 50 °C con una exactitud de ±2.0 y 1°C de precisión y el rango de medición para la humedad relativa es de 20% a 80% con una exactitud del 5% y 1% de precisión. En ambos casos el resultado esta conformado por 16-bit siendo un byte para el valor entero y el otro byte para el decimal, pero este modelo posee una resolución de 8-bit por que únicamente se emplea la parte entera del resultado. Los ciclos de lectura debe ser como mínimo 2 segundos.
DHT22: El rango de medición de temperatura es de -40°C a 80 °C con exactitud de ±0.5 °C y precisión de 0.1°C. El rango de humedad es de 0 a 100% RH con exactitud del 2% y precisión del 0.1%. El resultado de ambas mediciones esta conformado por 16-bit, el tiempo entre lecturas debe ser de 2 segundos.
A simple vista podemos destacar que la principal diferencia entre ambos modelos es el rango de operación y la exactitud pero también hay diferencias en el proceso para establecer la comunicación con el sensor y el resultado de una medición, además que los ciclos de lectura en un DHT22 son mas lentos (2 a 5 segundos) debido a su mayor precisión en el resultado.
Como ya mencionamos previamente el voltaje de operación nominal para estos sensores es de 5V, pero pueden trabajar a menor voltaje 3.3V considerando que la distancia entre el sensor y el MCU sera mucho menor, adames en el pin de comunicación SDA(DATA) es necesario adicionar una resistencia en modo pull-up de 4.7k con la que es posible conectar a una distancia de 30 metros, una resistencia de mayor reduce esta distancia de conexión, también es recomendable agregar una capacitor de 100nF entre VDD y GND para un mejor filtrado en el voltaje de alimentación, la figura 3 muestra la conexión necesaria entre el sensor y el MCU.
![]() |
Fig3. Conexión entre el Sensor y el MCU |
Para
establecer la comunicación bidireccional a través de la linea SDA(DATA) el microcontrolador (MCU) utilizara un pin configurado como salida al momento de establecer un nivel bajo en SDA y como entrada tri-state para leer los niveles de SDA, utilizando el siguiente procedimiento de señalización y su respectiva temporización:
![]() |
Fig4. Protocolo de comunicación MCU - Sensor |
Señal de Establecimiento (Start signal): Normalmente la linea SDA se encuentra en un estado ALTO, entonces en esta etapa el MCU establece la linea SDA en nivel BAJO por un tiempo de 1ms(DHT22) o 18ms(DHT11) para luego liberar la linea a su estado inicial es decir un nivel ALTO.
Señal de Respuesta (Response signal): En esta etapa el MCU tiene configurado el pin como entrada tri-state esperando a que el sensor coloque la linea SDA en nivel BAJO como respuesta al Start Signal, la duración este cambio sera al menos 80us y luego el sensor libera la linea SDA por un tiempo mínimo de 80us. A partir de este momento el sensor empezar a enviar los datos de la ultima medición efectuada.
Datos (Data transfer): En esta etapa el MCU mantiene el pin como entrada tr-state para recibir los 40-bits de datos por parte del sensor, cada bit se interpretara conforme a la siguiente regla de tiempos:
(Bit 0) Nivel BAJO por 50us y ALTO por 25 a 28us.
(Bit 1) Nivel BAJO por 50us y ALTO por 70us.
Una vez completado el procedimiento de comunicación, el resultado de 40 bits recibidos del sensor mantienen el formato de campos que se muestra en la figura 5, donde los dos bytes mas significativos representan el valor de la humedad, los siguientes dos bytes corresponden a la temperatura y finalmente el ultimo byte se utiliza para verificar error de paridad y es un resultado de sumar los cuatro primeros bytes del dato.
![]() |
Fig6. Esquema del circuito PIC |
#define DHT_PORT PORTB //Puerto asociado al Sensor
#define DHT_TRIS TRISB //Registro de Configuración del Puerto
#define DHT_DEV1 0x10 //Mascara del pin RB4 conectado al DHT
/* END USER PORT DEFINITION */
Ahora mostraremos la lista de los procedimientos que podemos utilizar para hacer uso de este sensor:
DHTSetup(devmask): Este procedimiento configura los pines definidos en la cabecera para su posterior uso con el sensor DHT, el pin colocar por defecto la linea SDA en nivel ALTO. Siendo posible iniciar uno o mas pines a los que se conectara un sensor, por ejemplo:
DHTSetup(DHT_DEV1); //Configura un pin DHTDHTSetup(DHT_DEV1|DHT_DEV2|DHT_DEV3); //Configura tres pines DHT
DHTStart(devmask, type): Es una función que establece el pulso de inicio y retorna uno (1) al finalizar el pulso ya cuando el nivel de la linea SDA es ALTO. Es importante recalcar que esta función debe llamarse consecutivamente hasta que devuelva un uno (1) y luego de esto recién iniciar la lectura del sensor.
DHTRead(devmask, type, dst): Esta es la función encargada de recibir los 40-bits del sensor DHT, el resultado estará almacenado en la dirección dado por el parámetro dst (puntero a byte) y retorna uno (1) solo si la verificacion de paridad es correcta. Debe tomar en cuenta que esta función es bloqueante y se deberia evitar interrupciones mientras se ejecuta. A continuación veremos el siguiente ejemplo de uso.
if(DHTStart(DHT_DEV1, DHT11)) //Emite pulso de inicio DHT11{
INTCONbits.GIE = 0; //Desactiva interrupción global
res = DHTRead(DHT_DEV1, DHT11, buffer); //Lectura de los 40-bits
INTCONbits.GIE = 1; //Activa interrupción global
if(res) //Valido solo si la paridad es correcta
//Se procesan los datos almacenados en buffer
DHTUpdate(type, src): Este procedimiento es el encargado de procesar el resultado de 40-bits de una lectura previa, y obtener los valores de humedad relativa y temperatura en el sistema decimal, para esto la librería utiliza una estructura de datos DHT con los siguientes campos:
{
uint8_t tem; //Temperatura parte entera
uint8_t temr;//Temperatura parte decimal (fracción)
uint8_t hum; //Humedad parte entera
uint8_t humr;//Humedad parte decimal
} DHT_t;
{
INTCONbits.GIE = 0;
if(DHTRead(DHT_DEV1, DHT11, buffer))
{
printf("Raw Hu=%X%X Te=%X%X\r\n",buffer[0],buffer[1],buffer[2],buffer[3]);
DHTUpdate(DHT11, buffer);
printf("Final Hu=%u Te=%u\r\n",DHT.hum, DHT.tem);
}
INTCONbits.GIE = 1;
}
Un programa completo para llevar a cabo la lectura del sensor DHT11 con intervalos de dos segundos, tendría la siguiente estructura:
{
MCUSetup();
DHTSetup(DHT_DEV1);
while(1)
{
if(tickms) //Valida cada ms
{
tickms = 0;
taskLED(); //Destellar LED
taskDHT(); //Lectura y envío datos Sensor
}
}
}
Donde la tarea para efectuar la lectura taskDHT que es llamada continuamente cada un milisegundo, controlara su estado de ejecución a través del siguiente código:
{
static uint8_t state = 0;
static uint16_t cnt = 0;
uint8_t res;
cnt++;
switch(state)
{
case 0: //Lectura y muestra del sensor DEV1
if(DHTStart(DHT_DEV1, DHT11))
{
INTCONbits.GIE = 0;
res = DHTRead(DHT_DEV1, DHT11, buffer);
INTCONbits.GIE = 1;
if(res) //Si paridad es correcta
{
DHTUpdate(DHT11, buffer);
print("Final Hu=");
printByte(DHT.hum);
print("% Te=");
printByte(DHT.tem);
print("\'C\r\n");
}
state = 1; //próxima espera
}
break;
case 1://Espera nuevo ciclo dos segundos
if(cnt == 2000)
{
cnt = 0;
state = 0;
}
break;
}
}
Una vez compilado y preparado el código en el PIC, se llevaran a cabo las conexiones del circuito incluido la comunicación con una terminal serial desde el ordenado (PC), entonces el resultado que nos arrojara el MCU sera el que se muestra en la figura 8.
Los procedimientos que se mostraron con antelación son parte del archivo principal main.c
que contiene el proyecto, este archivo contiene código adicional que no
se ha detallando en la presente publicación, por esta razón dejo el
enlace para que puedas descargarlo y analizar con mas detalles desde el
IDE MPLABX. <Proyecto DHT11 con PIC16>
Si quieres ver como compilar e implementar los proyectos de este blog, elaborados con MPLABX mira este vídeo.<Compilando proyectos MPLABX>
Luego
de hacer la demostración del programa podemos concluir que podemos
implementar fácilmente cualquiera de estos dos sensores.
Una desventaja con estos sensores es la velocidad de las lecturas y el
tiempo de espera para realizar una lectura nueva que es mayor a dos segundos, aunque en muchos casos puede no ser un inconveniente debido a que la
Temperatura y Humedad relativa son variables que no cambian de forma rápida.
Sin
mas que mencionar agradezco tu visita al blog y espero que el ejemplo
visto pueda ser útil en tu formación y el proyecto que desarrollas.
Atentamente, Pablo Zárate Arancibia email: pablinza@me.com / pablinzte@gmail.com, @pablinzar
Santa Cruz de la Sierra - Bolivia