DHT-22 Code question/help

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
bcook65
 
Posts: 109
Joined: Sat Apr 03, 2010 1:25 pm

DHT-22 Code question/help

Post by bcook65 »

Some time back I had purchased a couple DHT-22 sensors to play with..
After a few months of issues with arduino com issues I finally got the code to load to my Arduino uno.. yay.
Then as simple as the DHT sensor setup was I was having issues with data printing to the serial monitor and the or the 7 segment display.. Finally resolved that once I actually located the correct code.

Seems to work fine now, only I would like to change how fast it pints to the 7 segment display.. I am not sure of the current duration but it displays temp thru humidity at maybe 1 sec intervals and holds slightly longer on dewpoint reading.

I am not super good with coding and would like some help with
1. changing the display delay and making it a little slower for all readings. What part of the code do I need to change?
2. Possibly just removing the Centigrade/Celsius display altogether, what section of code do I change for this?

Here is the code I am using:
Last edited by bcook65 on Sun Oct 07, 2012 6:37 pm, edited 1 time in total.

User avatar
bcook65
 
Posts: 109
Joined: Sat Apr 03, 2010 1:25 pm

Re: DHT-22 Code question/help

Post by bcook65 »

Oops.. My bad.. here is the code

Code: Select all

/* Temperature-Humidity-Dewpoint Monitor
This sketch gathers temperature and humidity data via a DHT22 sensor,
and also calculates dew point based on those measurements.
*/

#include <SoftwareSerial.h>
#include <stdlib.h>

#define DHT22_ERROR_VALUE -99.5

#define DHT22_PIN 4

typedef enum
{
  DHT_ERROR_NONE = 0,
  DHT_BUS_HUNG,
  DHT_ERROR_NOT_PRESENT,
  DHT_ERROR_ACK_TOO_LONG,
  DHT_ERROR_SYNC_TIMEOUT,
  DHT_ERROR_DATA_TIMEOUT,
  DHT_ERROR_CHECKSUM,
  DHT_ERROR_TOOQUICK
} DHT22_ERROR_t;

class DHT22
{
  private:
    uint8_t _bitmask;
    volatile uint8_t *_baseReg;
    unsigned long _lastReadTime;
    float _lastHumidity;
    float _lastTemperature;

  public:
    DHT22(uint8_t pin);
    DHT22_ERROR_t readData(void);
    float getHumidity();
    float getTemperatureC();
    void clockReset();
};


// Setup a DHT22 instance
DHT22 myDHT22(DHT22_PIN);


#define SerialIn 2
#define SerialOut 3


#define WDelay 900


byte thou=0;
byte hund=0;
byte tens=0;
byte ones=0;


SoftwareSerial mySerialPort(SerialIn, SerialOut);


void setup(void)
{


// start serial port
Serial.begin(9600);
Serial.println("DHT22 Library Demo");


pinMode(SerialOut, OUTPUT);
pinMode(SerialIn, INPUT);


mySerialPort.begin(9600);
mySerialPort.print("v");

mySerialPort.print("xxxx");
delay(WDelay);
mySerialPort.print("----");
delay(WDelay);
mySerialPort.print("8888");
delay(WDelay);
mySerialPort.print("xxxx");
delay(WDelay);
}

void loop(void)
{
float tempC;
float tempF;
float humid;
float dewPoint;

DHT22_ERROR_t errorCode;

delay(2000);

errorCode = myDHT22.readData();

Serial.print(errorCode);

switch(errorCode)
{
        case DHT_ERROR_NONE:
        Serial.print("Temperature: ");
        tempC = myDHT22.getTemperatureC();
                 
        Serial.print(tempC);
        Serial.print("C Humidity: ");
        
        dispData((int)tempC, 'C');
        
        tempF = (tempC*1.8)+32;
                   
        delay(WDelay);
        dispData((int) tempF, 'F');
        delay(WDelay);
        
        humid = myDHT22.getHumidity();
        
        Serial.print(humid);
        Serial.println("%");
        
        dispData((int)humid, 'h');
        delay(WDelay);
        
        dewPoint = calculateDewpoint(tempC, humid);
        dispData((int) dewPoint, 'd');
 
        Serial.print(dewPoint);
        Serial.println("d");
        
        delay(WDelay);
       
        break;
        case DHT_ERROR_CHECKSUM:
        Serial.print("Error Cheksum");
        break;
        case DHT_BUS_HUNG:
        Serial.print("Bus Hung");
        break;
        case DHT_ERROR_NOT_PRESENT:
        Serial.print("Not Present");
        break;
        case DHT_ERROR_ACK_TOO_LONG:
        Serial.print("ACK too long");
        break;
        case DHT_ERROR_SYNC_TIMEOUT:
        Serial.print("Sync timeout");
        break;
        case DHT_ERROR_DATA_TIMEOUT:
        Serial.print("Data timeout");
        break;
        case DHT_ERROR_TOOQUICK:
        Serial.print("Too quick!");
        break;
}

}


float calculateDewpoint(float T, float RH)
{
// approximate dewpoint using the formula from wikipedia's article on dewpoint

float dp = 0.0;
float gTRH = 0.0;
float a = 17.271;
float b = 237.7;

gTRH = ((a*T)/(b+T))+log(RH/100);
dp = (b*gTRH)/(a-gTRH);

return dp;
}

void dispData(int i, char c)
{

 if(c == 'k' || c=='K' || c=='m' || c=='l' || c == 'v' || c=='V' || c=='W' || c=='Z' || c=='w' || c=='z')
 {
        mySerialPort.print("bAdx");
        return;
        
 }
  
 if((i<-999) || (i>9999))
 {
   mySerialPort.print("ERRx");
   return;
 }

 mySerialPort.print("v");

 if (i > 999) { // i between 1000 and 9999 inclusive

   mySerialPort.print(i, DEC);

 } else if (i > 99) { // i between 100 and 999, inclusive

   mySerialPort.print(i, DEC);
   mySerialPort.print(c);

 } else if (i > 9) { // i between 10 and 99 inclusive

   mySerialPort.print(i, DEC);
   mySerialPort.print("x");
   mySerialPort.print(c);

 } else if (i > 0) { // i between 1 and 9 inclusive

   mySerialPort.print("x");
   mySerialPort.print(i, DEC);
   mySerialPort.print("x");
      mySerialPort.print(c);

 } else if (i < -99) { // i between -100 and -999, inclusive

   mySerialPort.print(i, DEC);
   mySerialPort.print(c);

 } else if (i < -9) { // i between -10 and -99, inclusive

   mySerialPort.print(i, DEC);
   mySerialPort.print(c);

 } else if (i < 0) { // i between -1 and -9 inclusive

   mySerialPort.print(i, DEC);
   mySerialPort.print("x");
   mySerialPort.print(c);

 }

}

/*
  DHT22.cpp - DHT22 sensor library
  Developed by Ben Adams - 2011

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


Humidity and Temperature Sensor DHT22 info found at
http://www.sparkfun.com/products/10167

Version 0.4: 24-Jan-2011 by Ben Adams
Added return code constants to keywords.txt
Returns DHT_ERROR_CHECKSUM on check sum mismatch 

Version 0.3: 17-Jan-2011 by Ben Adams
This version reads data
Needs check sum code added at the end of readData

Version 0.2: 16-Jan-2011 by Ben Adams
Changed coding style to match other Arduino libraries.
This version will not read data either!

Version 0.1: 10-Jan-2011 by Ben Adams nethoncho AT gmail.com
First Version is a skeleton. This version will not read data!
Code adapted from the following sources:
The Arduino OneWire lib
http://sheepdogguides.com/arduino/ar3ne1humDHT11.htm

*/

#include "Arduino.h"

extern "C" {
//#include "WConstants.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
}

#define DIRECT_READ(base, mask) 	(((*(base)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask)	((*(base+1)) &= ~(mask))
#define DIRECT_MODE_OUTPUT(base, mask)	((*(base+1)) |= (mask))
#define DIRECT_WRITE_LOW(base, mask)	((*(base+2)) &= ~(mask))
//#define DIRECT_WRITE_HIGH(base, mask)	((*(base+2)) |= (mask))

// This should be 40, but the sensor is adding an extra bit at the start
#define DHT22_DATA_BIT_COUNT 41

DHT22::DHT22(uint8_t pin)
{
    _bitmask =  digitalPinToBitMask(pin);
    _baseReg = portInputRegister(digitalPinToPort(pin));
    _lastReadTime = millis();
    _lastHumidity = DHT22_ERROR_VALUE;
    _lastTemperature = DHT22_ERROR_VALUE;
}

//
// Read the 40 bit data stream from the DHT 22
// Store the results in private member data to be read by public member functions
//
DHT22_ERROR_t DHT22::readData()
{
  uint8_t bitmask = _bitmask;
  volatile uint8_t *reg asm("r30") = _baseReg;
  uint8_t retryCount;
  uint8_t bitTimes[DHT22_DATA_BIT_COUNT];
  int currentHumidity;
  int currentTemperature;
  uint8_t checkSum, csPart1, csPart2, csPart3, csPart4;
  unsigned long currentTime;
  int i;

  currentHumidity = 0;
  currentTemperature = 0;
  checkSum = 0;
  currentTime = millis();
  for(i = 0; i < DHT22_DATA_BIT_COUNT; i++)
  {
    bitTimes[i] = 0;
  }

  if(currentTime - _lastReadTime < 2000)
  {
    // Caller needs to wait 2 seconds between each call to readData
    return DHT_ERROR_TOOQUICK;
  }
  _lastReadTime = currentTime;

  // Pin needs to start HIGH, wait until it is HIGH with a timeout
  cli();
  DIRECT_MODE_INPUT(reg, bitmask);
  sei();
  retryCount = 0;
  do
  {
    if (retryCount > 125)
    {
      return DHT_BUS_HUNG;
    }
    retryCount++;
    delayMicroseconds(2);
  } while(!DIRECT_READ(reg, bitmask));
  // Send the activate pulse
  cli();
  DIRECT_WRITE_LOW(reg, bitmask);
  DIRECT_MODE_OUTPUT(reg, bitmask); // Output Low
  sei();
  delayMicroseconds(1100); // 1.1 ms
  cli();
  DIRECT_MODE_INPUT(reg, bitmask);	// Switch back to input so pin can float
  sei();
  // Find the start of the ACK Pulse
  retryCount = 0;
  do
  {
    if (retryCount > 25) //(Spec is 20 to 40 us, 25*2 == 50 us)
    {
      return DHT_ERROR_NOT_PRESENT;
    }
    retryCount++;
    delayMicroseconds(2);
  } while(!DIRECT_READ(reg, bitmask));
  // Find the end of the ACK Pulse
  retryCount = 0;
  do
  {
    if (retryCount > 50) //(Spec is 80 us, 50*2 == 100 us)
    {
      return DHT_ERROR_ACK_TOO_LONG;
    }
    retryCount++;
    delayMicroseconds(2);
  } while(DIRECT_READ(reg, bitmask));
  // Read the 40 bit data stream
  for(i = 0; i < DHT22_DATA_BIT_COUNT; i++)
  {
    // Find the start of the sync pulse
    retryCount = 0;
    do
    {
      if (retryCount > 35) //(Spec is 50 us, 35*2 == 70 us)
      {
        return DHT_ERROR_SYNC_TIMEOUT;
      }
      retryCount++;
      delayMicroseconds(2);
    } while(!DIRECT_READ(reg, bitmask));
    // Measure the width of the data pulse
    retryCount = 0;
    do
    {
      if (retryCount > 50) //(Spec is 80 us, 50*2 == 100 us)
      {
        return DHT_ERROR_DATA_TIMEOUT;
      }
      retryCount++;
      delayMicroseconds(2);
    } while(DIRECT_READ(reg, bitmask));
    bitTimes[i] = retryCount;
  }
  // Now bitTimes have the number of retries (us *2)
  // that were needed to find the end of each data bit
  // Spec: 0 is 26 to 28 us
  // Spec: 1 is 70 us
  // bitTimes[x] <= 11 is a 0
  // bitTimes[x] >  11 is a 1
  // Note: the bits are offset by one from the data sheet, not sure why
  for(i = 0; i < 16; i++)
  {
    if(bitTimes[i + 1] > 11)
    {
      currentHumidity |= (1 << (15 - i));
    }
  }
  for(i = 0; i < 16; i++)
  {
    if(bitTimes[i + 17] > 11)
    {
      currentTemperature |= (1 << (15 - i));
    }
  }
  for(i = 0; i < 8; i++)
  {
    if(bitTimes[i + 33] > 11)
    {
      checkSum |= (1 << (7 - i));
    }
  }

  _lastHumidity = (float(currentHumidity & 0x7FFF) / 10.0);
  if(currentTemperature & 0x8000)
  {
   // Below zero, non standard way of encoding negative numbers!
    currentTemperature &= 0x7FFF;
    _lastTemperature = (float(currentTemperature) / 10.0) * -1.0;
  }
  else
  {
    _lastTemperature = float(currentTemperature) / 10.0;
  }

  csPart1 = currentHumidity >> 8;
  csPart2 = currentHumidity & 0xFF;
  csPart3 = currentTemperature >> 8;
  csPart4 = currentTemperature & 0xFF;
  if(checkSum == ((csPart1 + csPart2 + csPart3 + csPart4) & 0xFF))
  {
    return DHT_ERROR_NONE;
  }
  return DHT_ERROR_CHECKSUM;
}

float DHT22::getHumidity()
{
  return _lastHumidity;
}

float DHT22::getTemperatureC()
{
  return _lastTemperature;
}

//
// This is used when the millis clock rolls over to zero
//
void DHT22::clockReset()
{
  _lastReadTime = millis();

}

User avatar
bcook65
 
Posts: 109
Joined: Sat Apr 03, 2010 1:25 pm

Re: DHT-22 Code question/help

Post by bcook65 »


User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: DHT-22 Code question/help

Post by adafruit_support_rick »

bcook65 wrote:1. changing the display delay and making it a little slower for all readings. What part of the code do I need to change?
You want more time between each thing that shows up on the display? Change the value of wDelay to some bigger number. For example:

Code: Select all

#define WDelay 2000
WDelay is the delay between display changes in milliseconds. So, 2000 is 2 seconds. 900 is 0.9 seconds.
bcook65 wrote:2. Possibly just removing the Centigrade/Celsius display altogether, what section of code do I change for this?
Put "//" at the beginning of these lines, as follows:

Code: Select all

                 
//        Serial.print(tempC);
//        Serial.print("C Humidity: ");
//        
//        dispData((int)tempC, 'C');

User avatar
bcook65
 
Posts: 109
Joined: Sat Apr 03, 2010 1:25 pm

Re: DHT-22 Code question/help

Post by bcook65 »

driverblock wrote:
bcook65 wrote:1. changing the display delay and making it a little slower for all readings. What part of the code do I need to change?
You want more time between each thing that shows up on the display? Change the value of wDelay to some bigger number. For example:

Code: Select all

#define WDelay 2000
WDelay is the delay between display changes in milliseconds. So, 2000 is 2 seconds. 900 is 0.9 seconds.
bcook65 wrote:2. Possibly just removing the Centigrade/Celsius display altogether, what section of code do I change for this?
Put "//" at the beginning of these lines, as follows:

Code: Select all

                 
//        Serial.print(tempC);
//        Serial.print("C Humidity: ");
//        
//        dispData((int)tempC, 'C');

thank you much.. will plug it in and see what happens.. I saw delay and wdelay and was not sure what the dif was.. thanks

User avatar
bcook65
 
Posts: 109
Joined: Sat Apr 03, 2010 1:25 pm

Re: DHT-22 Code question/help

Post by bcook65 »

Ok.. that worked great.. 2 last questions

I set the WDelay to 3 seconds.. which is fine.. But there is like maybe a 10 second delay after the dew point reading before it recycles back to the beginning.. Will that be a different delay setting?

2. I would maybe assume I need an external editor for this but is it possible for the arduino software to put line numbers? Sure seems it would make it a lot quicker to navigate and find things..

Again thanks for the help

Bill

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: DHT-22 Code question/help

Post by adafruit_support_rick »

bcook65 wrote:I set the WDelay to 3 seconds.. which is fine.. But there is like maybe a 10 second delay after the dew point reading before it recycles back to the beginning.. Will that be a different delay setting?
Yes. There is a delay(2000) a few lines down from void loop(void). After the dew point reading, you do a delay(WDelay) before looping around to the top. Then at the top, you do that delay(2000). So that gives you a total delay of 5 seconds (assuming WDelay is set to 3000). Change the delay(2000) to something shorter.
bcook65 wrote:2. I would maybe assume I need an external editor for this but is it possible for the arduino software to put line numbers? Sure seems it would make it a lot quicker to navigate and find things..
I don't think the arduino editor supports line numbers.

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”