dht22 shows check sum error

Thread Starter

mah

Joined Mar 15, 2010
393
this code works well for dht22 but it shows checksum error in the range from 49-51%.
C:
/*****************************************************
Chip type               : ATmega8
Program type            : Application
AVR Core Clock frequency: 8,000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
*****************************************************/

#include <mega8.h>
#include <stdint.h>
#include <stdio.h>
#include <delay.h>
#include <stdlib.h>

#define DHT22       //define DHT22 or DHT11
#define DHT_PORT        PORTD
#define DHT_DDR         DDRD
#define DHT_PIN         PIND
#define DHT11_PIN 1



// Alphanumeric LCD Module functions
#include <alcd.h>
uint8_t c=0,I_RH,D_RH,I_Temp,D_Temp,CheckSum;
int q;
     float RH;
   unsigned char data [5];

void Request()                /* Microcontroller send start pulse/request */
{
    DDRD |= (1<<DHT11_PIN);
    PORTD &= ~(1<<DHT11_PIN);    /* set to low pin */
    delay_ms(20);            /* wait for 20ms */
    PORTD |= (1<<DHT11_PIN);    /* set to high pin */
}

void Response()                /* receive response from DHT11 */
{
    DDRD &= ~(1<<DHT11_PIN);
    while(PIND & (1<<DHT11_PIN));
    while((PIND & (1<<DHT11_PIN))==0);
    while(PIND & (1<<DHT11_PIN));
}

uint8_t Receive_data()            /* receive data */
{  
    for (q=0; q<8; q++)
    {
        while((PIND & (1<<DHT11_PIN)) == 0);  /* check received bit 0 or 1 */
        delay_us(30);
        if(PIND & (1<<DHT11_PIN))/* if high pulse is greater than 30ms */
        c = (c<<1)|(0x01);    /* then its logic HIGH */
        else            /* otherwise its logic LOW */
        c = (c<<1);
        while(PIND & (1<<DHT11_PIN));
    }
    return c;
}


void main(void)
{
PORTB=0x00;
DDRB=0xFF;

PORTC=0x00;
DDRC=0x00;

PORTD=0x00;
DDRD=0xFF;

lcd_init(16);

while (1)
      {
       Request();        /* send start pulse */
        Response();        /* receive response */
        I_RH=Receive_data();    /* store first eight bit in I_RH */
        D_RH=Receive_data();    /* store next eight bit in D_RH */
        I_Temp=Receive_data();    /* store next eight bit in I_Temp */
        D_Temp=Receive_data();    /* store next eight bit in D_Temp */
        CheckSum=Receive_data();/* store next eight bit in CheckSum */
      
        if ((I_RH + D_RH + I_Temp + D_Temp) != CheckSum)
        {
            lcd_gotoxy(0,1);
            lcd_putsf("Error");
        }
      
        else
        {
        
      
              lcd_gotoxy(0,0);
            lcd_putsf("Humidity =");
            lcd_gotoxy(0,10);
  
           #ifdef DHT22
            RH= (float) I_RH * 256.0 + D_RH ;
            RH=RH/10.0;
          
            #else
            RH =  I_RH;
             #endif
             sprintf(data,"%.1f%%  ",RH);
           lcd_puts(data);
 
 
            }
                delay_ms(2000);

            }
}
 
Last edited by a moderator:

AlbertHall

Joined Jun 4, 2014
12,269
Do you have a decoupling capacitor at the sensor power pins?
How long is the cable to the sensor and is it near anything that could interfere with the signals (mains cables, SMPS...)?
 

spinnaker

Joined Oct 29, 2009
7,830
Here is what the wonderful datasheet says:

M2303sendouthigherdatabitfirstly!

DATA=8bitintegralRHdata+8bitdecimalRHdata+8bitintegralTdata+8bitdecimalTdata+8bitcheck-sum

If the data transmission is right,check-sum should be the last 8 bit of "8 bit integral RH data+8 bit decimal RH data+8 bit integral Tdata+8bitdecimal Tdata"
.

Whatever that means. ;) Are you certain you are receiving data as you expect? Does Proteus have a logic analyzer? If so I would put tit on the output of the sensor.

Why does it seem I am the only one that can't afford to by Proteus? ;)
 
C:
        I_RH=Receive_data();    /* store first eight bit in I_RH */
        D_RH=Receive_data();    /* store next eight bit in D_RH */
        I_Temp=Receive_data();    /* store next eight bit in I_Temp */
        D_Temp=Receive_data();    /* store next eight bit in D_Temp */
        CheckSum=Receive_data();/* store next eight bit in CheckSum */
     
        if ((I_RH + D_RH + I_Temp + D_Temp) != CheckSum)
        {
            lcd_gotoxy(0,1);
            lcd_putsf("Error");
        }
That is not the way I have done the checksum in C - I have done it this way and without errors:
C:
/*
 5 bytes of DHT data are as follows:
 [0] RH integral
 [1] RH decimal
 [2] Temp integral
 [3] Temp decimal
 [4] checksum is the sum of all four bytes AND 255
 */
    // checksum
     if (((DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) & 255)
         != DHTdata[4]) {
       QM_PRINTF("  *** BAD CRC! ***  \n");
     } else {
       QM_PRINTF("  OK  \n");
     }
 

spinnaker

Joined Oct 29, 2009
7,830
C:
        I_RH=Receive_data();    /* store first eight bit in I_RH */
        D_RH=Receive_data();    /* store next eight bit in D_RH */
        I_Temp=Receive_data();    /* store next eight bit in I_Temp */
        D_Temp=Receive_data();    /* store next eight bit in D_Temp */
        CheckSum=Receive_data();/* store next eight bit in CheckSum */
   
        if ((I_RH + D_RH + I_Temp + D_Temp) != CheckSum)
        {
            lcd_gotoxy(0,1);
            lcd_putsf("Error");
        }
That is not the way I have done the checksum in C - I have done it this way and without errors:
C:
/*
5 bytes of DHT data are as follows:
[0] RH integral
[1] RH decimal
[2] Temp integral
[3] Temp decimal
[4] checksum is the sum of all four bytes AND 255
*/
    // checksum
     if (((DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) & 255)
         != DHTdata[4]) {
       QM_PRINTF("  *** BAD CRC! ***  \n");
     } else {
       QM_PRINTF("  OK  \n");
     }

Yes but if you read the cryptic datasheet that does not appear how it is done.
 
Yes but if you read the cryptic datasheet that does not appear how it is done.
There are only two kinds of datasheets for the DHT22, bad and worse. But, the way I am calculating the checksum in the C code fragment that I posted above (as well as MPASM code that I have written) is, I believe the correct way and is also consistent with the datasheet...

DHT22 send out higher data bit firstly! DATA=8 bit integral RH data+8 bit decimal RH data+8 bit integral T data+8 bit decimal T data+8 bit check-sumIf the data transmission is right, check-sum should be the last 8 bit of "8 bit integral RH data+8 bit decimal RHdata+8 bit integral T data+8 bit decimal T data". from https://www.sparkfun.com/datasheets/Sensors/Temperature/DHT22.pdf

" check-sum should be the last 8 bit of "8 bit integral RH data+8 bit decimal RHdata+8 bit integral T data+8 bit decimal T data" that means:

(DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) & 255) will = DHTdata[4] IF the checksum is good.


How are you reading it?

Now, I don't know ISIS or Proteus from Shinola, but I am pretty sure that the way I am doing the checksum for these is correct - still, I could be wrong.

edited to correct typos and non-existing tags
 

Ian Rogers

Joined Dec 12, 2012
1,130
but, how do you explain that the same code works with dht11 without errors?
I was playing with this I wrote a pic version just play with... There are slight timing differences between DHT11 and DHT22.

Remember! ISIS is too rigorous for real time... Digital simulation will have errors... If you have an Arduino to hand, build it for real, It'll probably be fine.
On ETO I said the pullup resistor needs to be digital... I stand by this.. I tested my version and it doesn't show any CRC errors.
 
but, how do you explain that the same code works with dht11 without errors?
Because, as I recall, the DHT11 does not use a decimal. So, the bytes for temp decimal and humidity decimal are always 0. So, when you sum all 4 bytes, two are zero and as long as the Temp integral and hum integral do not add up to more than 255, you will not over run 255.

So, the mistake of leaving out the & 255 in the way you were calculating:
if ((I_RH + D_RH + I_Temp + D_Temp) != CheckSum)
does not cause an error.

With the DHT22, the decimal bytes get added and when your sum is greater that 255, you end up compaing that sum with the transmitted checksum byte and they are not equal and you get the error.

- follow?
 
Last edited:

AlbertHall

Joined Jun 4, 2014
12,269
With the DHT22, the decimal bytes get added and when your sum is greater that 255, you end up compaing that sum with the transmitted checksum byte and they are not equal and you get the error.
But that shouldn't matter. All the values that are read and the checksum are declared to be uint8_t so '& 255' should make no difference.
 
But that shouldn't matter. All the values that are read and the checksum are declared to be uint8_t so '& 255' should make no difference.
That is a valid point and I also saw that, but it does make a difference - apparently (the OP has not actually said one way or the other). Maybe there is some sinister promotion/demotion going on with a 16 bit value to an 8 bit value.

I would like to know also. In the code that I have written, I also use uint8_t but I also use &255, as per the datasheet.

I may actually go test it, well, maybe, after my coffee :) (amazing the excuses I can use to avoid doing other kinds of work).
 
Top