«

»

nov 05

Sensor de temperatura y humedad DHT11

Ya hemos visto en otra entrada como medir la humedad empleando un termómetro de bulbo húmedo y uno de bulbo seco, emulando un psicrómetro. Una solución mucho más sencilla es utilizar un componente discreto como el DHT11 que no tiene mantenimiento como pasaba con el psicrómetro y no necesita complicadas fórmulas o tablas para obtener la humedad. Eso sí, la resolución no es ni de lejos tan buena como la que nos proporciona un DS1820 en la medición de temperatura, tiene un error de hasta +- 2ºC frente a los 0.5ºC del DS1820. En cuanto a la humedad relativa tenemos un error del hasta el +-5% con medidas entre el 20% y el 90% de humedad.

El datasheet lo podemos encontrar aquí

De las cuatro patas sólo vamos a emplear 3, dos son la alimentación entre 3 y 5.5V y la tercera se usa como bus de datos de un sólo hilo tanto para leer como para escribir, es necesario conectar una resistencia de pull-up de 4K7 en esta línea.

No hay reloj, así que la comunicación es asíncrona, hacemos una petición de datos y el DHT11 nos responde con una trama devolviendo la temperatura y la humedad relativa. Cada bit transmitido empieza por un flanco de cero a uno y el valor del bit viene dado por el tiempo en estado alto (26-28 us es un 0 y 70 us es un uno).

Aquí os dejo un ejemplo para leer los valores, devuelve cero si todo va bien, o un número menor que cero en caso de defecto. Los valores de temperatura y humedad se escriben en las variables T_DHT11 y RH_DHT11 y la función está preparada para trabajar en el PIN_B5 del PIC.

#define DHT11 PIN_B5
float T_DHT11,RH_DHT11;
UINT8 Tint,Tdec,RHint,RHdec,CRC;

int leer_DHT11(void)
{
UINT16 i,j;
UINT8 chkCRC;
UINT32 Respuesta;

   Tint=0;
   Tdec=0;
   RHint=0;
   RHdec=0;
   Respuesta=0;
   CRC=0;
   set_tris_b(get_tris_b()&0xEF);
   output_high(DHT11);
   delay_ms(25);
   output_low(DHT11);
   delay_ms(25); // Por lo menos 18us
   output_high(DHT11);
   delay_us(30);
   set_tris_b(get_tris_b()|0x10);
   for (i=0;i<100;i++) { // Espera respuesta de 20-40us
      if (!input(DHT11)) break;
      delay_us(1);
   }
   if (i==100) return -1;
   for (i=0;i<100;i++) { // Espera respuesta de 80us
      if (input(DHT11)) break;
      delay_us(1);
   }
   if (i==100) return -2;
   for (i=0;i<100;i++) { // Espera respuesta de 80us
      if (!input(DHT11)) break;
      delay_us(1);
   }
   if (i==100) return -3;
   for (i=0;i<32;i++) {
      for (j=0;j<100;j++) {
         if (input(DHT11)) break;
         delay_us(1);
      }
      if (i==100) return -4;
      delay_us(30);
      Respuesta<<=1;
      if (input(DHT11)) Respuesta|=1;
      for (j=0;j<100;j++) {
         if (!input(DHT11)) break;
         delay_us(1);
      }
      if (i==100) return -5;
   }
   for (i=0;i<8;i++) {
      for (j=0;j<100;j++) {
         if (input(DHT11)) break;
         delay_us(1);
      }
      if (i==100) return -4;
      delay_us(30);
      CRC<<=1;
      if (input(DHT11)) CRC|=1;
      for (j=0;j<100;j++) {
         if (!input(DHT11)) break;
         delay_us(1);
      }
      if (i==100) return -5;
   }
   RHint=make8(Respuesta,3);
   RHdec=make8(Respuesta,2);
   Tint=make8(Respuesta,1);
   Tdec=make8(Respuesta,0);
   chkCRC=(RHint+RHdec+Tint+Tdec)&0xFF;
   set_tris_b(get_tris_b()&0xEF);
   output_high(DHT11);
   T_DHT11=(float)make16(Tint,Tdec)/256.0;
   RH_DHT11=(float)make16(RHint,RHdec)/256.0;
   if (chkCRC==CRC) return 0;
   return -6;
}

Eso es todo por hoy. Hasta la próxima.

3 comentarios

  1. Óscar

    Muchas gracias por el aporte!
    Mañana mismo lo pruebo!!

  2. Óscar

    Buenas!
    He probado el código pero cada vez me sale un valor distinto, pero de manera muy curiosa, empieza con un valor aparentemente real, y a partir de ahí empieza ese valor a doblarse:

    Hum 30, Hum 60, .. y así…

    1. David

      ¿Y la temperatura la lee bien? ¿O también hace cosas raras?

      La función devuelve como resultado 0 si el CRC es correcto, asegúrate de comprobarlo, y si da menor que cero comprueba el cableado, la resistencia de pull-up o (me ha pasado) si la fuente de alimentación que usas mete ruido en el circuito.

Deja un comentario

Conectar con:

Tu dirección de correo electrónico no será publicada.

Puedes utilizar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>