DHT11 Temp and Humidity Sensor - CRC error

I have connected a DHT11 sensor to a nano atmega 328.

Note that I also use an interrupt driven routine to maintain a real-time-clock. Measuring the DHT11 pulses that are just a few microseconds, I had a lot of trouble with time-outs and correct data, as the RTC clock routine interfered with the microsecond time measurement.

I fixed this by syncing the DHT11 code to a point in time where the interrupt routine really does not do anything (things happen at second roll-over in the RTC routine).

Now that I have fixed this, I still get checksum errors, which appear temperature dependent. I added debug code, and for instance found that when temp=10C, the sensor often sends 00000001 for temp byte, completely leaving bit 3 at zero (temp byte should be 00001001). The checksum is actually correct for what the temperature byte should have been.

Has anybody seen this? Seems the sensor is (somewhat) broken - a data dependent malfunction?
I only have one DHT11, so I cannot easily try another…

int dht11::read(int pin)
{
	// BUFFER TO RECEIVE
	uint8_t bits[5]; // 5 * 8 = 40 bits total
	uint8_t cnt = 7;
	uint8_t idx = 0;
        int kk;
	// EMPTY receive BUFFER
	for (int kk=0; kk< 5; kk++) bits[kk] = 0;
	// REQUEST reading from sensor
        my_sync=false; //reset sync flag
        while (my_sync==false) delayMicroseconds(3); //synchronize with real time clock interrrupt routine
	pinMode(pin, OUTPUT);   // the sensor data pin is BIDI!!
        delayMicroseconds(100);  // do not immediately write after pin changed to output... caused check errors when at 10C!
	digitalWrite(pin, LOW);
	delayMicroseconds(10000);  // cannot exceed 16000.... so split in two calls
        delayMicroseconds(8000); 
	digitalWrite(pin, HIGH);
	delayMicroseconds(15);
	pinMode(pin, INPUT); // change to receive data, wait for sensor data now

	// ACKNOWLEDGE or TIMEOUT
	unsigned int loopCnt = 10000;
	while(digitalRead(pin) == LOW)
		if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;

	loopCnt = 10000;
	while(digitalRead(pin) == HIGH)
		if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;

	// READ OUTPUT, 40 BITS => 5 BYTES or TIMEOUT
        // each bit starts with 50uS low, a 0 is sent with 27uS high, a 1 is sent with 70uS high:
        //
        //       \______/------------\ one bit of 40
        //         50uS    27 or 70uS
        //
	for (int kk=0; kk<40; kk++) //receive 40 bits total
	{
		loopCnt = 10000;
		while(digitalRead(pin) == LOW) // is has to go low for this protocol
			if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;

		loopCnt = 10000;
		while(digitalRead(pin) == HIGH) {
			if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;
                }
		if ((10000-loopCnt)>10) bits[idx] |= (1 << cnt);  // either 2..5 iterations (bit=0), or 13..16 iterations (bit=1)

		if (cnt == 0)   // next byte?
		{
			cnt = 7;    // restart at MSB
			idx++;      // next byte!
		}
		else cnt--;
	}

	// WRITE TO RIGHT VARS
        // as bits[1] and bits[3] are allways zero they are omitted in formulas.
	uint8_t sum = bits[0] + bits[2];

if (deb_flag & (bits[4] != sum)){
  Serial.print(FcurTime(str));Serial.print(" CHK: ");
  for ( kk=0; kk<5; kk++){
  itoa(bits[kk],str,2);
  Serial.print(str);Serial.print(" ");
}
Serial.println(".");
}

	if (bits[4] != sum) return DHTLIB_ERROR_CHECKSUM;
	humidity    = bits[0]; //byte 0
	temperature = bits[2]; //byte 2

	return DHTLIB_OK;
}

Moderator: split off your topic

which version of which DHT lib are you patching?

How did you connect the DHT to the Nano? What resistor did you use, how connected?

  • don’t remember which library version I patched - I worked on that a year ago and made some forum posts about timing and microsecond calls.

  • connection: GND to GND, VCC to 5V output of nano, with Capacitor, data pin to A4 (all digital only pins are used to connect a display). See picture.

try this version - Arduino/libraries/DHTstable at master · RobTillaart/Arduino · GitHub
has been confirmed to work on several boards.

Has it been confirmed on a Nano? A year ago (see my posts then) I concluded that micros() on nano yields useless results....

Seems that the 10k ("103" on the SMD) resistor between data and Vcc is already on your DHT breakout. So it seems ok for me.

In case you fear the Nano is a problem. Can you tap the DHT with an Uno or other "proofed" MC and test if this is working? So you can exclude that the DHT itself is working?

In the mean time I concluded that the sensor itself is not fully OK. I added the following code just before returning the error code:

	if (bits[4] != sum) { //test whether checksum is good
           if (humidity+2>=bits[0] & humidity-2<=bits[0] & bits[1]==0 & bits[3]==0) { // this is a hack to deal with faulty sensor
             	humidity    = bits[0]; //byte 0
	        temperature = bits[4]-bits[0]; //calculate what temp should have been
                dd_cnt++; //count this kind of guessing
                if (deb_flag) {
                  Serial.print(FcurTime(str));
                  Serial.print(F(" CHK: Temp deduced to "));itoa(temperature,str,10);Serial.print(str);
                  Serial.print(F(" diff= "));itoa(temperature-bits[2],str,10);Serial.println(str);
                }
                return DHTLIB_OK;
           }
           else return DHTLIB_ERROR_CHECKSUM;

and guess what. I get no more CRC errors. For some reason, when humidity is a certain value, the temperature is either 8 or 4 degrees too low on certain readouts. Seems like bits are stuck internally in the DHT11. I checked power supply which is fine.

I have no other arduino nor sensor to play with at the moment.

In hindsight, there were two issues at the same time: timing issues with the code and a partially working sensor which made it interesting to debug.

I will order a new sensor…

Good to hear it is solved!