Main > Diary > Development

« XBee Pulse I/O | Main

February 20, 2012

Arduino DHT22 Library Improvement

Rob Faludi and I have been teaching a class at the International Center for Theoretical Physics in Trieste, Italy. Marco Zennaro furnished us with a number of DHT22-based Grove Temperature and Humidity Sensors for Seeed Studio. The example code on the Seeed wasn't very robust nor parameterized to work on any Arduino pin so I took a few moments to make some changes. There are now two files:

DHT22.h:

#ifndef DHT22_H
#define DHT22_H

enum DHT22_Err_t {
  DHT22_ERR_NONE = 0,
  DHT22_ERR_HUNG = 1,
  DHT22_ERR_SYNC = 2,
  DHT22_ERR_CHKSUM = 3,
};

DHT22_Err_t getDHT22(int pin, float *temperature, float *humidity);

#endif

DHT22.ino:

#include "DHT22.h"

static byte _read_dht22_dat(volatile uint8_t *in, uint8_t bitmask)
{
  byte i = 0;
  byte result=0;
  for(i=0; i< 8; i++){
    while(!(*in & bitmask));  // wait for 50us
    delayMicroseconds(30);
 
    if(*in & bitmask) 
      result |=(1<<(7-i));
    while((*in & bitmask));  // wait '1' finish
  }
  return result;
}

DHT22_Err_t getDHT22(int pin, float *temperature, float *humidity)
{
  byte dht22_dat[5];
  byte dht22_in;
  byte i;

  uint8_t bitmask = digitalPinToBitMask(pin);
  volatile uint8_t port = digitalPinToPort(pin);
  volatile uint8_t *reg, *out, *in;

  // setup registers and pins
  reg = portModeRegister(port);
  out = portOutputRegister(port);
  in =  portInputRegister(port);
  *reg |= bitmask;
  *out |= bitmask;

  // start condition
  // 1. pull-down i/o pin from 18ms
  *out &= ~bitmask;
  delay(18);
  *out |= bitmask;
  delayMicroseconds(40);
 
  *reg &= ~bitmask;
  delayMicroseconds(40);
 
  dht22_in = *in & bitmask;
 
  if(dht22_in){
    Serial.println("dht22 start condition 1 not met");
    return DHT22_ERR_HUNG;
  }
  delayMicroseconds(80);
 
  dht22_in = *in & bitmask;
 
  if(!dht22_in){
    return DHT22_ERR_SYNC;
  }
  delayMicroseconds(80);
  // now ready for data reception
  for (i=0; i<5; i++)
    dht22_dat[i] = _read_dht22_dat(in, bitmask);
 
  *reg |= bitmask;
  *out |= bitmask;
 
  byte dht22_check_sum = dht22_dat[0]+dht22_dat[1]+dht22_dat[2]+dht22_dat[3];
  // check check_sum
  if(dht22_dat[4]!= dht22_check_sum)
  {
    return DHT22_ERR_CHKSUM;
  }
  
  *humidity=((float)(dht22_dat[0]*256+dht22_dat[1]))/10;
  *temperature=((float)(dht22_dat[2]*256+dht22_dat[3]))/10;
 
  return DHT22_ERR_NONE; 
}

This can be used as in in the following example:

#include "DHT22.h"

void setup() {
  Serial.begin(9600);
  delay(2000); // Recommended delay before sensor can be used
}

void loop() {
  DHT22_Err_t result;
  float temperature = 0, humidity = 0;
  
  result = getDHT22(4, &temperature, &humidity);  
  if (result != DHT22_ERR_NONE)
  {
    delay(5000);
    return;
  }
  
  Serial.print("Current humdity = ");
  Serial.print(humidity,1);
  Serial.print("%  ");
  Serial.print("temperature = ");
  Serial.print(temperature,1);
  Serial.println("C  ");
  delay(5000);
}

You may download the file ICTP_DHT22_XIG.zip. It contains a slightly enhanced example which transmits the information to the XBee Internet Gateway.

Posted by jordanh at February 20, 2012 6:46 AM |

Trackback Pings

TrackBack URL for this entry:
http://jordan.husney.com/mt/mt-tb.cgi/415.

Comments

Post a comment




Remember Me?