Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bugfix] Refracture of not working dht.c Example #440

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
215 changes: 167 additions & 48 deletions gpio/dht_sensor/dht.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,80 +13,199 @@
#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();
gpio_init(DHT_PIN);
gpio_pull_up(DHT_PIN);
#ifdef LED_PIN
gpio_init(LED_PIN);
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) {
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;
}
// ==> 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 = (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;
}
#ifdef LED_PIN
gpio_put(LED_PIN, 0);
#endif
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");
}