Nope Noper
Nope Noper

Reputation: 1

How does technions DHT22.c program calculate the temperature?

How does his code calculate the temperature?

It's especially this part of the program I'm searching an explanation for (I don't undetsand why he's doing (& 0x7F) and multiplying by 256):

if ((j >= 40) &&
  (dht22_dat[4] == ((dht22_dat[0] + dht22_dat[1] + dht22_dat[2] + dht22_dat[3]) & 0xFF)) ) {
    float t, h;
    h = (float)dht22_dat[0] * 256 + (float)dht22_dat[1];
    h /= 10;
    t = (float)(dht22_dat[2] & 0x7F)* 256 + (float)dht22_dat[3];
    t /= 10.0;
    if ((dht22_dat[2] & 0x80) != 0)  t *= -1;
    sicher = 0;    
    dsicher = false;
    temp = t;
printf("Humidity = %.2f %% Temperature = %.2f *C \n", h, t );

I'd be more than grateful if somebody could comment the code above. The entire program can be found here: http://pastebin.com/zkaTjQiS

Upvotes: 0

Views: 1569

Answers (1)

Wintermute
Wintermute

Reputation: 44063

As you can see in the DHT22 datasheet, the sensor, when asked, clocks out 40 bits of data over 1-wire. The first 16 bits encode the relative humidity as tenths of a percent, the next 16 bits the temperature as tenths of degress Celsius, and the last 8 are a checksum.

All this happens in MSBit order, and the numbers in the transcribed 5 bytes are therefore encoded in big endian. Furthermore, as you can also see in the datasheet, the temperature data is encoded as signed magnitude rather than two's complement.

So:

if ((j >= 40) &&
  (dht22_dat[4] == ((dht22_dat[0] + dht22_dat[1] + dht22_dat[2] + dht22_dat[3]) & 0xFF)) ) {

checks that 40 bits were clocked out and that the checksum is valid.

h = (float)dht22_dat[0] * 256 + (float)dht22_dat[1];
h /= 10;

makes unnecessary use of floating point arithmetic in order to keep the humidity in percent rather than promille, but other than that it just shifts the higher byte up in value to its rightful place and adds the lower to that. You could just as well write

h = dht22_dat[0] << 8 | dht22_dat[1];

if you preferred that notation; the point is to make from the two individual bytes the 16-bit integer value that they represent.

Think of this, if you will, as though the sensor had given you two decimal digits 2 and 3, and you had to reconstruct the value from them. If you knew 2 to be the more significant digit, you would calculate 2 * 10 + 3 to get the actual value of 23. The same principle applies here, except that the sensor didn't give you decimal digits but 256-ary ones, and so instead of a * 10 + b you calculate a * 256 + b.

Similarly,

t = (float)(dht22_dat[2] & 0x7F)* 256 + (float)dht22_dat[3];
t /= 10.0;

assembles the lower 7 bit of the higher byte and the lower byte into the absolute value of the temperature. Isolating the lower 7 bit of the higher byte is necessary because its highest bit is a sign bit used to represent negative temperatures and not part of the absolute value of the temperature.

Then

if ((dht22_dat[2] & 0x80) != 0)  t *= -1;

checks if that sign bit is set and adjusts the sign of the result if it is, and

printf("Humidity = %.2f %% Temperature = %.2f *C \n", h, t );

prints the results of the transformation.

Upvotes: 2

Related Questions