Explorar el Código

Correct negative results in DHT driver (#3210)

* DHT module: fix the handling of negative temps.

The macro handling the conversion from the 2 bytes buffer to a double
was handling negative values by checking the sign bit and taking the
negative value of the number minus the sign bit.
Unfortunately this does not work as the negative values are represented
in 1's complement, so for instance -1 was becoming -32767
  * +1 = b0000_0000_0000_ 0001
  * -1 = 1111_1111_1111_1111

This replace the spacial code with a signed 16 bits value.

* Refactoring: removes some code duplication.

* Fixed the conversion of the 8/16 bits values

Co-authored-by: Marco Dondero <marco@dondero.eu>
Emdioh hace 3 años
padre
commit
bf15299cea
Se han modificado 1 ficheros con 51 adiciones y 30 borrados
  1. 51 30
      app/dht/dht.c

+ 51 - 30
app/dht/dht.c

@@ -40,13 +40,21 @@
 #define HIGH    1
 #endif /* ifndef HIGH */
 
-#define COMBINE_HIGH_AND_LOW_BYTE(byte_high, byte_low)  (((byte_high) << 8) | (byte_low))
-
 static double dht_humidity;
 static double dht_temperature;
 
 static uint8_t dht_bytes[5];  // buffer to receive data
+
+typedef enum {
+    Humidity = 0,
+    Temperature,
+    Humidity8,
+    Temperature8
+} dht_Signal;
+
 static int dht_readSensor(uint8_t pin, uint8_t wakeupDelay);
+static double getValue(dht_Signal s);
+static bool verifyChecksum();
 
 /////////////////////////////////////////////////////
 //
@@ -91,19 +99,17 @@ int dht_read_universal(uint8_t pin)
 #endif // defined(DHT_DEBUG_BYTES)
 
     // Assume it is DHT11
-    // If it is DHT11, both bit[1] and bit[3] is 0
+    // If it is DHT11, both temp and humidity's decimal
     if ((dht_bytes[1] == 0) && (dht_bytes[3] == 0))
     {
         // It may DHT11
         // CONVERT AND STORE
         DHT_DEBUG("DHT11 method\n");
-        dht_humidity    = dht_bytes[0];  // dht_bytes[1] == 0;
-        dht_temperature = dht_bytes[2];  // dht_bytes[3] == 0;
+        dht_humidity    = getValue(Humidity8);
+        dht_temperature = getValue(Temperature8);
 
         // TEST CHECKSUM
-        // dht_bytes[1] && dht_bytes[3] both 0
-        uint8_t sum = dht_bytes[0] + dht_bytes[2];
-        if (dht_bytes[4] != sum)
+        if (!verifyChecksum())
         {
             // It may not DHT11
             dht_humidity    = DHTLIB_INVALID_VALUE; // invalid value, or is NaN prefered?
@@ -119,16 +125,11 @@ int dht_read_universal(uint8_t pin)
     // Assume it is not DHT11
     // CONVERT AND STORE
     DHT_DEBUG("DHTxx method\n");
-    dht_humidity = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[0], dht_bytes[1]) * 0.1;
-    dht_temperature = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[2] & 0x7F, dht_bytes[3]) * 0.1;
-    if (dht_bytes[2] & 0x80)  // negative dht_temperature
-    {
-        dht_temperature = -dht_temperature;
-    }
+    dht_humidity = getValue(Humidity);
+    dht_temperature = getValue(Temperature);
 
     // TEST CHECKSUM
-    uint8_t sum = dht_bytes[0] + dht_bytes[1] + dht_bytes[2] + dht_bytes[3];
-    if (dht_bytes[4] != sum)
+    if (!verifyChecksum())
     {
         return DHTLIB_ERROR_CHECKSUM;
     }
@@ -151,13 +152,11 @@ int dht_read11(uint8_t pin)
     }
 
     // CONVERT AND STORE
-    dht_humidity    = dht_bytes[0];  // dht_bytes[1] == 0;
-    dht_temperature = dht_bytes[2];  // dht_bytes[3] == 0;
+    dht_humidity = getValue(Humidity8);
+    dht_temperature = getValue(Temperature8);
 
     // TEST CHECKSUM
-    // dht_bytes[1] && dht_bytes[3] both 0
-    uint8_t sum = dht_bytes[0] + dht_bytes[1] + dht_bytes[2] + dht_bytes[3];
-    if (dht_bytes[4] != sum) return DHTLIB_ERROR_CHECKSUM;
+    if (!verifyChecksum()) return DHTLIB_ERROR_CHECKSUM;
 
     return DHTLIB_OK;
 }
@@ -179,16 +178,11 @@ int dht_read(uint8_t pin)
     }
 
     // CONVERT AND STORE
-    dht_humidity = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[0], dht_bytes[1]) * 0.1;
-    dht_temperature = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[2] & 0x7F, dht_bytes[3]) * 0.1;
-    if (dht_bytes[2] & 0x80)  // negative dht_temperature
-    {
-        dht_temperature = -dht_temperature;
-    }
+    dht_humidity = getValue(Humidity);
+    dht_temperature = getValue(Temperature);
 
     // TEST CHECKSUM
-    uint8_t sum = dht_bytes[0] + dht_bytes[1] + dht_bytes[2] + dht_bytes[3];
-    if (dht_bytes[4] != sum)
+    if (!verifyChecksum())
     {
         return DHTLIB_ERROR_CHECKSUM;
     }
@@ -242,7 +236,7 @@ int dht_readSensor(uint8_t pin, uint8_t wakeupDelay)
     // volatile uint8_t *PIR = portInputRegister(port);
 
     // EMPTY BUFFER
-    for (i = 0; i < 5; i++) dht_bytes[i] = 0;
+    memset(dht_bytes, sizeof(uint8_t)*5, 0);
 
     // REQUEST SAMPLE
     // pinMode(pin, OUTPUT);
@@ -314,6 +308,33 @@ int dht_readSensor(uint8_t pin, uint8_t wakeupDelay)
 
     return DHTLIB_OK;
 }
+
+// Assembles the high and low byte in a signed 16bit value
+static double getValue(dht_Signal s)
+{
+    uint8_t high=0, low=0;
+
+    // the '8' variants leave the low byte set to 0
+    switch(s){
+        case Humidity:
+            low = dht_bytes[1];
+        case Humidity8:
+            high = dht_bytes[0];
+            break;
+        case Temperature:
+            low = dht_bytes[3];
+        case Temperature8:
+            high = dht_bytes[2];
+            break;
+    }
+    return ((high << 8) | low) * 0.1;
+}
+
+static bool verifyChecksum(){
+    uint8_t sum = dht_bytes[0] + dht_bytes[1] + dht_bytes[2] + dht_bytes[3];
+    return (dht_bytes[4] == sum);
+}
+
 //
 // END OF FILE
 //