DHT22 "fails to respond" after running for a period of time.

Breakout boards, sensors, other Adafruit kits, etc.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
russgrue
 
Posts: 5
Joined: Fri Jun 06, 2014 1:57 am

DHT22 "fails to respond" after running for a period of time.

Post by russgrue »

Hey,

I've bought two DHT22 sensors from Adafruit. I've wired up a Spark Core(arduino-compat) to these sensors and written a sketch to probe the sensor and HTTP POST the data to a webserver. I've been working on this HTTP code for a while and use it successfully with other sensors.

When I apply power to the Spark Core with the first DHT22 connected it will probe the sensor successfully for approximately 2-3hours then the sensor will fail. With the second DHT22 sensor it will fail in 5 mins.

The sensor code I'm using should throw an error if the sensor dies but it keeps saying "OK" and outputting "-5" for the values.

If I cut power to the sensor by pulling the power pin then reconnect the sensors will work for the previously mentioned periods.

I'll get photos of the breadboard and samples of the code shortly, but I don't think these are the problem.

Russ

User avatar
adafruit_support_bill
 
Posts: 88092
Joined: Sat Feb 07, 2009 10:11 am

Re: DHT22 "fails to respond" after running for a period of t

Post by adafruit_support_bill »

Are you using the supplied 10K pullup resistor?
Post photos of how you have everything connected.

russgrue
 
Posts: 5
Joined: Fri Jun 06, 2014 1:57 am

Re: DHT22 "fails to respond" after running for a period of t

Post by russgrue »

Yes I'm using the pull up resistor. Photos and code attached.

Code: Select all

// This #include statement was automatically added by the Spark IDE.
#include "idDHT22/idDHT22.h"


// declaration for DHT11 handler
int idDHT22pin = D4; //Digital pin for comunications
void dht22_wrapper(); // must be declared before the lib initialization

// DHT instantiate
idDHT22 DHT22(idDHT22pin, dht22_wrapper);


void setup()
{
	Serial.begin(9600);
	while(!Serial.available()) {
	    Serial.println("hit a key");
	    delay(1000);
	}
	Serial.println("idDHT22 Example program");
	Serial.print("LIB version: ");
	Serial.println(idDHT22LIB_VERSION);
	Serial.println("---------------");
}
// This wrapper is in charge of calling
// mus be defined like this for the lib work
void dht22_wrapper() {
	DHT22.isrCallback();
}
void loop()
{

	Serial.print("\nRetrieving information from sensor: ");
	Serial.print("Read sensor: ");
	//delay(100);
	DHT22.acquire();
	while (DHT22.acquiring())
		;
	int result = DHT22.getStatus();
	switch (result)
	{
		case IDDHTLIB_OK:
			Serial.println("OK");
			break;
		case IDDHTLIB_ERROR_CHECKSUM:
			Serial.println("Error\n\r\tChecksum error");
			break;
		case IDDHTLIB_ERROR_ISR_TIMEOUT:
			Serial.println("Error\n\r\tISR Time out error");
			break;
		case IDDHTLIB_ERROR_RESPONSE_TIMEOUT:
			Serial.println("Error\n\r\tResponse time out error");
			break;
		case IDDHTLIB_ERROR_DATA_TIMEOUT:
			Serial.println("Error\n\r\tData time out error");
			break;
		case IDDHTLIB_ERROR_ACQUIRING:
			Serial.println("Error\n\r\tAcquiring");
			break;
		case IDDHTLIB_ERROR_DELTA:
			Serial.println("Error\n\r\tDelta time to small");
			break;
		case IDDHTLIB_ERROR_NOTSTARTED:
			Serial.println("Error\n\r\tNot started");
			break;
		default:
			Serial.println("Unknown error");
			break;
	}
	Serial.print("Humidity (%): ");
	Serial.println(DHT22.getHumidity(), 2);

	Serial.print("Temperature (oC): ");
	Serial.println(DHT22.getCelsius(), 2);

	Serial.print("Temperature (oF): ");
	Serial.println(DHT22.getFahrenheit(), 2);

	Serial.print("Temperature (K): ");
	Serial.println(DHT22.getKelvin(), 2);

	Serial.print("Dew Point (oC): ");
	Serial.println(DHT22.getDewPoint());

	Serial.print("Dew Point Slow (oC): ");
	Serial.println(DHT22.getDewPointSlow());

	delay(2000);
}

Code: Select all

/********************************************************************/
/*
FILE: idDHT22.cpp
VERSION: 0.0.1
PURPOSE: Interrupt driven Lib for DHT11 with Arduino.
LICENCE: GPL v3 (http://www.gnu.org/licenses/gpl.html)
DATASHEET: http://www.micro4you.com/files/sensor/DHT11.pdf
Based on DHT11 library: http://playground.arduino.cc/Main/DHT11Lib
*/
/*
	Modified by Paul Kourany for DHT22, Mar 28, 2014
	Originally ported to Spark.Core
	January 18, 2014
	Scott Piette

	Original version from niesteszek located @ https://github.com/niesteszeck/idDHT22
*/

#include "idDHT22.h"


// Fix to define word type conversion function
uint16_t word(uint8_t high, uint8_t low) {
    uint16_t ret_val = low;
    ret_val += (high << 8);
    return ret_val;
}


idDHT22::idDHT22(int sigPin, void (*callback_wrapper)()) {
	init(sigPin, callback_wrapper);
}

void idDHT22::init(int sigPin, void (*callback_wrapper) ()) {
	this->_sigPin = sigPin;
	this->isrCallback_wrapper = callback_wrapper;
	_hum = 0;
	_temp = 0;
	pinMode(sigPin, OUTPUT);
	digitalWrite(sigPin, HIGH);
	_state = STOPPED;
	_status = IDDHTLIB_ERROR_NOTSTARTED;
}

int idDHT22::acquire() {
	if (_state == STOPPED || _state == ACQUIRED) {
		// Setup the initial state machine
		_state = RESPONSE;

		//Empty buffer and variables
		for (int i=0; i< 6; i++)
			_bits[i] = 0;
		_cnt = 7;
		_idx = 0;
		_hum = 0;
		_temp = 0;

		/*
		 * Toggle the digital output to trigger the DHT device
		 * to send us temperature and humidity data
		 */
		pinMode(_sigPin, OUTPUT);
		digitalWrite(_sigPin, LOW);
		delay(18);						//Spec: min 1ms
		digitalWrite(_sigPin, HIGH);
		delayMicroseconds(40);			//Spec: 20-40us
		pinMode(_sigPin, INPUT);

		/*
		 * Attach the interrupt handler to receive the data once the DHT
		 * starts to send us its data
		 */
		_us = micros();
		attachInterrupt(_sigPin, isrCallback_wrapper, FALLING);

		return IDDHTLIB_ACQUIRING;
	} else
		return IDDHTLIB_ERROR_ACQUIRING;
}

int idDHT22::acquireAndWait() {
	acquire();
	while(acquiring())
		;
	return getStatus();
}

void idDHT22::isrCallback() {
	unsigned long newUs = micros();
	unsigned long delta = (newUs -_us);
	_us = newUs;
	if (delta>6000) {
		_status = IDDHTLIB_ERROR_ISR_TIMEOUT;
		_state = STOPPED;
		detachInterrupt(_sigPin);
		return;
	}
	switch(_state) {
		case RESPONSE:
			if(delta < 25){
				_us -= delta;
				break; //do nothing, it started the response signal
			} if(125 < delta && delta < 190) {
				_state = DATA;
			} else {
				detachInterrupt(_sigPin);
				_status = IDDHTLIB_ERROR_RESPONSE_TIMEOUT;
				_state = STOPPED;
			}
			break;
		case DATA:
			if(delta<10) {
				detachInterrupt(_sigPin);
				_status = IDDHTLIB_ERROR_DELTA;
				_state = STOPPED;
			} else if(60 < delta && delta < 145) { //valid in timing
				if(delta > 100) //is a one
					_bits[_idx] |= (1 << _cnt);
				if (_cnt == 0) { // we have fullfilled the byte, go to next
						_cnt = 7; // restart at MSB
						if(_idx++ == 4) { // go to next byte, if we have got 5 bytes stop.
							detachInterrupt(_sigPin);
							// WRITE TO RIGHT VARS
							_hum = word(_bits[0], _bits[1]) * 0.1;
							_temp = (_bits[2] & 0x80 ? 
								-word(_bits[2] & 0x7F, _bits[3]) :
								word(_bits[2], _bits[3]))
								* 0.1;
								uint8_t sum = _bits[0] + _bits[1] + _bits[2] + _bits[3];
							if (_bits[4] != sum) {
								_status = IDDHTLIB_ERROR_CHECKSUM;
								_state = STOPPED;
							} else {
								_status = IDDHTLIB_OK;
								_state = ACQUIRED;
							}
							break;
						}
				}
				else _cnt--;
			}
			else {
				detachInterrupt(_sigPin);
				_status = IDDHTLIB_ERROR_DATA_TIMEOUT;
				_state = STOPPED;
			}
			break;
		default:
			break;
	}
}

bool idDHT22::acquiring() {
	if (_state != ACQUIRED && _state != STOPPED)
		return true;
	return false;
}

int idDHT22::getStatus() {
	return _status;
}

float idDHT22::getCelsius() {
	idDHT22_CHECK_STATE;
	return _temp;
}

float idDHT22::getHumidity() {
	idDHT22_CHECK_STATE;
	return _hum;
}

float idDHT22::getFahrenheit() {
	idDHT22_CHECK_STATE;
	return _temp * 1.8 + 32;
}

float idDHT22::getKelvin() {
	idDHT22_CHECK_STATE;
	return _temp + 273.15;
}

// delta max = 0.6544 wrt dewPoint()
// 5x faster than dewPoint()
// reference: http://en.wikipedia.org/wiki/Dew_point
double idDHT22::getDewPoint() {
	idDHT22_CHECK_STATE;
	double a = 17.271;
	double b = 237.7;
	double temp_ = (a * (double) _temp) / (b + (double) _temp) + log( (double) _hum/100);
	double Td = (b * temp_) / (a - temp_);
	return Td;
}

// dewPoint function NOAA
// reference: http://wahiduddin.net/calc/density_algorithms.htm
double idDHT22::getDewPointSlow() {
	idDHT22_CHECK_STATE;
	double a0 = (double) 373.15 / (273.15 + (double) _temp);
	double SUM = (double) -7.90298 * (a0-1.0);
	SUM += 5.02808 * log10(a0);
	SUM += -1.3816e-7 * (pow(10, (11.344*(1-1/a0)))-1) ;
	SUM += 8.1328e-3 * (pow(10,(-3.49149*(a0-1)))-1) ;
	SUM += log10(1013.246);
	double VP = pow(10, SUM-3) * (double) _hum;
	double T = log(VP/0.61078); // temp var
	return (241.88 * T) / (17.558-T);
}

Code: Select all

/*
	FILE:		 idDHT22.h
	VERSION:	 0.0.1
	PURPOSE:	 Interrupt driven Lib for DHT11 with Arduino.
	LICENCE:	GPL v3 (http://www.gnu.org/licenses/gpl.html)
	DATASHEET: http://www.micro4you.com/files/sensor/DHT11.pdf
	
	Based on DHT11 library: http://playground.arduino.cc/Main/DHT11Lib
*/

/*
	Modified by Paul Kourany for DHT22, Mar 28, 2014
	Originally ported to Spark.Core
	January 18, 2014
	Scott Piette

	Original version from niesteszek located @ https://github.com/niesteszeck/idDHT22
*/
#include "application.h"
#include "math.h"

/************************************ _iDHT.h **************************/
/*
FILE: idDHT22.h
VERSION: 0.1
PURPOSE: Interrupt driven Lib for DHT11 with Arduino.
LICENCE: GPL v3 (http://www.gnu.org/licenses/gpl.html)
DATASHEET: http://www.micro4you.com/files/sensor/DHT11.pdf
Based on DHT11 library: http://playground.arduino.cc/Main/DHT11Lib
*/


#define idDHT22LIB_VERSION "0.1"

// state codes
#define IDDHTLIB_OK						0
#define IDDHTLIB_ACQUIRING				1
#define IDDHTLIB_ACQUIRED				2
#define IDDHTLIB_RESPONSE_OK			3

// error codes
#define IDDHTLIB_ERROR_CHECKSUM				-1
#define IDDHTLIB_ERROR_ISR_TIMEOUT			-2
#define IDDHTLIB_ERROR_RESPONSE_TIMEOUT		-3
#define IDDHTLIB_ERROR_DATA_TIMEOUT			-4
#define IDDHTLIB_ERROR_ACQUIRING			-5
#define IDDHTLIB_ERROR_DELTA				-6
#define IDDHTLIB_ERROR_NOTSTARTED			-7

#define idDHT22_CHECK_STATE		if(_state == STOPPED)					\
									return _status;						\
								else if(_state != ACQUIRED)				\
									return IDDHTLIB_ERROR_ACQUIRING;

class idDHT22
{
public:
	idDHT22(int sigPin, void (*isrCallback_wrapper)());
    void init(int sigPin, void (*isrCallback_wrapper)());
	void isrCallback();
	int acquire();
	int acquireAndWait();
	float getCelsius();
	float getFahrenheit();
	float getKelvin();
	double getDewPoint();
	double getDewPointSlow();
	float getHumidity();
	bool acquiring();
	int getStatus();

private:
	void (*isrCallback_wrapper)(void);

	enum states{RESPONSE=0,DATA=1,ACQUIRED=2,STOPPED=3,ACQUIRING=4};
	volatile states _state;
	volatile int _status;
	volatile uint8_t _bits[6];
	volatile uint8_t _cnt;
	volatile uint8_t _idx;
	volatile unsigned long _us;
	int _sigPin;
	int _type;
	unsigned long _lastreadtime;
	volatile float _hum;
	volatile float _temp;
};

Attachments
10558545_10152281348501242_862359843_o.jpg
10558545_10152281348501242_862359843_o.jpg (173.64 KiB) Viewed 800 times
10567827_10152281350546242_389673898_o.jpg
10567827_10152281350546242_389673898_o.jpg (153.57 KiB) Viewed 800 times

User avatar
adafruit_support_bill
 
Posts: 88092
Joined: Sat Feb 07, 2009 10:11 am

Re: DHT22 "fails to respond" after running for a period of t

Post by adafruit_support_bill »

Given that you are seeing problems with 2 out of 2 sensors, I'd suspect something in either your code or setup.

Breadboards are always suspect. Intermittent connections are fairly common - especially on a well-used board. You can try moving your circuit to a different set of holes and see if the reliability improves.

I'm not familiar with the library you are using there. I don't see any obvious problems in the code. But interrupts do add some runtime complexity. One thing you might try is reducing your SRAM footprint to reduce the risk of a stack crash. You have quite a few literal strings that could be moved to Flash with the F() macro: https://learn.adafruit.com/memories-of- ... izing-sram

russgrue
 
Posts: 5
Joined: Fri Jun 06, 2014 1:57 am

Re: DHT22 "fails to respond" after running for a period of t

Post by russgrue »

Sussed it... It was the library I was using.

I have experienced problems with the breadboard before but if the temperature isn't changing radically and things aren't shrinking and expanding a breadboard is fairly static once a solid connection is made it's hard to imagine it disconnecting spontaneously.

Using a the Adafruit DHT Library slightly modified for the Spark Core I've achieved several days of stability now.

User avatar
adafruit_support_bill
 
Posts: 88092
Joined: Sat Feb 07, 2009 10:11 am

Re: DHT22 "fails to respond" after running for a period of t

Post by adafruit_support_bill »

Great! Thanks for the follow-up.

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

Return to “Other Products from Adafruit”