Skip to content

Commit cc0f3b2

Browse files
committed
sns(dht): merge common dht11 & dht12 calculations
notice sign bit in both bytes, apply magnitude mask to integer & scale nb. technically... dht11 shares dht12 format, but prefer to stay on the integer side
1 parent 305918d commit cc0f3b2

File tree

1 file changed

+22
-7
lines changed

1 file changed

+22
-7
lines changed

code/espurna/sensors/DHTSensor.h

+22-7
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,18 @@ float dht_humidity(DHTChipType type, std::array<uint8_t, 2> pair) {
5757
// but, its never negative, so no reason to do any conversions for signed numbers
5858
float out;
5959

60+
// based on ADSONG datasheet and various other libs implementing dht12
61+
// extract sign info from the decimal scale part instead of the integral
62+
constexpr auto MagnitudeMask = uint8_t{ 0b1111111 };
63+
6064
switch (type) {
6165
case DHT_CHIP_DHT11:
6266
out = pair[0];
6367
break;
6468

6569
case DHT_CHIP_DHT12:
66-
out = pair[0];
67-
out += pair[1] * 0.1f;
70+
out = (pair[0] & MagnitudeMask);
71+
out += (pair[1] & MagnitudeMask) * 0.1f;
6872
break;
6973

7074
case DHT_CHIP_DHT21:
@@ -85,38 +89,49 @@ float dht_temperature(DHTChipType type, std::array<uint8_t, 2> pair) {
8589
constexpr auto SignMask = uint8_t{ 0b10000000 };
8690

8791
// in case it is negative and looks like twos-complement, value can be c/p into memory as-is
88-
// plus, it is enough to only check the sign bit neighbour. possible values are around [0...800]
92+
// it is enough to only check the sign bit neighbour; possible values are around [0...800]
8993
constexpr auto NegativeTwoComplementMask = uint8_t{ 0b11000000 };
9094

9195
float out;
9296

9397
switch (type) {
98+
// []pair for dht11 & dht12 contains integral and decimal scale
99+
// based on ADSONG datasheet and various other libs implementing dht12
100+
// try to extract sign info from both pairs, not just the integral one
101+
102+
// original code prefers to drop decimal scale in favour of a integral reading due to poor precision
94103
case DHT_CHIP_DHT11:
95104
out = pair[0];
105+
if ((pair[0] & SignMask) || (pair[1] & SignMask)) {
106+
out = -out;
107+
}
96108
break;
97109

110+
// added decimal place based on the decimal scale byte
98111
case DHT_CHIP_DHT12:
99-
out = pair[0] & MagnitudeMask;
100-
if (pair[0] & SignMask) {
112+
out = (pair[0] & MagnitudeMask);
113+
out += (pair[1] & MagnitudeMask) * 0.1f;
114+
if ((pair[0] & SignMask) || (pair[1] & SignMask)) {
101115
out = -out;
102116
}
103117

104-
out = out * 0.1f;
105118
break;
106119

120+
// []pair on recent chips contains s16 data w/ sign included
107121
case DHT_CHIP_DHT21:
108122
case DHT_CHIP_DHT22:
109123
case DHT_CHIP_AM2301:
110124
case DHT_CHIP_SI7021:
125+
// special exception for negative numbers in twos-complement
111126
if ((pair[0] & NegativeTwoComplementMask) == NegativeTwoComplementMask) {
112127
int16_t tmp;
113128
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
114129
std::swap(pair[0], pair[1]);
115130
#endif
116131
std::memcpy(&tmp, pair.data(), sizeof(tmp));
117132
out = tmp;
133+
// fallback works both for the original chips and positive numbers
118134
} else {
119-
// positive numbers are the same, no conversion needed
120135
pair[0] &= MagnitudeMask;
121136
out = (pair[0] << 8) | pair[1];
122137
if (pair[0] & SignMask) {

0 commit comments

Comments
 (0)