DHT22/Reading it/04. Tenths and the sign bit
Reading it · 04 of 9

Tenths and the sign bit

The DHT22 sends each number as one 16-bit word counting tenths: 51.2 % is 512, 23.4 °C is 234. Below freezing, the top bit of the temperature word turns on and the other fifteen still count up from zero, so −0.1 °C is 0x8001. Adafruit's library reads that correctly; a decoder written by hand can print −3276.7.

Two words of tenths

The frame is the same forty bits as a DHT11's: humidity high and low, temperature high and low, and a checksum, which forty bits and a checksum in the DHT11 book takes apart. What the DHT22 changes is what the pairs of bytes mean.

A DHT11 puts whole units in the first byte of each pair and, nearly always, zero in the second. A DHT22 uses each pair as one 16-bit number counting tenths, high byte first. So 51.2 % arrives as 0x02 0x00, which is 512, and 23.4 °C as 0x00 0xEA, which is 234. Adafruit's library shifts the high byte up eight places, adds the low one, and multiplies by 0.1.

The datasheet's own §6 describes the bytes as "integral" and "decimal", which is how the DHT11 packs them and not how the DHT22 does. Trust the arithmetic: two bytes, one number, tenths.

The minus sign

Slide the temperature below zero and watch the top bit.

Sixteen bits of temperature
bytes 2 and 3 · 0x80 0x35
The room is at-5.3 °C
Word
0x8035
Bit 15
1, minus
Library prints
-5.3 °C
Below zero, only the top bit changes. The other fifteen still count tenths up from zero, so -5.3 °C is 53 tenths with the sign bit set. The library reads it that way. Read the word as an ordinary signed integer and you get -3271.5; forget the sign bit and you get 3282.1. Both are what a hand-written decoder prints on the first frost.

The temperature word is sign and magnitude. Bit 15 is the minus sign and bits 0 to 14 are the size, in tenths, counting up from zero whichever side of zero you are. So +0.1 °C is 0x0001 and −0.1 °C is 0x8001, one bit apart.

That is not how a microcontroller stores a negative number. An int16_t uses two's complement, where −0.1 would be 0xFFFF. Read the DHT22's word straight into an int16_t and −0.1 °C becomes −32767 tenths, which prints as −3276.7. Read it as unsigned and it prints 3276.9. Both show up the first night the sensor goes below zero, and never in testing indoors.

Adafruit's library gets it right: it masks bit 15 off, reads the other fifteen as tenths, and negates the result if bit 15 was set. The fault only appears in code that decodes the bytes itself, such as a sketch ported from another sensor or a decoder written for a different platform.

The range, in words

The DHT22 is specified from −40.0 to 80.0 °C. That is words from 0x8190 (−400 tenths) through 0x0000 to 0x0320 (800 tenths). Humidity runs from 0x0000 to 0x03E8, 0 to 1000 tenths. Anything outside those in a frame whose checksum passes points at the decoder before the sensor.

When it does not work

It printed −3276.7 °C on a cold night

Something read the temperature word as an ordinary signed 16-bit integer. The DHT22 uses sign and magnitude, not two's complement, so −0.1 °C, which is 0x8001, becomes −32767 tenths. Mask off bit 15, divide the rest by ten, and negate if bit 15 was set, as Adafruit's library does.

It printed 3276.9 °C, or something over 3000

The decoder ignored the sign bit and read the whole word as a positive number of tenths. Anything from 3276.8 up means bit 15 was set: the real temperature is below zero. Adafruit's library handles it; a hand-written decoder has to.

The humidity reads 1305.6 %

That is a DHT11's frame read by the DHT22 decoder: 51 % in the first byte becomes 51 × 256 tenths. Either the sensor is a DHT11 or the sketch says DHT22 on a TK38. The white cage is the DHT22.

The datasheet says integral and decimal bytes

It does, in §6, and for the DHT22 that description is wrong. 51.2 % arrives as 0x02 0x00, which is 512 tenths, not as 51 and 2. Read each pair of bytes as one 16-bit number and divide by ten.

Where this goes next

The DHT22's floor, the library's cache at the same number, and a loop timed so every line is a new reading.

Every two seconds

Edit this page — content/books/dht22/tenths-and-the-sign-bit.mdx

Community

Questions about this product

See what other owners have asked, and read their solutions.

This page covers several products. Choose yours to see the right discussions.

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse Modules and blocks on the forum