dht22 shows check sum error

spinnaker

Joined Oct 29, 2009
7,830
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

I am reading it as simply adding the bytes togetger. But again the english is absolutely horrible not to mention how it is laid out.
 

Ian Rogers

Joined Dec 12, 2012
1,136
One thing I will need to ask....

On the DHT11 you say it works fine.. When using the DHT22 is there an ISIS warning of net contention after the initial starting of the device?
 
OK, I tested it out on my code. It took me ~35 minutes to remember how to use this D2000 board and to notice that the RX pin was disconnected!

When I use the original code there s no CRC error (Temp~ 24.79 and RH~19.60). When I remove the &255, I receive a CRC error;
C:
    if (((DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) & 255)
     //if (((DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) ) // WRONG WAY TEST
         != DHTdata[4]) {
       QM_PRINTF("  *** BAD CRC! ***  \n");
     } else {
       QM_PRINTF("  OK  \n");
     }
The fragment above shows the commented out bad line without & 255 that will produce an error. So, the question is why and I don't yet know. This is repeatable.

The complete program I am using is from https://www.allaboutcircuits.com/projects/how-to-check-and-calibrate-a-humidity-sensor/

Complete program code below:
C:
/*
*****************************************************
** This software is offered strictly as is with no **
** warranties whatsoever. Use it at your own risk. **
*****************************************************
*
* DHT22.C
*
* Reads a DHT-22 humidity and temperature sensor.
*/

/* includes */
#include "qm_gpio.h"
#include "clk.h"

/* prototypes */
int getDHT();
uint32_t wait_for_low();
uint32_t wait_for_high();
void print_float(float);
void delay_minutes(unsigned int);

/* defines */
#define DHTPIN (0)   /* DHT data pin connected to GPIO  */
#define EPOCH (1)  /* time between samples  */

/* globals */
qm_gpio_port_config_t GPIOcfg;
qm_gpio_state_t state;
uint8_t bytecounter, bitcounter, acounter;
uint8_t DHTdata[5];
/*
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
*/
int finished;

int main() {

   float RH, Temp;
   uint16_t sampleN = 0; /* counter for  samples */

   QM_PUTS("\nDHT-22 Sensor Test\n");

   /* print banner */
   QM_PRINTF("Sample  Temp (C)  Humidity  CKSUM\n");

   while (1) {
     DHTdata[0] = DHTdata[1] = DHTdata[2] = DHTdata[3] = DHTdata[4] = 0;

     if (getDHT() != 0) {
       QM_PRINTF("\nError reading DHT\n");
     } else {
       /* QM_PRINTF("\nDHT read OK"); */
     }

     // Humidity
     RH = DHTdata[0];
     RH *= 256.0;
     RH += DHTdata[1];
     RH /= 10;
     // Temperature
     Temp = DHTdata[2] & 0x7f;
     Temp *= 256.0;
     Temp += DHTdata[3];
     Temp /= 10;
     if (DHTdata[2] & 0x80) {
       Temp *= -1;
     }
     /* Use the following for Temp C to F */
     /* float TempF=Temp * 9 / 5 +32; */
     QM_PRINTF("%d  ",sampleN);
     sampleN++;
     print_float(Temp);
     QM_PRINTF("  ");
     print_float(RH);
     // checksum
     if (((DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) & 255)
     //if (((DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) ) // WRONG WAY TEST
         != DHTdata[4]) {
       QM_PRINTF("  *** BAD CRC! ***  \n");
     } else {
       QM_PRINTF("  OK  \n");
     }
     delay_minutes(EPOCH);
   }
}

int getDHT() {

   acounter = 0; /* array index counter */
   bytecounter = 5; /* data bytes counter  */
   bitcounter = 8; /* data bits counter  */
   finished = 0; /* mark not finished  */

   /* make GPIO pin connected to DHT data pin output and set it low */
   GPIOcfg.direction |= (1U << DHTPIN);
   qm_gpio_set_config(QM_GPIO_0, &GPIOcfg);
   qm_gpio_clear_pin(QM_GPIO_0, DHTPIN);
   clk_sys_udelay(18000); /* delay 18 ms */
   /* bring data pin high for 30 us */
   qm_gpio_set_pin(QM_GPIO_0, DHTPIN);
   clk_sys_udelay(30); /* delay 30 us */
   /* set data pin to input */
   GPIOcfg.direction &= ~(1U << DHTPIN);
   qm_gpio_set_config(QM_GPIO_0, &GPIOcfg);
   /* DHT should set the line low for 80 us - check and wait for it */
   if (wait_for_low() == 0) {
     QM_PRINTF("\nTimeout error waiting for DHT low 1 \n");
     return (1); /* error */
   }
   /* DHT should set the line high for 80 us - check and wait for it */
   if (wait_for_high() == 0) {
     QM_PRINTF("\nTimeout error waiting for DHT high\n");
     return (1); /* error */
   }
   /* DHT should set the line low again marking the beginning of a start bit */
   if (wait_for_low() == 0) {
     QM_PRINTF("\nTimeout error waiting for DHT low 2\n");
     return (1); /* error */
   }

   /* get all 5 bytes */
   while (finished == 0) {
     /* this is the start bit - a 50 us low on the data line followed
      by a 26-28 us high if bit='0' or 70 us high if bit='1' */
     /* wait for start bit time to end (a high) */
     if (wait_for_high() == 0) {
       QM_PRINTF("\nTimeout error waiting for DHT high\n");
       return (1); /* error */
     }
     /* delay for 40 us */
     clk_sys_udelay(40);
     /* read the data line to determine if the bit is a 1 or was a 0 */
     qm_gpio_read_pin(QM_GPIO_0, DHTPIN, &state);
     if (state == 0) {
       /* the bit was a 0 and it is over and the DHT is in a start bit time
        with about 24 us left - process the bit and jump to wait for high */
       DHTdata[acounter] = DHTdata[acounter] << 1;
       DHTdata[acounter] &= 254; /* make sure lsb=0 (probably unnecessary) */
       if (--bitcounter == 0) {
         bitcounter = 8;
         acounter++;
         if (--bytecounter == 0) {
           finished = 1;
         }
       }
     } else {
       /* the bit was a '1' and we are still in the bit time - wait for it to end
        first then process the bit and check for bumps */
       if (wait_for_low() == 0) {
         QM_PRINTF("\nTimeout error waiting for DHT low 3\n");
         return (1); /* error */
       }
       /* process the bit */
       DHTdata[acounter] = DHTdata[acounter] << 1;
       DHTdata[acounter] |= 1; /* set lsb=1 */
       /* bump bit counter */
       if (--bitcounter == 0) {
         bitcounter = 8;
         acounter++;
         if (--bytecounter == 0) {
           finished = 1;
         }
       }

     }
   }
   return (0);
}

uint32_t wait_for_low() {
   /* wait for the DHT pin to be low - return 0 on failure (count exceeded) */

   uint32_t count = 1;

   qm_gpio_read_pin(QM_GPIO_0, DHTPIN, &state);
   while (state != 0) {
     if (count++ >= 200000) { /* ~ 1-2 millisecond to read time out */
       return 0; /* Exceeded timeout, fail. */
     }
     qm_gpio_read_pin(QM_GPIO_0, DHTPIN, &state);
   }
   return count;
}

uint32_t wait_for_high() {
   /* wait for the DHT pin to be high - return 0 on failure (count exceeded) */
   uint32_t count = 1;
   qm_gpio_read_pin(QM_GPIO_0, DHTPIN, &state);
   while (state != 1) {
     if (count++ >= 200000) { /* ~ 1-2 millisecond to read time out */
       return 0; /* Exceeded timeout, fail. */
     }
     qm_gpio_read_pin(QM_GPIO_0, DHTPIN, &state);
   }
   return count;
}

void print_float(float value) {
   /*
    *  simple dedicated floating point print routine
    *  *basically* accurate to two place right of dp
    */

   /* prints 2 digits after the decimal point */
   int digit, intdigits, fractdigits;

   if (value < 0) {
     value *= -1;
     QM_PRINTF("-");
   }

   intdigits = (int) value;
   fractdigits = (10000 * (value - (float) intdigits));
   QM_PRINTF("%d",intdigits); QM_PRINTF(".");
   digit = fractdigits / 1000;
   QM_PRINTF("%d",digit);
   fractdigits = fractdigits % 1000;
   digit = fractdigits / 100;
   QM_PRINTF("%d",digit);
}

void delay_minutes(unsigned int mins) {
   unsigned int count;

   for (count = 0; count < mins; count++) {
     clk_sys_udelay(60000000UL); /* delay 60 seconds */
   }
}
@WBahn if you have some time, could you weigh in here?

Edit: to make the question a little clearer...
If I have an array declared as:
uint8_t DHTdata[5];
/*
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
*/
and I read in values for all 5 elements from the device
and then I compare the sum of the first 4 elements [0]-[3] with [4] which is the checksum sent by the device.

why do these two code fragments yield different results, that is why does the & 255 make a difference?

C:
    // works
    if (((DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) & 255)
         != DHTdata[4]) {
       QM_PRINTF("  *** BAD CRC! ***  \n");
     } else {
       QM_PRINTF("  OK  \n");
     }
C:
    // does NOT work
     if (((DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) )
         != DHTdata[4]) {
       QM_PRINTF("  *** BAD CRC! ***  \n");
     } else {
       QM_PRINTF("  OK  \n");
     }
Edited again: This is making my head hurt.
 
Last edited:

Thread Starter

mah

Joined Mar 15, 2010
393
ok,guys i added &255 the error has gone thanks.
another question, Is this dht22 reliable? I used dht11 and it was working but suddenly stuck at high or low reading. but i was't doing checksum error could that be the reason or it's a flawed in this type of sensors.
 
ok,guys i added &255 the error has gone thanks.
another question, Is this dht22 reliable? I used dht11 and it was working but suddenly stuck at high or low reading. but i was't doing checksum error could that be the reason or it's a flawed in this type of sensors.
Good to hear. What do you mean by reliable?
 

Thread Starter

mah

Joined Mar 15, 2010
393
I used dht11 and it was working but suddenly stuck at high or low reading. i was't doing checksum error could that be the reason or it's a flawed in this type of sensors. I a afraid that dht22 stuck at high or low value too. so I am asking if it is good or bad type
 
I used dht11 and it was working but suddenly stuck at high or low reading. i was't doing checksum error could that be the reason or it's a flawed in this type of sensors. I a afraid that dht22 stuck at high or low value too. so I am asking if it is good or bad type
You are simply avoiding answering my question by substituting "good or bad" for "reliable". You may not want to hear it, but it is much more complicated than that.

To me (and I am being general):
Reliability refers to how similar the values are to each other when repeatedly being read under the same conditions.
Validity/accuracy refers to how well the values represent the actual conditions.

It is a sensor and you either compare the value you get to a known standard to determine validity/accuracy or you settle for what looks reasonable.

How long the sensor will last with out malfunctioning is another question and one that requires systematic data and not a few anecdotal reports.

So, is it good or bad? - I don't know. When I tested a number of temp/humidity sensors and when I consider having used many more than the few that I tested, I would say that I prefer the higher end Honeywell sensors to the DHT22. That is an opinion only.

Sorry that I can't give you a simple yes or no.
 

spinnaker

Joined Oct 29, 2009
7,830
OK, I tested it out on my code. It took me ~35 minutes to remember how to use this D2000 board and to notice that the RX pin was disconnected!

When I use the original code there s no CRC error (Temp~ 24.79 and RH~19.60). When I remove the &255, I receive a CRC error;
C:
    if (((DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) & 255)
     //if (((DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) ) // WRONG WAY TEST
         != DHTdata[4]) {
       QM_PRINTF("  *** BAD CRC! ***  \n");
     } else {
       QM_PRINTF("  OK  \n");
     }
The fragment above shows the commented out bad line without & 255 that will produce an error. So, the question is why and I don't yet know. This is repeatable.

The complete program I am using is from https://www.allaboutcircuits.com/projects/how-to-check-and-calibrate-a-humidity-sensor/

Complete program code below:
C:
/*
*****************************************************
** This software is offered strictly as is with no **
** warranties whatsoever. Use it at your own risk. **
*****************************************************
*
* DHT22.C
*
* Reads a DHT-22 humidity and temperature sensor.
*/

/* includes */
#include "qm_gpio.h"
#include "clk.h"

/* prototypes */
int getDHT();
uint32_t wait_for_low();
uint32_t wait_for_high();
void print_float(float);
void delay_minutes(unsigned int);

/* defines */
#define DHTPIN (0)   /* DHT data pin connected to GPIO  */
#define EPOCH (1)  /* time between samples  */

/* globals */
qm_gpio_port_config_t GPIOcfg;
qm_gpio_state_t state;
uint8_t bytecounter, bitcounter, acounter;
uint8_t DHTdata[5];
/*
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
*/
int finished;

int main() {

   float RH, Temp;
   uint16_t sampleN = 0; /* counter for  samples */

   QM_PUTS("\nDHT-22 Sensor Test\n");

   /* print banner */
   QM_PRINTF("Sample  Temp (C)  Humidity  CKSUM\n");

   while (1) {
     DHTdata[0] = DHTdata[1] = DHTdata[2] = DHTdata[3] = DHTdata[4] = 0;

     if (getDHT() != 0) {
       QM_PRINTF("\nError reading DHT\n");
     } else {
       /* QM_PRINTF("\nDHT read OK"); */
     }

     // Humidity
     RH = DHTdata[0];
     RH *= 256.0;
     RH += DHTdata[1];
     RH /= 10;
     // Temperature
     Temp = DHTdata[2] & 0x7f;
     Temp *= 256.0;
     Temp += DHTdata[3];
     Temp /= 10;
     if (DHTdata[2] & 0x80) {
       Temp *= -1;
     }
     /* Use the following for Temp C to F */
     /* float TempF=Temp * 9 / 5 +32; */
     QM_PRINTF("%d  ",sampleN);
     sampleN++;
     print_float(Temp);
     QM_PRINTF("  ");
     print_float(RH);
     // checksum
     if (((DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) & 255)
     //if (((DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) ) // WRONG WAY TEST
         != DHTdata[4]) {
       QM_PRINTF("  *** BAD CRC! ***  \n");
     } else {
       QM_PRINTF("  OK  \n");
     }
     delay_minutes(EPOCH);
   }
}

int getDHT() {

   acounter = 0; /* array index counter */
   bytecounter = 5; /* data bytes counter  */
   bitcounter = 8; /* data bits counter  */
   finished = 0; /* mark not finished  */

   /* make GPIO pin connected to DHT data pin output and set it low */
   GPIOcfg.direction |= (1U << DHTPIN);
   qm_gpio_set_config(QM_GPIO_0, &GPIOcfg);
   qm_gpio_clear_pin(QM_GPIO_0, DHTPIN);
   clk_sys_udelay(18000); /* delay 18 ms */
   /* bring data pin high for 30 us */
   qm_gpio_set_pin(QM_GPIO_0, DHTPIN);
   clk_sys_udelay(30); /* delay 30 us */
   /* set data pin to input */
   GPIOcfg.direction &= ~(1U << DHTPIN);
   qm_gpio_set_config(QM_GPIO_0, &GPIOcfg);
   /* DHT should set the line low for 80 us - check and wait for it */
   if (wait_for_low() == 0) {
     QM_PRINTF("\nTimeout error waiting for DHT low 1 \n");
     return (1); /* error */
   }
   /* DHT should set the line high for 80 us - check and wait for it */
   if (wait_for_high() == 0) {
     QM_PRINTF("\nTimeout error waiting for DHT high\n");
     return (1); /* error */
   }
   /* DHT should set the line low again marking the beginning of a start bit */
   if (wait_for_low() == 0) {
     QM_PRINTF("\nTimeout error waiting for DHT low 2\n");
     return (1); /* error */
   }

   /* get all 5 bytes */
   while (finished == 0) {
     /* this is the start bit - a 50 us low on the data line followed
      by a 26-28 us high if bit='0' or 70 us high if bit='1' */
     /* wait for start bit time to end (a high) */
     if (wait_for_high() == 0) {
       QM_PRINTF("\nTimeout error waiting for DHT high\n");
       return (1); /* error */
     }
     /* delay for 40 us */
     clk_sys_udelay(40);
     /* read the data line to determine if the bit is a 1 or was a 0 */
     qm_gpio_read_pin(QM_GPIO_0, DHTPIN, &state);
     if (state == 0) {
       /* the bit was a 0 and it is over and the DHT is in a start bit time
        with about 24 us left - process the bit and jump to wait for high */
       DHTdata[acounter] = DHTdata[acounter] << 1;
       DHTdata[acounter] &= 254; /* make sure lsb=0 (probably unnecessary) */
       if (--bitcounter == 0) {
         bitcounter = 8;
         acounter++;
         if (--bytecounter == 0) {
           finished = 1;
         }
       }
     } else {
       /* the bit was a '1' and we are still in the bit time - wait for it to end
        first then process the bit and check for bumps */
       if (wait_for_low() == 0) {
         QM_PRINTF("\nTimeout error waiting for DHT low 3\n");
         return (1); /* error */
       }
       /* process the bit */
       DHTdata[acounter] = DHTdata[acounter] << 1;
       DHTdata[acounter] |= 1; /* set lsb=1 */
       /* bump bit counter */
       if (--bitcounter == 0) {
         bitcounter = 8;
         acounter++;
         if (--bytecounter == 0) {
           finished = 1;
         }
       }

     }
   }
   return (0);
}

uint32_t wait_for_low() {
   /* wait for the DHT pin to be low - return 0 on failure (count exceeded) */

   uint32_t count = 1;

   qm_gpio_read_pin(QM_GPIO_0, DHTPIN, &state);
   while (state != 0) {
     if (count++ >= 200000) { /* ~ 1-2 millisecond to read time out */
       return 0; /* Exceeded timeout, fail. */
     }
     qm_gpio_read_pin(QM_GPIO_0, DHTPIN, &state);
   }
   return count;
}

uint32_t wait_for_high() {
   /* wait for the DHT pin to be high - return 0 on failure (count exceeded) */
   uint32_t count = 1;
   qm_gpio_read_pin(QM_GPIO_0, DHTPIN, &state);
   while (state != 1) {
     if (count++ >= 200000) { /* ~ 1-2 millisecond to read time out */
       return 0; /* Exceeded timeout, fail. */
     }
     qm_gpio_read_pin(QM_GPIO_0, DHTPIN, &state);
   }
   return count;
}

void print_float(float value) {
   /*
    *  simple dedicated floating point print routine
    *  *basically* accurate to two place right of dp
    */

   /* prints 2 digits after the decimal point */
   int digit, intdigits, fractdigits;

   if (value < 0) {
     value *= -1;
     QM_PRINTF("-");
   }

   intdigits = (int) value;
   fractdigits = (10000 * (value - (float) intdigits));
   QM_PRINTF("%d",intdigits); QM_PRINTF(".");
   digit = fractdigits / 1000;
   QM_PRINTF("%d",digit);
   fractdigits = fractdigits % 1000;
   digit = fractdigits / 100;
   QM_PRINTF("%d",digit);
}

void delay_minutes(unsigned int mins) {
   unsigned int count;

   for (count = 0; count < mins; count++) {
     clk_sys_udelay(60000000UL); /* delay 60 seconds */
   }
}
@WBahn if you have some time, could you weigh in here?

Edit: to make the question a little clearer...
If I have an array declared as:
uint8_t DHTdata[5];
/*
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
*/
and I read in values for all 5 elements from the device
and then I compare the sum of the first 4 elements [0]-[3] with [4] which is the checksum sent by the device.

why do these two code fragments yield different results, that is why does the & 255 make a difference?

C:
    // works
    if (((DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) & 255)
         != DHTdata[4]) {
       QM_PRINTF("  *** BAD CRC! ***  \n");
     } else {
       QM_PRINTF("  OK  \n");
     }
C:
    // does NOT work
     if (((DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) )
         != DHTdata[4]) {
       QM_PRINTF("  *** BAD CRC! ***  \n");
     } else {
       QM_PRINTF("  OK  \n");
     }
Edited again: This is making my head hurt.

So what in the datasheet told you that you are calculating checksum correctly?
 
So what in the datasheet told you that you are calculating checksum correctly?
huh? I mean the words did as I said back in post #15...

" 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.
So, you must mean something else. Can you show some code of how you are calculating it, and/or can you show some code that shows that I am not calculating it correctly?
 

spinnaker

Joined Oct 29, 2009
7,830
huh? I mean the words did as I said back in post #15...



So, you must mean something else. Can you show some code of how you are calculating it, and/or can you show some code that shows that I am not calculating it correctly?

Yes I just want to know how you knew what they were talking about. Or did you just read the word checksum, used your experience, and ignored the rest of that mess in the datasheet?
 
Yes I just want to know how you knew what they were talking about. Or did you just read the word checksum, used your experience, and ignored the rest of that mess in the datasheet?
Oh, I see. It was a long time ago, but if I recall correctly, I had to struggle with it and ended up printing out the five values and eventually figured it out - likely after a lot of hand calculating. I also tested it quite a bit (by changing a value inside the program and similar). Don't get me wrong, when I first read something like "check-sum should be the last 8 bit", I am thinking wtf does that mean?

Contrast that situation with ds1820 where you can see the crc algorithm and get references and so on.
 
actually it isn't mentioned in datasheet that you use 255 so we want to know how do you have this idea.
It IS mentioned in the datasheet as per post #15 quote - just not in particularly clear fashion. The cryptic decoding comes in when you finally figure out that "check-sum should be the last 8 bit" means only look at the last 8 bits and hence &255.
 

Ian Rogers

Joined Dec 12, 2012
1,136
Here is the code I used.... Works for both

C:
  RH_byte1 = ReadData();
  RH_byte2 = ReadData();
  T_byte1 = ReadData();
  T_byte2 = ReadData();
  Sum = ReadData();
  if(Sum == ((RH_byte1+RH_byte2+T_byte1+T_byte2) & 0XFF))
 
So, I am still wondering about why you have to do "& 255" when the individual elements are all uint8_t (as @AlbertHall mentioned) e.g.,

( (DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) & 255)

Is it possible that the compiler holds the value of (DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) in 16 bits? Ostensibly to account for any carries?

That's why I pinged @WBahn because he usually knows these things. I add that on the D2000 gcc I get no conversion warnings, although I don't know what level I have set.
 
So, I am still wondering about why you have to do "& 255" when the individual elements are all uint8_t (as @AlbertHall mentioned) e.g.,

( (DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) & 255)

Is it possible that the compiler holds the value of (DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) in 16 bits? Ostensibly to account for any carries?

That's why I pinged @WBahn because he usually knows these things. I add that on the D2000 gcc I get no conversion warnings, although I don't know what level I have set.
I think I may be on to something with that explanation.

I just tested it using an explicit typecast and no & 255

( (uint8_t)(DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) )

and it works fine with no cksum errors!
 

spinnaker

Joined Oct 29, 2009
7,830
So, I am still wondering about why you have to do "& 255" when the individual elements are all uint8_t (as @AlbertHall mentioned) e.g.,

( (DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) & 255)

Is it possible that the compiler holds the value of (DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) in 16 bits? Ostensibly to account for any carries?

That's why I pinged @WBahn because he usually knows these things. I add that on the D2000 gcc I get no conversion warnings, although I don't know what level I have set.

My guess.

If it was done something like this

unint8 crcRec = (DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]);
if (crcRec != DHTdata[4])

It would probably have worked.
 

spinnaker

Joined Oct 29, 2009
7,830
So, I am still wondering about why you have to do "& 255" when the individual elements are all uint8_t (as @AlbertHall mentioned) e.g.,

( (DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) & 255)

Is it possible that the compiler holds the value of (DHTdata[0] + DHTdata[1] + DHTdata[2] + DHTdata[3]) in 16 bits? Ostensibly to account for any carries?

That's why I pinged @WBahn because he usually knows these things. I add that on the D2000 gcc I get no conversion warnings, although I don't know what level I have set.
Stupid compilers. ;)
 

WBahn

Joined Mar 31, 2012
32,853
When I use the original code there s no CRC error (Temp~ 24.79 and RH~19.60). When I remove the &255, I receive a CRC error;

The fragment above shows the commented out bad line without & 255 that will produce an error. So, the question is why and I don't yet know. This is repeatable.

@WBahn if you have some time, could you weigh in here?
The type of an expression is only loosely related to the type of its operands. Most compilers promote integer narrower than an int to an int when performing any expression evaluation. This is done for a couple of reasons, not the least of which is to exploit the natural data width of the processor. They are transparently down-converted if necessary when they are assigned to a variable. Since the equality comparison operation is not an assignment, but just a regular old binary operator, it doesn't affect this.

I tried finding where this is discussed in the C99 draft standard (that is my basic goto document since I have a copy of it) and couldn't find it in the minute or so that I looked. So I don't know if this behavior is required by the standard or just allowed.
 
Top