From c7b50cdf5b4a4354d26e9d3c464a33ae974fd1e2 Mon Sep 17 00:00:00 2001 From: Hasenradball Date: Wed, 29 Nov 2023 22:30:54 +0100 Subject: [PATCH 1/5] refracture not working dht.c example - refracture dht.c example - improve functionality --- gpio/dht_sensor/dht.c | 205 ++++++++++++++++++++++++++++++++---------- 1 file changed, 156 insertions(+), 49 deletions(-) diff --git a/gpio/dht_sensor/dht.c b/gpio/dht_sensor/dht.c index c9ce8748c..259d05330 100644 --- a/gpio/dht_sensor/dht.c +++ b/gpio/dht_sensor/dht.c @@ -13,15 +13,26 @@ #define LED_PIN PICO_DEFAULT_LED_PIN #endif -const uint DHT_PIN = 15; -const uint MAX_TIMINGS = 85; - -typedef struct { +// Data memory +struct DHT_Data { float humidity; float temp_celsius; -} dht_reading; +}; + +// forward declarations +int8_t await_state(uint8_t state); +int8_t read_sensor_data(uint8_t *buffer, uint8_t size); +int8_t read_from_dht(struct DHT_Data *result); +void print_byte_as_bit(char value); -void read_from_dht(dht_reading *result); +// define constants +const int8_t SENSOR_READ_OK = 0; +const int8_t SENSOR_ERROR_CHECKSUM = -1; +const int8_t SENSOR_ERROR_TIMEOUT = -2; +const uint8_t READ_TIMEOUT = 100U; + +// DHT Pin +const uint DHT_PIN = 15; int main() { stdio_init_all(); @@ -30,63 +41,159 @@ int main() { gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); #endif + printf("\n\n === Pi Pico Example - Read DHTxx-Sensor === \n\n"); + while (1) { - dht_reading reading; - read_from_dht(&reading); - float fahrenheit = (reading.temp_celsius * 9 / 5) + 32; - printf("Humidity = %.1f%%, Temperature = %.1fC (%.1fF)\n", - reading.humidity, reading.temp_celsius, fahrenheit); - sleep_ms(2000); +#ifdef LED_PIN + gpio_put(LED_PIN, 1); +#endif + struct DHT_Data dht_data; + int8_t status = read_from_dht(&dht_data); + +#ifdef LED_PIN + gpio_put(LED_PIN, 0); +#endif + + printf("Sensor-status: %d\n", status); + + if (status == SENSOR_READ_OK) { + float fahrenheit = (dht_data.temp_celsius * 9 / 5) + 32; + printf("Humidity = %.1f %%\tTemperature = %.1f degC (%.1f F)\n", + dht_data.humidity, dht_data.temp_celsius, fahrenheit); + } + else { + if (status == SENSOR_ERROR_CHECKSUM) { + printf("ERROR: Checksum not valid\n"); + } + else if (status == SENSOR_ERROR_TIMEOUT) { + printf("ERROR: Timeout overflow\n"); + } + } + printf("\n\n"); + sleep_ms(5000); } } -void read_from_dht(dht_reading *result) { - int data[5] = {0, 0, 0, 0, 0}; - uint last = 1; - uint j = 0; - +int8_t read_from_dht(struct DHT_Data *result) { gpio_set_dir(DHT_PIN, GPIO_OUT); + // start sequence min. 1 ms low then high gpio_put(DHT_PIN, 0); - sleep_ms(20); + sleep_us(1200U); + gpio_put(DHT_PIN, 1); gpio_set_dir(DHT_PIN, GPIO_IN); -#ifdef LED_PIN - gpio_put(LED_PIN, 1); -#endif - for (uint i = 0; i < MAX_TIMINGS; i++) { - uint count = 0; - while (gpio_get(DHT_PIN) == last) { - count++; - sleep_us(1); - if (count == 255) break; - } - last = gpio_get(DHT_PIN); - if (count == 255) break; + // await for the Acknowledge sequence + // wait for 80 µs lOW + await_state(0); + // wait for 80 µs HIGH + await_state(1); - if ((i >= 4) && (i % 2 == 0)) { - data[j / 8] <<= 1; - if (count > 16) data[j / 8] |= 1; - j++; - } + // Now read Sensor data + // start of time critical code + // create buffer + uint8_t data[5U] = {0}; + if (read_sensor_data(data, 5U) == SENSOR_ERROR_TIMEOUT) { + return SENSOR_ERROR_TIMEOUT; } -#ifdef LED_PIN - gpio_put(LED_PIN, 0); -#endif + // ==> END of time critical code <== + // check checksum + int8_t _checksum_ok = (data[4] == ( (data[0] + data[1] + data[2] + data[3]) & 0xFF) ); + //printf("Checksum_ok: %d\n", _checksum_ok); + + /* + // Code part to check the checksum + // Due to older sensors have an bug an deliver wrong data + int8_t d4 = data[4]; + int8_t cs = ( (data[0] + data[1] + data[2] + data[3]) & 0xFF); + printf("delivered Checksum: %d - ", d4); + print_byte_as_bit(d4); + printf("calculated Checksum: %d - ", cs); + print_byte_as_bit(cs); + */ + + if (_checksum_ok) { + uint16_t hum = (data[0] << 8) | data[1]; + int16_t temp = (data[2] << 8) | data[3]; + result->humidity = hum * 0.1F; + result->temp_celsius = temp * 0.1F; + return SENSOR_READ_OK; + } + else { + return SENSOR_ERROR_CHECKSUM; + } +} - if ((j >= 40) && (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF))) { - result->humidity = (float) ((data[0] << 8) + data[1]) / 10; - if (result->humidity > 100) { - result->humidity = data[0]; +/** + * @brief wait for given state + * + * @param state + * @return int8_t state to wait for + */ +int8_t await_state(uint8_t state) { + uint8_t wait_counter = 0, state_counter = 0; + // count wait for state time + while ( (gpio_get(DHT_PIN) != state) ) { + ++wait_counter; + sleep_us(1U); + if (wait_counter >= READ_TIMEOUT) { + return SENSOR_ERROR_TIMEOUT; } - result->temp_celsius = (float) (((data[2] & 0x7F) << 8) + data[3]) / 10; - if (result->temp_celsius > 125) { - result->temp_celsius = data[2]; + } + // count state time + while ( (gpio_get(DHT_PIN) == state) ) { + ++state_counter; + sleep_us(1U); + if (state_counter >= READ_TIMEOUT) { + return SENSOR_ERROR_TIMEOUT; } - if (data[2] & 0x80) { - result->temp_celsius = -result->temp_celsius; + } + return (state_counter > wait_counter); +} + +/** + * @brief read sensor data + * + * @param buffer data buffer of 40 bit + * @param size of buffer => 5 Byte + * @return int8_t + */ +int8_t read_sensor_data(uint8_t *buffer, uint8_t size) { + for (uint8_t i = 0; i < size; ++i) { + for (uint8_t bit = 0; bit < 8; ++bit) { + uint8_t wait_counter = 0, state_counter = 0; + // count wait for state time + while ( !gpio_get(DHT_PIN) ) { + ++wait_counter; + sleep_us(1U); + if (wait_counter >= READ_TIMEOUT) { + return SENSOR_ERROR_TIMEOUT; + } + } + // count state time + while ( gpio_get(DHT_PIN) ) { + ++state_counter; + sleep_us(1U); + if (state_counter >= READ_TIMEOUT) { + return SENSOR_ERROR_TIMEOUT; + } + } + buffer[i] <<= 1; + buffer[i] |= (state_counter > wait_counter); } - } else { - printf("Bad data\n"); } + return SENSOR_READ_OK; +} + +/** + * @brief helper function to print byte as bit + * + * @param value byte with 8 bits + */ +void print_byte_as_bit(char value) { + for (int i = 7; i >= 0; --i) { + char c = (value & (1 << i)) ? '1' : '0'; + printf("%c", c); + } + printf("\n"); } From baddb8d18f9c4254b86ac5c44e65fba95b9c888d Mon Sep 17 00:00:00 2001 From: Hasenradball Date: Sun, 3 Dec 2023 22:17:47 +0100 Subject: [PATCH 2/5] Update dht.c - fix for negative temperature detection --- gpio/dht_sensor/dht.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/gpio/dht_sensor/dht.c b/gpio/dht_sensor/dht.c index 259d05330..23b74fe0f 100644 --- a/gpio/dht_sensor/dht.c +++ b/gpio/dht_sensor/dht.c @@ -113,8 +113,17 @@ int8_t read_from_dht(struct DHT_Data *result) { */ if (_checksum_ok) { - uint16_t hum = (data[0] << 8) | data[1]; - int16_t temp = (data[2] << 8) | data[3]; + uint16_t hum = (uint16_t)((data[0] << 8) | data[1]); + // check now if temperature is smaller than zero + int16_t temp {0}; + if (data[2] & 0x80) { + // found negative Temperature + data[2] &= 0x7f; + temp = -(int16_t)((data[2] << 8) | data[3]); + } + else { + temp = (int16_t)((data[2] << 8) | data[3]); + } result->humidity = hum * 0.1F; result->temp_celsius = temp * 0.1F; return SENSOR_READ_OK; From 814bd09327c297796e73a911de1eb325eb2a4ee0 Mon Sep 17 00:00:00 2001 From: Hasenradball Date: Sat, 9 Dec 2023 18:30:47 +0100 Subject: [PATCH 3/5] Update dht.c - correction into c style initialisation (line 118) --- gpio/dht_sensor/dht.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gpio/dht_sensor/dht.c b/gpio/dht_sensor/dht.c index 23b74fe0f..6efa2888e 100644 --- a/gpio/dht_sensor/dht.c +++ b/gpio/dht_sensor/dht.c @@ -115,7 +115,7 @@ int8_t read_from_dht(struct DHT_Data *result) { if (_checksum_ok) { uint16_t hum = (uint16_t)((data[0] << 8) | data[1]); // check now if temperature is smaller than zero - int16_t temp {0}; + int16_t temp = 0; if (data[2] & 0x80) { // found negative Temperature data[2] &= 0x7f; From 10d4451d3f135ed25f2fcb6353c9a872017158e0 Mon Sep 17 00:00:00 2001 From: Hasenradball Date: Fri, 15 Dec 2023 21:07:59 +0100 Subject: [PATCH 4/5] add power up time - add power up time for sensor to reach stable state --- gpio/dht_sensor/dht.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gpio/dht_sensor/dht.c b/gpio/dht_sensor/dht.c index 6efa2888e..c5de03f16 100644 --- a/gpio/dht_sensor/dht.c +++ b/gpio/dht_sensor/dht.c @@ -42,6 +42,8 @@ int main() { gpio_set_dir(LED_PIN, GPIO_OUT); #endif printf("\n\n === Pi Pico Example - Read DHTxx-Sensor === \n\n"); + // wait min. 2 s to power up the sensor (see darasheet) + sleep_ms(2000); while (1) { From f3b139f6bc68fb3fd4a41df294c05dce125e9083 Mon Sep 17 00:00:00 2001 From: hasenradball Date: Thu, 25 Apr 2024 16:43:56 +0200 Subject: [PATCH 5/5] set pull up => making work without HW PullUp --- gpio/dht_sensor/dht.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gpio/dht_sensor/dht.c b/gpio/dht_sensor/dht.c index c5de03f16..00683c50e 100644 --- a/gpio/dht_sensor/dht.c +++ b/gpio/dht_sensor/dht.c @@ -37,6 +37,7 @@ const uint DHT_PIN = 15; int main() { stdio_init_all(); gpio_init(DHT_PIN); + gpio_pull_up(DHT_PIN); #ifdef LED_PIN gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT);