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>
This commit is contained in:
Emdioh 2020-08-03 20:58:19 +02:00 committed by GitHub
parent 2fa63a1303
commit bf15299cea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 51 additions and 30 deletions

View File

@ -40,13 +40,21 @@
#define HIGH 1 #define HIGH 1
#endif /* ifndef HIGH */ #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_humidity;
static double dht_temperature; static double dht_temperature;
static uint8_t dht_bytes[5]; // buffer to receive data 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 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) #endif // defined(DHT_DEBUG_BYTES)
// Assume it is DHT11 // 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)) if ((dht_bytes[1] == 0) && (dht_bytes[3] == 0))
{ {
// It may DHT11 // It may DHT11
// CONVERT AND STORE // CONVERT AND STORE
DHT_DEBUG("DHT11 method\n"); DHT_DEBUG("DHT11 method\n");
dht_humidity = dht_bytes[0]; // dht_bytes[1] == 0; dht_humidity = getValue(Humidity8);
dht_temperature = dht_bytes[2]; // dht_bytes[3] == 0; dht_temperature = getValue(Temperature8);
// TEST CHECKSUM // TEST CHECKSUM
// dht_bytes[1] && dht_bytes[3] both 0 if (!verifyChecksum())
uint8_t sum = dht_bytes[0] + dht_bytes[2];
if (dht_bytes[4] != sum)
{ {
// It may not DHT11 // It may not DHT11
dht_humidity = DHTLIB_INVALID_VALUE; // invalid value, or is NaN prefered? 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 // Assume it is not DHT11
// CONVERT AND STORE // CONVERT AND STORE
DHT_DEBUG("DHTxx method\n"); DHT_DEBUG("DHTxx method\n");
dht_humidity = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[0], dht_bytes[1]) * 0.1; dht_humidity = getValue(Humidity);
dht_temperature = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[2] & 0x7F, dht_bytes[3]) * 0.1; dht_temperature = getValue(Temperature);
if (dht_bytes[2] & 0x80) // negative dht_temperature
{
dht_temperature = -dht_temperature;
}
// TEST CHECKSUM // TEST CHECKSUM
uint8_t sum = dht_bytes[0] + dht_bytes[1] + dht_bytes[2] + dht_bytes[3]; if (!verifyChecksum())
if (dht_bytes[4] != sum)
{ {
return DHTLIB_ERROR_CHECKSUM; return DHTLIB_ERROR_CHECKSUM;
} }
@ -151,13 +152,11 @@ int dht_read11(uint8_t pin)
} }
// CONVERT AND STORE // CONVERT AND STORE
dht_humidity = dht_bytes[0]; // dht_bytes[1] == 0; dht_humidity = getValue(Humidity8);
dht_temperature = dht_bytes[2]; // dht_bytes[3] == 0; dht_temperature = getValue(Temperature8);
// TEST CHECKSUM // TEST CHECKSUM
// dht_bytes[1] && dht_bytes[3] both 0 if (!verifyChecksum()) return DHTLIB_ERROR_CHECKSUM;
uint8_t sum = dht_bytes[0] + dht_bytes[1] + dht_bytes[2] + dht_bytes[3];
if (dht_bytes[4] != sum) return DHTLIB_ERROR_CHECKSUM;
return DHTLIB_OK; return DHTLIB_OK;
} }
@ -179,16 +178,11 @@ int dht_read(uint8_t pin)
} }
// CONVERT AND STORE // CONVERT AND STORE
dht_humidity = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[0], dht_bytes[1]) * 0.1; dht_humidity = getValue(Humidity);
dht_temperature = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[2] & 0x7F, dht_bytes[3]) * 0.1; dht_temperature = getValue(Temperature);
if (dht_bytes[2] & 0x80) // negative dht_temperature
{
dht_temperature = -dht_temperature;
}
// TEST CHECKSUM // TEST CHECKSUM
uint8_t sum = dht_bytes[0] + dht_bytes[1] + dht_bytes[2] + dht_bytes[3]; if (!verifyChecksum())
if (dht_bytes[4] != sum)
{ {
return DHTLIB_ERROR_CHECKSUM; return DHTLIB_ERROR_CHECKSUM;
} }
@ -242,7 +236,7 @@ int dht_readSensor(uint8_t pin, uint8_t wakeupDelay)
// volatile uint8_t *PIR = portInputRegister(port); // volatile uint8_t *PIR = portInputRegister(port);
// EMPTY BUFFER // EMPTY BUFFER
for (i = 0; i < 5; i++) dht_bytes[i] = 0; memset(dht_bytes, sizeof(uint8_t)*5, 0);
// REQUEST SAMPLE // REQUEST SAMPLE
// pinMode(pin, OUTPUT); // pinMode(pin, OUTPUT);
@ -314,6 +308,33 @@ int dht_readSensor(uint8_t pin, uint8_t wakeupDelay)
return DHTLIB_OK; 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 // END OF FILE
// //