8
8
#pragma once
9
9
10
10
#include " ../gpio.h"
11
+ #include " ../system_time.h"
11
12
#include " ../utils.h"
13
+
12
14
#include " BaseSensor.h"
13
15
14
16
enum class DHTChipType {
@@ -28,15 +30,20 @@ enum class DHTChipType {
28
30
#define DHT_CHIP_AM2301 DHTChipType::AM2301
29
31
#define DHT_CHIP_SI7021 DHTChipType::SI7021
30
32
31
- int dhtchip_to_number (DHTChipType chip) {
32
- switch (chip) {
33
+ namespace {
34
+
35
+ int dht_chip_to_number (DHTChipType type) {
36
+ switch (type) {
33
37
case DHTChipType::DHT11:
34
38
return 11 ;
39
+
35
40
case DHTChipType::DHT12:
36
41
return 12 ;
42
+
37
43
case DHTChipType::DHT21:
38
44
case DHTChipType::AM2301:
39
45
return 21 ;
46
+
40
47
case DHTChipType::DHT22:
41
48
case DHTChipType::SI7021:
42
49
return 22 ;
@@ -45,6 +52,91 @@ int dhtchip_to_number(DHTChipType chip) {
45
52
return -1 ;
46
53
}
47
54
55
+ float dht_humidity (DHTChipType type, std::array<uint8_t , 2 > pair) {
56
+ // binary representation varies between the original chip and its copies
57
+ // but, its never negative, so no reason to do any conversions for signed numbers
58
+ float out;
59
+
60
+ switch (type) {
61
+ case DHT_CHIP_DHT11:
62
+ out = pair[0 ];
63
+ break ;
64
+
65
+ case DHT_CHIP_DHT12:
66
+ out = pair[0 ];
67
+ out += pair[1 ] * 0 .1f ;
68
+ break ;
69
+
70
+ case DHT_CHIP_DHT21:
71
+ case DHT_CHIP_DHT22:
72
+ case DHT_CHIP_AM2301:
73
+ case DHT_CHIP_SI7021:
74
+ out = ((pair[0 ] << 8 ) | pair[1 ]) * 0 .1f ;
75
+ break ;
76
+ }
77
+
78
+ return out;
79
+ }
80
+
81
+ float dht_temperature (DHTChipType type, std::array<uint8_t , 2 > pair) {
82
+ // binary representation varies between the original chip and its copies
83
+ // by default, check for generic sign-magnitude
84
+ constexpr auto MagnitudeMask = uint8_t { 0b1111111 };
85
+ constexpr auto SignMask = uint8_t { 0b10000000 };
86
+
87
+ // 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]
89
+ constexpr auto NegativeTwoComplementMask = uint8_t { 0b11000000 };
90
+
91
+ float out;
92
+
93
+ switch (type) {
94
+ case DHT_CHIP_DHT11:
95
+ out = pair[0 ];
96
+ break ;
97
+
98
+ case DHT_CHIP_DHT12:
99
+ out = pair[0 ] & MagnitudeMask;
100
+ if (pair[0 ] & SignMask) {
101
+ out = -out;
102
+ }
103
+
104
+ out = out * 0 .1f ;
105
+ break ;
106
+
107
+ case DHT_CHIP_DHT21:
108
+ case DHT_CHIP_DHT22:
109
+ case DHT_CHIP_AM2301:
110
+ case DHT_CHIP_SI7021:
111
+ if ((pair[0 ] & NegativeTwoComplementMask) == NegativeTwoComplementMask) {
112
+ int16_t tmp;
113
+ #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
114
+ std::swap (pair[0 ], pair[1 ]);
115
+ #endif
116
+ std::memcpy (&tmp, pair.data (), sizeof (tmp));
117
+ out = tmp;
118
+ } else {
119
+ // positive numbers are the same, no conversion needed
120
+ pair[0 ] &= MagnitudeMask;
121
+ out = (pair[0 ] << 8 ) | pair[1 ];
122
+ if (pair[0 ] & SignMask) {
123
+ out = -out;
124
+ }
125
+ }
126
+
127
+ out *= 0 .1f ;
128
+ break ;
129
+ }
130
+
131
+ return out;
132
+ }
133
+
134
+ bool dht_checksum (const std::array<uint8_t , 5 >& data) {
135
+ return data[4 ] == ((data[0 ] + data[1 ] + data[2 ] + data[3 ]) & 0xFF );
136
+ }
137
+
138
+ } // namespace
139
+
48
140
class DHTSensor : public BaseSensor {
49
141
50
142
public:
@@ -82,7 +174,7 @@ class DHTSensor : public BaseSensor {
82
174
}
83
175
84
176
int getType () const {
85
- return dhtchip_to_number (_type);
177
+ return dht_chip_to_number (_type);
86
178
}
87
179
88
180
DHTChipType getChipType () const {
@@ -132,7 +224,7 @@ class DHTSensor : public BaseSensor {
132
224
String description () const override {
133
225
char buffer[20 ];
134
226
snprintf_P (buffer, sizeof (buffer),
135
- " DHT%d @ GPIO%hhu" , dhtchip_to_number (_type), _gpio);
227
+ " DHT%d @ GPIO%hhu" , dht_chip_to_number (_type), _gpio);
136
228
return String (buffer);
137
229
}
138
230
@@ -244,49 +336,23 @@ class DHTSensor : public BaseSensor {
244
336
espurna::duration::Milliseconds (250 ));
245
337
}
246
338
247
- Data dhtData {};
339
+ Data data {};
248
340
249
341
noInterrupts ();
250
- _read_critical (dhtData );
342
+ _read_critical (data );
251
343
interrupts ();
252
344
253
345
if (_error != SENSOR_ERROR_OK) {
254
346
return ;
255
347
}
256
348
257
- // Verify checksum
258
- if (dhtData[4 ] != ((dhtData[0 ] + dhtData[1 ] + dhtData[2 ] + dhtData[3 ]) & 0xFF )) {
349
+ if (!dht_checksum (data)) {
259
350
_error = SENSOR_ERROR_CRC;
260
351
return ;
261
352
}
262
353
263
- // Get humidity from Data[0] and Data[1]
264
- if (_type == DHT_CHIP_DHT11) {
265
- _humidity = dhtData[0 ];
266
- } else if (_type == DHT_CHIP_DHT12) {
267
- _humidity = dhtData[0 ];
268
- _humidity += dhtData[1 ] * 0.1 ;
269
- } else {
270
- _humidity = dhtData[0 ] * 256 + dhtData[1 ];
271
- _humidity /= 10 ;
272
- }
273
-
274
- // Get temp from Data[2] and Data[3]
275
- if (_type == DHT_CHIP_DHT11) {
276
- _temperature = dhtData[2 ];
277
- } else if (_type == DHT_CHIP_DHT12) {
278
- _temperature = (dhtData[2 ] & 0x7F );
279
- _temperature += dhtData[3 ] * 0.1 ;
280
- if (dhtData[2 ] & 0x80 ) {
281
- _temperature *= -1 ;
282
- }
283
- } else {
284
- _temperature = (dhtData[2 ] & 0x7F ) * 256 + dhtData[3 ];
285
- _temperature /= 10 ;
286
- if (dhtData[2 ] & 0x80 ) {
287
- _temperature *= -1 ;
288
- }
289
- }
354
+ _humidity = dht_humidity (_type, {data[0 ], data[1 ]});
355
+ _temperature = dht_temperature (_type, {data[2 ], data[3 ]});
290
356
291
357
_last_ok = TimeSource::now ();
292
358
0 commit comments