DHT sensors/How the one wire works/06. Forty bits and a checksum
How the one wire works · 06 of 12

Forty bits and a checksum

Five bytes come back: humidity, temperature and a checksum. The checksum proves the bytes arrived intact — and nothing at all about whether you decoded them right, which is why declaring the wrong sensor produces a confident wrong number rather than an error.

Five bytes

Every reading is forty bits, most significant bit first, in the same five bytes every time. Play it through, then switch what your sketch thinks it is talking to.

Forty bits, five bytes
40 bits · 5 bytes
What is actually on the wire
What your sketch says it is
Bytes
5
Checksum
passes
Reading
23.4 °C
The checksum proves the bytes arrived, not that you read them right. A DHT22 packs each number into two bytes as tenths; a DHT11 puts whole units in the first byte and — on most parts — zero in the second. Declare the wrong one and every byte still adds up, the library reports success, and your sketch prints a number that is confidently wrong. That is the single line to get right when you swap a blue board for a white one.

The first two bytes are the humidity, the next two the temperature, and the fifth is the low eight bits of the sum of the other four. If that sum does not match, the library throws the whole frame away and hands you nan.

How a bit gets its value

There is no clock line, so the length of a pulse is the data. Every bit opens with the sensor holding the line low for 50 µs; then it lets the line up, and how long it stays up is the value:

  • about 26–28 µs high is a 0
  • about 70 µs high is a 1

Adafruit's library does not actually measure microseconds. It counts loop iterations for the low half and for the high half and compares the two: if the high count is bigger than the low count, the bit is a 1. That is a neat trick, because it works identically on a 16 MHz Uno and a 240 MHz ESP32 without either being told its own clock speed — and it is also why interrupts have to be off while the counting happens.

The same bytes, two meanings

This is the part worth remembering, because it is silent when it goes wrong.

A DHT22 packs each number into two bytes as tenths. 51.2 % is 512, which is 0x02 0x00. 23.4 °C is 234, which is 0x00 0xEA.

A DHT11 puts whole units in the first byte and, on nearly every part, zero in the second. 51 % is 0x33 0x00. 23 °C is 0x17 0x00.

Both frames pass their checksum. Both are exactly forty bits. Nothing on the wire says which sensor sent them. If your sketch declares the wrong one, the library reports success and prints a number that is wrong by two orders of magnitude — and if you are not watching, "the humidity is 1305 %" reads as a broken sensor rather than as a wrong constant.

What the checksum is actually worth

It catches the failure that this protocol is prone to: a bit whose pulse got stretched or clipped because something interrupted the counting. That happens, and when it does you want the frame thrown away rather than averaged in.

What it cannot catch is anything upstream of the bytes — the wrong sensor type, the wrong pin, a sensor reading its own warm board. Those all produce perfectly valid frames.

When it does not work

The checksum passes but the numbers are absurd

Then the bytes are fine and the decoder is wrong. A DHT22's five bytes read as a DHT11 come out near 2 % and 0 °C; a DHT11's read as a DHT22 come out in the hundreds. Change the second argument to the DHT constructor and nothing else.

How does a DHT22 report a negative temperature?

The top bit of the third byte is the sign, and the rest of the two bytes is the magnitude in tenths. It is sign and magnitude, not two's complement, so −0.1 °C and +0.1 °C differ by one bit at the top and by nothing else. The library handles it; it matters if you ever decode the bytes yourself.

My DHT11 always reports whole numbers even though the frame has tenths bytes

Most DHT11s send zero in both of them. The format has room for tenths and the library reads them, but the part's stated resolution is 1 °C and 1 % RH and that is what nearly all of them produce. It is not a bug and there is no setting for it.

Can I check the checksum myself?

The library already does — a frame that fails it is discarded and you get nan, with no way to see the bytes. If you want them, the library has a debug mode, or you can read the pin yourself with the timings in the datasheet. For ordinary use, nan is the checksum failing.

Where this goes next

The sensor's floor, the library's cache, and why a tight loop shows a stale number.

How often you may ask

Edit this page — content/books/dht22/forty-bits-and-a-checksum.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