Forty bits and a checksum
Every reading is five bytes: humidity, temperature and a checksum. On the DHT11 the numbers are plain whole counts in the first byte of each pair. The checksum proves the bytes arrived intact, and nothing about whether the sketch decoded them as the right sensor.
Five bytes
Every reading is forty bits, most significant bit first, in the same five bytes. Play them through, then change what the sketch says it is talking to.
Byte 0 is the humidity and byte 2 the temperature, each a plain count: 51 %
is 0x33, 23 °C is 0x17. Bytes 1 and 3 have room for tenths, and on nearly
every DHT11 they are zero. Byte 4 is the low eight bits of the other four
added up. If it 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 DHT11 holding the line low for 50 µs. Then it lets the line up, and how long it stays up is the value:
- about 26 to 28 µs high is a 0
- about 70 µs high is a 1
Adafruit's library does not measure microseconds. It counts loop turns for the low half and for the high half of each bit and compares the two: if the high count is the bigger, the bit is a 1. That works the same on a 16 MHz Uno and a 240 MHz ESP32 without either knowing its own clock, and it is why interrupts have to be off while the counting happens.
Decoding it as the wrong sensor
The DHT22 packs each number into two bytes, as tenths. Tell the library the
TK38 is a DHT22 and, if the sensor answers at all, it reads 0x33 0x00 as one
number, 13056 tenths, and prints 1305.6 %. The temperature comes out at
588.8 °C.
The frame still passes its checksum. The library reports success. Nothing on
the wire says which sensor sent the bytes, so the only guard is the line in
the sketch: #define DHT_TYPE DHT11.
What the checksum is worth
It catches the fault this protocol is prone to: a bit whose pulse was stretched or clipped because something interrupted the counting. When that happens you want the frame thrown away, not averaged in.
It cannot catch anything upstream of the bytes: the wrong sensor type, the wrong pin, a sensor measuring its own warm board. Those all produce valid frames.
When it does not work
Then the bytes are fine and the decoder is wrong: the sketch says DHT22. A DHT11's bytes read as a DHT22's come out in the hundreds, 23 °C as 588.8 and 51 % as 1305.6. Change DHT_TYPE to DHT11 and nothing else.
Most DHT11s send zero in both of them. The format has room for tenths and the library adds them in, but the datasheet gives a resolution of 1 °C and 1 % RH and that is what nearly every part sends. It is not a bug and there is no setting for it.
Its range is 0 to 50 °C, so the datasheet never needs a minus sign. Adafruit's library reads one out of the top bit of byte 3 for parts that set it, but below 0 °C the DHT11 is outside its specification whatever it sends. The DHT22 on the TK39 is the part for frost.
The library already checks them: a frame that fails the checksum is thrown away and you get nan, with no way to see the bytes. Its debug mode prints them. For ordinary use, nan is the checksum failing or nothing answering.
The sensor's floor, the library's cache, and why a tight loop shows an old number.
How often you may ask →Edit this page — content/books/dht11/forty-bits-and-a-checksum.mdx
Questions about this product
See what other owners have asked, and read their solutions.
DHT11 Temperature and Humidity Sensor
Loading 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.