jueves, 6 de junio de 2019

1-WIRE Lectura de Temperatura y Humedad con DHT-11/22

Sensor Humedad/Temperatura DHT con PIC


Muchas gracias por tu visita a este blog relacionado con la programación de micro-controladores PIC, en esta entrada quiero mostrarles como utilizar los sensores de humedad y temperatura DHT que nos sera de gran utilidad en aplicaciones que requieran medir información ambiental o meteorología.

 El objetivo de esta entrada es realizar la lectura adecuada del sensor DHT con un microcontrolador PIC16F, para lo cual se implementara la comunicación con el protocolo 1-Wire respetando las especificaciones técnicas del sensor.

La programación se realizara utilizando el compilador XC8 y el entorno de desarrollo MPLABX, ambos disponibles de forma gratuita en la pagina de microchip.
Paso 1.Sobre el Sensor DHT

Es un sensor que mide Humedad y Temperatura de forma simultanea, cuenta con un procesador interno que realiza la medición al elemento capacitivo y termistor integrado, proporcionando el resultado a través de una señal digital. El proceso de comunicación con el PIC utiliza un único pin gracias al protocolo 1-Wire. Describiremos dos modelos identificados como DHT11 y DHT22 que poseen un encapsulado y disposición similar pero con las siguientes diferencias  técnicas:

  • DHT11: Trabaja con un rango de medición de temperatura de 0 a 50 °C con precisión de ±2.0 y un rango de humedad de 20% a 90% RH con precisión de 4%. Los ciclos de lectura debe ser como mínimo 1 o 2 segundos.
  • DHT22: El rango de  medición de temperatura es de  -40°C a 80 °C con precisión de ±0.5 y rango de humedad de 0 a 100% RH con precisión de 2%, el tiempo entre lecturas debe ser de 2 segundos.
A simple vista se puede observar que la diferencia con respecto a la medición esta en el rango y la precisión, pero revisando con mas detalle las especificaciones el pulso de inicio 1-Wire utiliza diferentes tiempos y el resultado se representa en un formato diferente, además el DHT11 soportar ciclos mas rápidos de lectura.


Paso 2. Conectar el Modulo al PIC16F.

El voltaje de operación nominal es 5V, la salida requiere utilizar una resistencia pull-up(entre 1-5k) para asegurar los niveles lógicos con el Microcontrolador, el manual también recomienda agregar un capacitor de 100nF entre VDD y GND para un mejor filtrado de la señal.


Es posible utilizar cualquier pin digital del PIC, eso si debe asegurarse de que sea bidireccional, algo que también debemos considerar es la distancia a la que puede estar el sensor del cual no tengo un dato exacto del limite máximo, pero he realizado pruebas sin inconvenientes hasta una distancia de 30mts, y considero que a mayores distancias se deberá utilizar un resistencia pull-up mínima(1k) considerando la perdida de voltaje en las lineas y posibles interferencias que puedan afectar a la señal de los datos.

Paso 3. Programación y lectura del sensor.

A fin de facilitar la rápida implementación del modulo, se crearon procedimientos en el archivo dht.c incluidos en la carpeta del proyecto MPLABX, en la ultima sección veras el enlace de descarga. 
El programa principal debe incluir las siguientes lineas que permiten definir el tipo y los pines utilizados con este sensor.
 
#define _XTAL_FREQ 4000000
#define DHTTYPE 11 // Modelo de sensor
#define DHTpin PORTBbits.RB0  //Pin de comunicación DTH
#define DHTtris TRISBbits.TRISB0 //Bit de control
#include "dht.h"

Para establecer la comunicación bidireccional utilizando solo un conductor, el sensor utiliza una variante del protocolo 1-Wire que establece reglas de temporización para las señales lógicas del microcontrolador.
 
En cada señal de lectura(Start signal) que realiza el microcontrolador, el sensor envía una señal de respuesta(Response signal) seguidos de una trama de 40bits, la duración de esta trama es variable en función de los niveles lógicos de cada bit recibido. 
Normalmente el pin del bus se encuentra en estado alto, entonces el (Start signal) que establece el microcontrolador es un pulso a nivel bajo con una duración de al menos 1ms(DHT22) o 18ms(DHT11) antes de normalizar el bus(nivel alto). Observe el diagrama de tiempos.
 
El sensor como respuesta(Response signal) colocara el bus en nivel bajo por 80us para luego normalizar esperando otros 80us, partir de este momento el sensor empezara a enviar una trama de 40 bits con la siguiente regla de tiempos:
(Bit 0) Nivel bajo por 50us y normalizar por un tiempo entre 25-28us.
(Bit 1) Nivel bajo por 50us y normalizar por un tiempo de 70us.
 
El siguiente código muestra un ejemplo simple para dar inicio al proceso de lectura en el sensor, siguiendo el diagrama de señal que se muestra en la parte superior.

    DHTtris = 0;    //Modo salida
    DHTpin = 0;     //Inicia el pulso bajo
    if(DHTTYPE == 22)
      __delay_ms(4); //Mantiene mínimo 1ms
    if(DHTTYPE == 11)
      __delay_ms(18);//Mantiene mínimo 18ms
    DHTpin = 1;     //Coloca el bus en nivel alto
    __delay_us(20); //Espera mínimo 20uS
    DHTtris = 1;    //Modo entrada
    while(DHTpin);  //Espera pulso bajo(hasta 40uS)
    while(!DHTpin); //Espera pulso alto(hasta 80uS)
    while(DHTpin);  //Espera pulso bajo(hasta 80uS)

 
Para mejorar este procedimiento inicial se deberá considerar limitar el tiempo de espera dentro de cada bucle indefinido, para esto se puede crear un procedimiento que utilice una variable de control que permita determinar la cantidad de tiempo transcurrido durante la espera.

De los 40 bits recibidos del sensor los dos bytes mas significativos representan la medición de humedad, los siguientes dos bytes corresponden a la medición de temperatura, finalmente un ultimo byte se utiliza para la comprobación de errores que se calcula con la suma de todos los bytes recibidos.


El sensor DHT22 representa la medición como un dato entero de 16-bits y como puede medir temperaturas negativas se utiliza el bit mas significativo del tercer byte para indicar el signo.

Ahora mostraremos la lista de los procedimientos que podemos utilizar para hacer uso de este sensor:
  • DHTSetup(): Es un procedimiento simple que coloca el pin de datos como entrada manteniendo un nivel lógico alto en el bus 1-Wire
  • DHTUpdate(dhtstruct *dht): Esta función realiza la lectura de las mediciones que posee el sensor y retorna un valor del tipo char para indicar si el proceso se realizo correctamente(1) o se produjo un error(0), ademas puesto que la lectura contiene información de humedad y temperatura se utiliza como parámetro un puntero a una estructura ya definida en el encabezado.
         typedef struct
         {
           unsigned int rawhum; //16bits para la humedad
           unsigned int rawtem; //16bits para la Temperatura
         } dhtstruct;




Paso 4. Prueba y Simulación.

Ahora escribiremos un pequeño programa para poner en practica y demostrar el uso de este sensor utilizando los procedimientos previamente descritos.

El siguiente código describe un programa que realiza la lectura de un sensor DHT11, muestra el resultado por el puerto USART en su formato de bits original y su conversión final.
  
#pragma config FOSC = INTRC_NOCLKOUT, WDTE = OFF, LVP = OFF
#include <xc.h>
#include <stdio.h>
#define _XTAL_FREQ 4000000
#define DHTTYPE 11  //Modelo DHT11
#define DHTpin PORTBbits.RB0 //Pin de datos RB0
#define DHTtris TRISBbits.TRISB0
#include "dht.h"
dhtstruct dht; //instancia a la estructura dht
unsigned int humedad, temperatura;
void main(void)
{
    char res;
    ANSEL = 0;  //Desactiva las entradas analógicas AN0-AN7
    ANSELH = 0; //Desactiva las entradas analógicas AN7-AN13
    OSCCONbits.IRCF = 6; //Configura el intosc a 4MHz Tcy = 0.5uS
    while(!OSCCONbits.HTS); //Espera estabilidad del oscilador
    DHTSetup();//Configura el pin de lectura para el DHT
   
    //CONFIGURAICON DEL MODULO USART 9600 BAUDIOS
    TXSTAbits.BRGH = 1; //UART en modo alta velocidad
    BAUDCTLbits.BRG16 = 1; //Generador de baudios en modo 16-bits
    SPBRG = 0x67; //X = _XTAL_FREQ/(4*BAUD) - 1;
    SPBRGH = 0x00;//X=[4000000/(4*9600)]-1 = 103 = 0x0067
    TXSTAbits.TXEN = 1; //Habilita la transmisión
    RCSTAbits.CREN = 1; //Habilita la recepción
    RCSTAbits.SPEN = 1; //Habilita el modulo USART
    while(1)
    {
        res = DHTUpdate(&dht); //Inicia la lectura del sensor
        if(res) //Verifica si se realizo correctamente
        {
            humedad = dht.rawhum >> 8; //Lectura la parte entera de la humedad
            temperatura = dht.rawtem >> 8; //Lectura la parte entera de la temp
            printf("Raw Hu=%04X Te=%04X\r\n", dht.rawhum, dht.rawtem);
            printf("Final Hu=%02u Te=%02u\r\n", humedad, temperatura);
        }
        __delay_ms(3000);
    }
}


1. Valores recibidos por la terminal USART


2. Ensayo del programa con un PIC16F886



Paso 5. Conclusiones y Recomendaciones.


Luego de hacer la demostración del programa podemos concluir que podemos implementar fácilmente cualquiera de estos dos sensores.

Para la conversión de lectura del sensor DHT22 deberá hacer una división entre 10, para conseguir el valor entero y si desea precisión con decimales debe guardar el resultado en variables del tipo float.
  float humedad, temperatura;
  humedad = dht.rawhum / 10.0F;
  temperatura = dht.rawtem / 10.0F;
  printf("Raw Hu=%f Te=%f\r\n", humedad, temperatura);
 
Los procedimientos descritos han sido probados a frecuencias igual o superiores a 4MHz en las versiones Free y Pro del compilador XC8; si requiere trabajar con frecuencias menores a 4MHz sera necesario modificar la función DHTReadbyte del archivo dht.c.

Una desventaja con estos sensores es la velocidad de las lecturas y el tiempo de espera para realizar una lectura nueva(2 segundos), aunque en muchos casos no es un factor negativo si consideramos que la Temperatura y Humedad son variables que no cambian de forma rápida.
 
Aquí dejo el enlace para que puedas descargar el proyecto creado en MPLABX para este blog, 
 
Enlace para Descarga -> DHTPIC16F 

Esperando que este ejemplo pueda servirte de ayuda agradezco tu visita al blog, atentamente Pablo Zárate
contacto:pablinza@me.com / pablinzte@gmail.com @pablinzar
Santa Cruz de la Sierra - Bolivia

 

No hay comentarios.:

Publicar un comentario