viernes, 11 de abril de 2014

Sensores de temperatura y humedad DHTxx

Los sensores DHT11 o DHT22 son unos pequeños dispositivos que nos permiten medir la temperatura y la humedad relativa. A diferencia de otros sensores, éstos los tendremos que conectar a pines digitales, ya que la señal de salida es de este tipo. Entre las desventajas, el DHTxx solo lee enteros, no podemos leer temperaturas con decimales por lo que tenemos que pensarlo muy bien a la hora de utilizar este sensor para trabajos en los que se requieran lecturas precisas de temperatura y/o humedad. Llevan un pequeño microcontrolador interno para hacer el tratamiento de señal.

¿Cómo funcionan?

Los DHTxx (xx por “11″ o “22″) se componen de un sensor capacitivo para medir la humedad y de un termistor. Ambos sensores están calibrados por lo que no es necesario añadir ningún circuito de tratamiento de señal. Esto sin duda es una ventaja porque nos simplifica las cosas en la protoboard. Además, como los DHTxx han sido calibrados en laboratorios y presentan una gran fiabilidad.


Ambos sensores funcionan con ciclos de operación de duración determinada (1s en el caso del DHT11 y 2s en el caso del DHT22). En este tiempo, el microcontrolador externo (Arduino por ejemplo) y el microcontrolador que lleva integrado el sensor, se hablan entre sí de la siguiente manera:

  • El microcontrolador (Arduino) inicia la comunicación.
  • El sensor responde estableciendo un nivel bajo de 80us y un nivel alto de 80us.
  • El sensor envía 5 bytes.
  • Se produce el handshaking.

¿Cuál elijo, DHT11 o DHT22?

Tanto DHT11 como DHT22 son geniales para empezar a jugar con Arduino o si estas pensando en alguna aplicación que requiera medir humedad y/o temperatura. Son además muy fáciles de conectar y sólo requieren de un pin de Arduino. Sin embargo, el DHT22 tiene rangos de medida más amplios y mayor resolución, a cambio de resultar algo más caro.

A modo resumen, las características de cada uno de los sensores las resumimos en la siguiente tabla:


Por lo que se refiere al pinout, los pines del DHT11 y del DHT22 siguen el mismo orden:




En la siguiente figura mostramos la conexión entre un Arduino Uno y un DHT22 sobre la protoboard:


Del montaje realizado, destacamos que no utilizamos el pin 3, y que La resistencia (10 K en este caso) tiene que conectarse entre la alimentación y el pin de salida de datos. También es interesante ver que, aunque el sensor entrega señales de naturaleza analógica como son la humedad y la temperatura, estas señales las leemos por un pin digital de Arduino. Este hecho revela que en un solo pin somos capaces de obtener dos lecturas, y nos damos cuenta de la ventaja que aportan las señales digitales frente a las analógicas: menos cables, más simplicidad en los montajes.

Yo he usado un módulo que adquirí a un precio muy económico y que me ahorra estar poniendo la resistencia de pull-up. Os pongo una imagen del módulo:
De izquierda a derecha, el uso de los pines es el siguiente
  • VCC
  • Out
  • GND
Programación de Arduino

Hay tutoriales que explican como leer este sensor sin dicha librería, sin embargo el tema es bastante complicado para alguien que no esté acostumbrado a programar. Se necesita leer una onda cuadrada en la cual se envían los bits con separaciones de unos cuantos microsegundos. 



Estructura de los datos del sensor DHT11 :
  1. Humedad (entero) : 8bit
  2. Humedad (fracción) : 8bit
  3. Temperatura (entero) :8bit
  4. Temperatura (fracción) : 8bit
  5. Check sum : Humedad (entero) + Humedad (fracción) + Temperatura (entero) + Temperatura (fracción)
La verdad prefiero usar la librería DHT11. Para ello, la descargo del siguiente link de adafruit (para instalar una librería consulta este enlace).

Instrucciones

#include "DHT.h" : Añadimos la librería para trabajar con el sensor
DHT dht(PinOut,TipoDHT) : Definimos con PinOut el pin al que se conectará el sensor en la placa de Arduino y TipoDHT el tipo de sensor que puede ser DHT11, DHT21 y DHT22). Ademas declaramos dht como un objeto DHT
int h = dht.readHumidity(); Lee el valor de la humedad relativa
int t = dht.readTemperature(); Lee el valor de la temperatura


Ejemplos

Para probar nuestro módulo, podemos utilizar el siguiente programa que es una variación del programa que viene como ejemplo en la librería:

// Sketch de ejemplo para testear el famoso sensor DHT de humedad y temperatura
// Escrito por ladyada, de dominio público
// Modificado por Regata para www.tallerarduino.wordpress.com
#include "DHT.h"  //Añadimos la libreria con la cual trabaja nuestro sensor
#define DHTPIN 2     // Indicamos el pin donde conectaremos la patilla data de nuestro sensor
// Descomenta el tipo de sensor que vas a emplear. En este caso usamos el DHT11
#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT22   // DHT 22  (AM2302)
//#define DHTTYPE DHT21   // DHT 21 (AM2301)
// Conecta el pin 1 (el de la izquierda) del sensor a +5V
// Conecta el pin 2 del sensor al pin que has elegido para DHTPIN
// Conecta el pin 4 (el de la derecha) del sensor a GROUND
// Conecta una resistencia de 10K del pin 2 (data) al pin 1 (+5V) del sensor
DHT dht(DHTPIN, DHTTYPE);  //Indica el pin con el que trabajamos y el tipo de sensor
int maxh=0, minh=100, maxt=0, mint=100;  //Variables para ir comprobando maximos y minimos
void setup()
{
  //Inicio comunicacion serie para ver los datos en el ordenador
  Serial.begin(9600);
  //Mensaje de inicio
  Serial.println("Comprobacion sensor DHTxx:");
  //Iniciamos el sensor
  dht.begin();
}
void loop()
{
  // La lectura de la temperatura o de la humedad lleva sobre 250 milisegundos 
  // La lectura del sensor tambien puede estar sobre los 2 segundos (es un sensor muy lento)
  int h = dht.readHumidity();  //Guarda la lectura de la humedad en la variable float h
  int t = dht.readTemperature();  //Guarda la lectura de la temperatura en la variable float t
  // Comprobamos si lo que devuelve el sensor es valido, si no son numeros algo esta fallando
  if (isnan(t) || isnan(h)) // funcion que comprueba si son numeros las variables indicadas
  {
    Serial.println("Fallo al leer del sensor DHT"); //Mostramos mensaje de fallo si no son numeros
  } else {
    //Mostramos mensaje con valores actuales de humedad y temperatura, asi como maximos y minimos de cada uno de ellos
    Serial.print("Humedad relativa: ");
    Serial.print(h);
    Serial.print(" %\t");
    Serial.print("Temperatura: ");
    Serial.print(t);
    Serial.println(" *C");
    //Comprobacion de maximos y minimos de humedad y temperatura
    if (maxh<h)
      maxh=h;
    if (h<minh)
      minh=h;
    if (maxt<t)
      maxt=t;
    if (t<mint)
      mint=t;
    Serial.print("Max: ");
    Serial.print(maxh);
    Serial.print(" % ");
    Serial.print("Min: ");
    Serial.print(minh);
    Serial.print(" %\t");
    Serial.print("Max: ");
    Serial.print(maxt);
    Serial.print(" *C ");
    Serial.print("Min: ");
    Serial.print(mint);
    Serial.println(" *C\n");
  }
  delay(1000);
}


Si no queremos utilizar las librerías, podemos utilizar este código:


//Programa test para sensor DHT11 de humedad y temperatura
//cleaned by sucotronic
//Modificado por Regata para tallerarduino.wordpress.com
#define DHTPIN 2 // Indicamos el pin del arduino donde conectamos el sensor
byte bGlobalErr;  //para pasar el codigo de error de vuelta de las funciones
byte DHTDAT[5];  //Array para almacenar los bytes enviados por el sensor
int maxh=0,minh=100,maxt=0,mint=100,t,h; //variables para ir guardando las maximas de
// humedad y temperatura y las minimas de humedad y temperatura
void setup()
{
  InitDHT();  // Inicializamos el pin empleado para leer el sensor
  Serial.begin(9600);  //Iniciamos comunicacion serie con el pc para ver los datos leidos
  Serial.println("Test sensor DHT11:");
  delay(1000);  //Este delay es para esperar el tiempo recomendado para acceder al sensor (1 segundo)
}
void loop()
{
  ReadDHT(); // Leemos el sensor y almacenamos el resultados en variables globales
  switch (bGlobalErr)
  {
     case 0:
        //Como en este sensor la humedad y la temperatura no nos sale con decimales,
        //podemos desechar los bytes 1 y 3 de la lectura del sensor
        h=DHTDAT[0];
        t=DHTDAT[2];
    Serial.print("Humedad relativa: ");
    Serial.print(h);
    Serial.print(" %\t");
    Serial.print("Temperatura: ");
    Serial.print(t);
    Serial.println("*C");
        //Comprobacion de maximos y minimos de humedad y temperatura
        if (maxh<h)
          maxh=h;
        if (h<minh)
          minh=h;
        if (maxt<t)
          maxt=t;
        if (t<mint)
          mint=t;
        Serial.print("Max: ");
        Serial.print(maxh);
        Serial.print(" % ");
        Serial.print("Min: ");
        Serial.print(minh);
        Serial.print(" %\t");
        Serial.print("Max: ");
        Serial.print(maxt);
        Serial.print(" *C ");
        Serial.print("Min: ");
        Serial.print(mint);
        Serial.println(" *C\n");
        break;
     case 1:
        Serial.println("Error 1: Condicion de start 1 no conocida.");
        break;
     case 2:
        Serial.println("Error 2: Condicion de start 2 no conocida.");
        break;
     case 3:
        Serial.println("Error 3: DHT checksum error.");
        break;
     default:
        Serial.println("Error: Encontrado codigo irreconocible.");
        break;
  }
  delay(1000);// Esperamos 1 segundo para la siguiente lectura
}
// Initilize pin for reading
void InitDHT(){
        pinMode(DHTPIN,OUTPUT);
        digitalWrite(DHTPIN,HIGH);
}
void ReadDHT(){
  bGlobalErr=0;
  byte dht_in;
  byte i;
  // Enviamos el comando "start read and report" al sensor
  // Primero: ponemos a "0" el pin durante 18ms
  digitalWrite(DHTPIN,LOW);
  delay(18);
  delay(5);//TKB, frm Quine at Arduino forum
  //Segundo: ponemos a "1" el pin durante 40us,enviamos el comando de "start read" al sensor
  digitalWrite(DHTPIN,HIGH);
  delayMicroseconds(40);
  //Tercero: Cambiamos el pin de Arduino a entrada de datos
  pinMode(DHTPIN,INPUT);
  delayMicroseconds(40); //Esperamos 40 us
  dht_in=digitalRead(DHTPIN);
  //si hay un 1 en la lectura del pin, indicamos que hay error de tipo 1
  if(dht_in)
  {
    bGlobalErr=1;
    return;
  }
  delayMicroseconds(80); //Esperamos 80us
  dht_in=digitalRead(DHTPIN);
  //si no hay un 1 en la lectura del pin, indicamos que hay error de tipo 2
  if(!dht_in){
    bGlobalErr=2;
    return;
  }
  /*Despues de 40us a nivel bajo, el pin deberia de estar durante 80us a nivel alto.
  Despues de esto comienza el envio del primer bit hasta alcanzar los 40 bits enviados.
  The routine "read_dht_dat()" expects to be called with the system already into this low.*/
  delayMicroseconds(80); //Esperamos 80us
  //Ahora comienza la recepcion de datos, son 5 bytes de datos, es decir 40 bits, almacenamos en un array de 5 bytes
  for (i=0; i<5; i++)
    DHTDAT[i] = read_dht_dat();
  //Cuarto: Volvemos a configurar el pin del arduino como salida
  pinMode(DHTPIN,OUTPUT);
  //Quinto:Ponemos a "1" el pin de salida
  digitalWrite(DHTPIN,HIGH);
  //Comprobamos si los datos recibidos coinciden con el checksum recibido
  byte DHTCHECKSUM = DHTDAT[0]+DHTDAT[1]+DHTDAT[2]+DHTDAT[3];
  //Si no coincide el byte recibido de checksum con la suma de los 4 primeros bytes enviamos error tipo 3
  if(DHTDAT[4]!= DHTCHECKSUM)
    bGlobalErr=3;
  };
byte read_dht_dat()
{
  //Cogemos 8 de los bits recibidos y los devolvemos como un byte.
  //Si por ejemplo recibimos 00000100 , devolvemos en decimal 4
  byte i = 0;
  byte result=0;
  for(i=0; i< 8; i++)
  {
    //Entramos mientras dura el primer bit de start (a nivel bajo durante 50us) del byte
    //Esperamos hasta que el pin se pone a nivel alto señalizando fin del la transmision del bit de start
    while(digitalRead(DHTPIN)==LOW);
    //La linea de datos debera estar ahora a nivel alto durante 27 o 70us,
    //dependiendo si un "0" o un "1" esta siendo enviado respectivamente
    delayMicroseconds(30);  //Esperamos 30 us
    if (digitalRead(DHTPIN)==HIGH)
      result |=(1<<(7-i));  //Si despues de los 30us el pin permanece a "1" añadimos un 1 al byte, sino queda un "0"
    //Esperamos hasta que el pin se vuelve a poner a nivel bajo,
    // el cual indica la señal de start del siguiente bit de la transmision
    while (digitalRead(DHTPIN)==HIGH);
  }
  return result; //devolvemos el resultado
}

Fuentes

Datasheet:
Más información:


No hay comentarios:

Publicar un comentario

Nota: solo los miembros de este blog pueden publicar comentarios.