From 40500b489f2637e851c7a1c5f209f55e93b655eb Mon Sep 17 00:00:00 2001 From: Maxim Prokhorov Date: Wed, 5 Mar 2025 23:02:13 +0300 Subject: [PATCH] sns(dht): another dht22 variant w/ 12bit values --- code/espurna/sensors/DHTSensor.h | 31 ++++++++++++----- code/test/unit/src/sensor/sensor.cpp | 50 ++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 8 deletions(-) diff --git a/code/espurna/sensors/DHTSensor.h b/code/espurna/sensors/DHTSensor.h index 1edc5c026d..28bc8353b1 100644 --- a/code/espurna/sensors/DHTSensor.h +++ b/code/espurna/sensors/DHTSensor.h @@ -82,6 +82,17 @@ float dht_humidity(DHTChipType type, std::array pair) { return out; } +float dht_raw_impl(std::array pair) { + int16_t out; + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + std::swap(pair[0], pair[1]); +#endif + std::memcpy(&out, pair.data(), sizeof(out)); + + return out; +} + float dht_temperature(DHTChipType type, std::array pair) { // binary representation varies between the original chip and its copies // by default, check for generic sign-magnitude @@ -92,6 +103,11 @@ float dht_temperature(DHTChipType type, std::array pair) { // it is enough to only check the sign bit neighbour; possible values are around [0...800] constexpr auto NegativeTwoComplementMask = uint8_t{ 0b11000000 }; + // another case is 12bit value instead of full 16bit + // in case of negative numbers we'd have to extend it to full 16bit + constexpr auto ShortVoidMask = uint8_t{ 0b11111000 }; + constexpr auto ShortSignMask = uint8_t{ 0b00001000 }; + float out; switch (type) { @@ -122,15 +138,14 @@ float dht_temperature(DHTChipType type, std::array pair) { case DHT_CHIP_DHT22: case DHT_CHIP_AM2301: case DHT_CHIP_SI7021: - // special exception for negative numbers in twos-complement + // negative numbers in twos-complement if ((pair[0] & NegativeTwoComplementMask) == NegativeTwoComplementMask) { - int16_t tmp; -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - std::swap(pair[0], pair[1]); -#endif - std::memcpy(&tmp, pair.data(), sizeof(tmp)); - out = tmp; - // fallback works both for the original chips and positive numbers + out = dht_raw_impl(pair); + // 12bit numbers have to be extended first + } else if ((pair[0] & ShortVoidMask) == ShortSignMask) { + pair[0] |= ShortVoidMask; + out = dht_raw_impl(pair); + // otherwise, use the standard copy } else { out = ((pair[0] & MagnitudeMask) << 8) | pair[1]; if (pair[0] & SignMask) { diff --git a/code/test/unit/src/sensor/sensor.cpp b/code/test/unit/src/sensor/sensor.cpp index f88ba2a306..c3f07616b3 100644 --- a/code/test/unit/src/sensor/sensor.cpp +++ b/code/test/unit/src/sensor/sensor.cpp @@ -15,13 +15,19 @@ // TODO is ..._SUPPORT wrapping necessary inside of sensor includes? // TODO ..._PORT should not be used in the class itself? +// TODO ignore -Wunused-value that comes up here from interrupts() / noInterrupts() usage +#undef xt_rsil +#define xt_rsil(X) + #define SENSOR_SUPPORT 1 #define CSE7766_SUPPORT 1 #define A02YYU_SUPPORT 1 +#define DHT_SUPPORT 1 #include #include #include +#include #include #include @@ -193,6 +199,49 @@ void test_a02yyu_data() { TEST_ASSERT_EQUAL_DOUBLE(1.953, ptr->value(0)); } +void test_dht_data() { + constexpr auto a = 0b00011010; + constexpr auto b = 0b10000110; + + TEST_ASSERT_EQUAL_FLOAT(56.8f, + dht_humidity(DHT_CHIP_DHT12, {0x38, 0x8})); + TEST_ASSERT_EQUAL_FLOAT(26.6f, + dht_temperature(DHT_CHIP_DHT12, {0x1a, 0x6})); + TEST_ASSERT_EQUAL_FLOAT(-26.6f, + dht_temperature(DHT_CHIP_DHT12, {0x1a, 0x86})); + + TEST_ASSERT_EQUAL_FLOAT(44.9f, + dht_humidity(DHT_CHIP_DHT22, {0x1, 0xc1})); + TEST_ASSERT_EQUAL_FLOAT(0.2f, + dht_temperature(DHT_CHIP_DHT22, {0x0, 0x2})); + TEST_ASSERT_EQUAL_FLOAT(-0.2f, + dht_temperature(DHT_CHIP_DHT22, {0x80, 0x2})); + + TEST_ASSERT_EQUAL_FLOAT(92.3f, + dht_humidity(DHT_CHIP_DHT22, {0x3, 0x9b})); + TEST_ASSERT_EQUAL_FLOAT(2.9f, + dht_temperature(DHT_CHIP_DHT22, {0x0, 0x1d})); + + TEST_ASSERT_EQUAL_FLOAT(56.3f, + dht_humidity(DHT_CHIP_DHT22, {0x2, 0x33})); + TEST_ASSERT_EQUAL_FLOAT(-0.9f, + dht_temperature(DHT_CHIP_DHT22, {0xff, 0xf7})); + + TEST_ASSERT_EQUAL_FLOAT(93.0f, + dht_humidity(DHT_CHIP_DHT22, {0x3, 0xa2})); + TEST_ASSERT_EQUAL_FLOAT(-4.8f, + dht_temperature(DHT_CHIP_DHT22, {0xff, 0xd0})); + TEST_ASSERT_EQUAL_FLOAT(-4.7f, + dht_temperature(DHT_CHIP_DHT22, {0xff, 0xd1})); + TEST_ASSERT_EQUAL_FLOAT(-4.6f, + dht_temperature(DHT_CHIP_DHT22, {0xff, 0xd2})); + + TEST_ASSERT_EQUAL_FLOAT(88.9f, + dht_humidity(DHT_CHIP_DHT22, {0x3, 0x79})); + TEST_ASSERT_EQUAL_FLOAT(-2.2f, + dht_temperature(DHT_CHIP_DHT22, {0xf, 0xea})); +} + } // namespace } // namespace test } // namespace espurna @@ -202,5 +251,6 @@ int main(int, char**) { using namespace espurna::test; RUN_TEST(test_cse7766_data); RUN_TEST(test_a02yyu_data); + RUN_TEST(test_dht_data); return UNITY_END(); }