Fix DHT module (#3334)

* DHT module negative values bug fix
* Revamp of the DHT module, DHT12 support
* Updated documentation
This commit is contained in:
Lukáš Voborský 2020-12-16 23:07:03 +01:00 committed by Marcel Stör
parent f4ba635d3c
commit 9c1f4aca5b
4 changed files with 106 additions and 188 deletions

View File

@ -26,6 +26,7 @@
// //
// Released to the public domain // Released to the public domain
// //
// #define NODE_DEBUG
#include "user_interface.h" #include "user_interface.h"
#include "platform.h" #include "platform.h"
@ -40,21 +41,14 @@
#define HIGH 1 #define HIGH 1
#endif /* ifndef HIGH */ #endif /* ifndef HIGH */
#define COMBINE_HIGH_AND_LOW_BYTE(byte_high, byte_low) ((uint16_t)((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();
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
// //
@ -79,10 +73,15 @@ double dht_getTemperature(void)
// DHTLIB_OK // DHTLIB_OK
// DHTLIB_ERROR_CHECKSUM // DHTLIB_ERROR_CHECKSUM
// DHTLIB_ERROR_TIMEOUT // DHTLIB_ERROR_TIMEOUT
int dht_read_universal(uint8_t pin) int dht_read(uint8_t pin, dht_type type)
{ {
// READ VALUES // READ VALUES
int rv = dht_readSensor(pin, DHTLIB_DHT_UNI_WAKEUP); int rv = dht_readSensor(pin,
type == DHT22 ? DHTLIB_DHT_WAKEUP :
type == DHT11 ? DHTLIB_DHT11_WAKEUP :
DHTLIB_DHT_UNI_WAKEUP
);
if (rv != DHTLIB_OK) if (rv != DHTLIB_OK)
{ {
dht_humidity = DHTLIB_INVALID_VALUE; // invalid value, or is NaN prefered? dht_humidity = DHTLIB_INVALID_VALUE; // invalid value, or is NaN prefered?
@ -90,129 +89,73 @@ int dht_read_universal(uint8_t pin)
return rv; // propagate error value return rv; // propagate error value
} }
#if defined(DHT_DEBUG_BYTES) NODE_DBG("DHT registers: %x\t%x\t%x\t%x\t%x == %x\n", dht_bytes[0], dht_bytes[1], dht_bytes[2], dht_bytes[3], dht_bytes[4], (uint8_t)(dht_bytes[0] + dht_bytes[1] + dht_bytes[2] + dht_bytes[3]));
int i;
for (i = 0; i < 5; i++)
{
DHT_DEBUG("%02X\n", dht_bytes[i]);
}
#endif // defined(DHT_DEBUG_BYTES)
// Assume it is DHT11 // Assume it is special case of DHT11,
// i.e. positive temperature and dht_bytes[3] == 0 ((dht_bytes[3] & 0x0f) * 0.1 to be added to temperature readout)
// If it is DHT11, both temp and humidity's decimal // If it is DHT11, both temp and humidity's decimal
dht_humidity = dht_bytes[0];
dht_temperature = dht_bytes[2];
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"); NODE_DBG("DHT11 method\n");
dht_humidity = getValue(Humidity8);
dht_temperature = getValue(Temperature8);
// TEST CHECKSUM // TEST CHECKSUM
if (!verifyChecksum()) uint8_t sum = dht_bytes[0] + dht_bytes[2];
{ if (dht_bytes[4] == sum)
// It may not DHT11
dht_humidity = DHTLIB_INVALID_VALUE; // invalid value, or is NaN prefered?
dht_temperature = DHTLIB_INVALID_VALUE; // invalid value
// Do nothing
}
else
{ {
return DHTLIB_OK; return DHTLIB_OK;
} }
} }
// Assume it is not DHT11 // Assume it is not DHT11 special case
// CONVERT AND STORE // CONVERT AND STORE
DHT_DEBUG("DHTxx method\n"); NODE_DBG("DHTxx method\n");
dht_humidity = getValue(Humidity);
dht_temperature = getValue(Temperature); switch (type) {
case DHT11:
case DHT12:
dht_humidity += dht_bytes[1] * 0.1;
break;
default:
dht_humidity = COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[0], dht_bytes[1]) * 0.1;
break;
}
switch (type) {
case DHT11:
if (dht_bytes[3] & 0x80) {
dht_temperature = -1 - dht_temperature;
}
dht_temperature += (dht_bytes[3] & 0x0f) * 0.1;
break;
case DHT12:
dht_temperature += (dht_bytes[3] & 0x0f) * 0.1;
if (dht_bytes[2] & 0x80) // negative dht_temperature
{
dht_temperature *= -1;
}
break;
default: // DHT22, DHT_NON11
dht_temperature = COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[2] & 0x7F, dht_bytes[3]) * 0.1;
if (dht_bytes[2] & 0x80) // negative dht_temperature
{
dht_temperature *= -1;
}
break;
}
// TEST CHECKSUM // TEST CHECKSUM
if (!verifyChecksum()) 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_ERROR_CHECKSUM;
} }
return DHTLIB_OK; return DHTLIB_OK;
} }
// return values:
// DHTLIB_OK
// DHTLIB_ERROR_CHECKSUM
// DHTLIB_ERROR_TIMEOUT
int dht_read11(uint8_t pin)
{
// READ VALUES
int rv = dht_readSensor(pin, DHTLIB_DHT11_WAKEUP);
if (rv != DHTLIB_OK)
{
dht_humidity = DHTLIB_INVALID_VALUE; // invalid value, or is NaN prefered?
dht_temperature = DHTLIB_INVALID_VALUE; // invalid value
return rv;
}
// CONVERT AND STORE
dht_humidity = getValue(Humidity8);
dht_temperature = getValue(Temperature8);
// TEST CHECKSUM
if (!verifyChecksum()) return DHTLIB_ERROR_CHECKSUM;
return DHTLIB_OK;
}
// return values:
// DHTLIB_OK
// DHTLIB_ERROR_CHECKSUM
// DHTLIB_ERROR_TIMEOUT
int dht_read(uint8_t pin)
{
// READ VALUES
int rv = dht_readSensor(pin, DHTLIB_DHT_WAKEUP);
if (rv != DHTLIB_OK)
{
dht_humidity = DHTLIB_INVALID_VALUE; // invalid value, or is NaN prefered?
dht_temperature = DHTLIB_INVALID_VALUE; // invalid value
return rv; // propagate error value
}
// CONVERT AND STORE
dht_humidity = getValue(Humidity);
dht_temperature = getValue(Temperature);
// TEST CHECKSUM
if (!verifyChecksum())
{
return DHTLIB_ERROR_CHECKSUM;
}
return DHTLIB_OK;
}
// return values:
// DHTLIB_OK
// DHTLIB_ERROR_CHECKSUM
// DHTLIB_ERROR_TIMEOUT
int dht_read21(uint8_t pin) __attribute__((alias("dht_read")));
// return values:
// DHTLIB_OK
// DHTLIB_ERROR_CHECKSUM
// DHTLIB_ERROR_TIMEOUT
int dht_read22(uint8_t pin) __attribute__((alias("dht_read")));
// return values:
// DHTLIB_OK
// DHTLIB_ERROR_CHECKSUM
// DHTLIB_ERROR_TIMEOUT
int dht_read33(uint8_t pin) __attribute__((alias("dht_read")));
// return values:
// DHTLIB_OK
// DHTLIB_ERROR_CHECKSUM
// DHTLIB_ERROR_TIMEOUT
int dht_read44(uint8_t pin) __attribute__((alias("dht_read")));
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
// //
// PRIVATE // PRIVATE
@ -236,7 +179,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
memset(dht_bytes, sizeof(uint8_t)*5, 0); memset(dht_bytes, 0, sizeof(uint8_t)*5);
// REQUEST SAMPLE // REQUEST SAMPLE
// pinMode(pin, OUTPUT); // pinMode(pin, OUTPUT);
@ -309,32 +252,6 @@ 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
// //

View File

@ -30,8 +30,6 @@
#define DHTLIB_DHT_WAKEUP 1 #define DHTLIB_DHT_WAKEUP 1
#define DHTLIB_DHT_UNI_WAKEUP 18 #define DHTLIB_DHT_UNI_WAKEUP 18
#define DHT_DEBUG
// max timeout is 100 usec. // max timeout is 100 usec.
// For a 16 Mhz proc 100 usec is 1600 clock cycles // For a 16 Mhz proc 100 usec is 1600 clock cycles
// loops using DHTLIB_TIMEOUT use at least 4 clock cycli // loops using DHTLIB_TIMEOUT use at least 4 clock cycli
@ -48,19 +46,18 @@
#define DIRECT_WRITE_LOW(pin) (GPIO_OUTPUT_SET(GPIO_ID_PIN(pin_num[pin]), 0)) #define DIRECT_WRITE_LOW(pin) (GPIO_OUTPUT_SET(GPIO_ID_PIN(pin_num[pin]), 0))
#define DIRECT_WRITE_HIGH(pin) (GPIO_OUTPUT_SET(GPIO_ID_PIN(pin_num[pin]), 1)) #define DIRECT_WRITE_HIGH(pin) (GPIO_OUTPUT_SET(GPIO_ID_PIN(pin_num[pin]), 1))
typedef enum {
DHT11 = 0,
DHT12,
DHT22,
DHT_NON11
} dht_type;
// return values: // return values:
// DHTLIB_OK // DHTLIB_OK
// DHTLIB_ERROR_CHECKSUM // DHTLIB_ERROR_CHECKSUM
// DHTLIB_ERROR_TIMEOUT // DHTLIB_ERROR_TIMEOUT
int dht_read_universal(uint8_t pin); int dht_read(uint8_t pin, dht_type type);
int dht_read11(uint8_t pin);
int dht_read(uint8_t pin);
int dht_read21(uint8_t pin);
int dht_read22(uint8_t pin);
int dht_read33(uint8_t pin);
int dht_read44(uint8_t pin);
double dht_getHumidity(void); double dht_getHumidity(void);
double dht_getTemperature(void); double dht_getTemperature(void);

View File

@ -32,7 +32,7 @@ static int dht_lapi_read( lua_State *L )
{ {
unsigned id = luaL_checkinteger( L, 1 ); unsigned id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( dht, id ); MOD_CHECK_ID( dht, id );
lua_pushinteger( L, dht_read_universal(id) ); lua_pushinteger( L, dht_read(id, DHT_NON11) );
aux_read( L ); aux_read( L );
return 5; return 5;
} }
@ -42,7 +42,17 @@ static int dht_lapi_read11( lua_State *L )
{ {
unsigned id = luaL_checkinteger( L, 1 ); unsigned id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( dht, id ); MOD_CHECK_ID( dht, id );
lua_pushinteger( L, dht_read11(id) ); lua_pushinteger( L, dht_read(id, DHT11) );
aux_read( L );
return 5;
}
// Lua: status, temp, humi, tempdec, humidec = dht.read12( id ))
static int dht_lapi_read12( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( dht, id );
lua_pushinteger( L, dht_read(id, DHT12) );
aux_read( L ); aux_read( L );
return 5; return 5;
} }
@ -52,48 +62,17 @@ static int dht_lapi_readxx( lua_State *L )
{ {
unsigned id = luaL_checkinteger( L, 1 ); unsigned id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( dht, id ); MOD_CHECK_ID( dht, id );
lua_pushinteger( L, dht_read(id) ); lua_pushinteger( L, dht_read(id, DHT22) );
aux_read( L ); aux_read( L );
return 5; return 5;
} }
// // Lua: result = dht.humidity()
// static int dht_lapi_humidity( lua_State *L )
// {
// lua_pushnumber( L, dht_getHumidity() );
// return 1;
// }
// // Lua: result = dht.humiditydecimal()
// static int dht_lapi_humiditydecimal( lua_State *L )
// {
// double value = dht_getHumidity();
// int result = (int)((value - (int)value) * 1000);
// lua_pushnumber( L, result );
// return 1;
// }
// // Lua: result = dht.temperature()
// static int dht_lapi_temperature( lua_State *L )
// {
// lua_pushnumber( L, dht_getTemperature() );
// return 1;
// }
// // Lua: result = dht.temperaturedecimal()
// static int dht_lapi_temperaturedecimal( lua_State *L )
// {
// double value = dht_getTemperature();
// int result = (int)((value - (int)value) * 1000);
// lua_pushnumber( L, result );
// return 1;
// }
// Module function map // Module function map
LROT_BEGIN(dht, NULL, 0) LROT_BEGIN(dht, NULL, 0)
LROT_FUNCENTRY( read, dht_lapi_read ) LROT_FUNCENTRY( read, dht_lapi_read )
LROT_FUNCENTRY( read11, dht_lapi_read11 ) LROT_FUNCENTRY( read11, dht_lapi_read11 )
LROT_FUNCENTRY( readxx, dht_lapi_readxx ) LROT_FUNCENTRY( read12, dht_lapi_read12 )
LROT_FUNCENTRY( readxx, dht_lapi_read )
LROT_NUMENTRY( OK, DHTLIB_OK ) LROT_NUMENTRY( OK, DHTLIB_OK )
LROT_NUMENTRY( ERROR_CHECKSUM, DHTLIB_ERROR_CHECKSUM ) LROT_NUMENTRY( ERROR_CHECKSUM, DHTLIB_ERROR_CHECKSUM )
LROT_NUMENTRY( ERROR_TIMEOUT, DHTLIB_ERROR_TIMEOUT ) LROT_NUMENTRY( ERROR_TIMEOUT, DHTLIB_ERROR_TIMEOUT )

View File

@ -9,7 +9,8 @@ Constants for various functions.
`dht.OK`, `dht.ERROR_CHECKSUM`, `dht.ERROR_TIMEOUT` represent the potential values for the DHT read status `dht.OK`, `dht.ERROR_CHECKSUM`, `dht.ERROR_TIMEOUT` represent the potential values for the DHT read status
## dht.read() ## dht.read()
Read all kinds of DHT sensors, including DHT11, 21, 22, 33, 44 humidity temperature combo sensor. Reads all kinds of DHT sensors, including DHT11, 21, 22, 33, 44 humidity temperature combo sensor.
Returns correct readout except for DHT12 and negative temperatures by DHT11. Use [`dht.read12()`](#dhtread12) and [`dht.read11()`](#dhtread11) instead. It is to use model specific read function anyway.
#### Syntax #### Syntax
`dht.read(pin)` `dht.read(pin)`
@ -74,8 +75,32 @@ Read DHT11 humidity temperature combo sensor.
#### See also #### See also
[dht.read()](#dhtread) [dht.read()](#dhtread)
## dht.read12()
Read DHT12 humidity temperature combo sensor.
#### Syntax
`dht.read12(pin)`
#### Parameters
`pin` pin number of DHT12 sensor (can't be 0), type is number
#### Returns
- `status` as defined in Constants
- `temp` temperature (see note below)
- `humi` humidity (see note below)
- `temp_dec` temperature decimal
- `humi_dec` humidity decimal
!!! note
If using float firmware then `temp` and `humi` are floating point numbers. On an integer firmware, the final values have to be concatenated from `temp` and `temp_dec` / `humi` and `hum_dec`.
#### See also
[dht.read()](#dhtread)
## dht.readxx() ## dht.readxx()
Read all kinds of DHT sensors, except DHT11. Read all kinds of DHT sensors, except DHT11 and DHT12. Differs from `dht.read()` only by waiting only sufficient 1 ms for sensor wake-up while `dht.read()` waits universal 18 ms.
####Syntax ####Syntax
`dht.readxx(pin)` `dht.readxx(pin)`