#include "dht22.h" #include "esp_log.h" #include "hal/gpio_types.h" #include "sdkconfig.h" #include "driver/gpio.h" #include #include "esp_timer.h" #include "freertos/portmacro.h" #define DATA_GPIO CONFIG_DHT22_DATA_GPIO #if DATA_GPIO == -1 #error "Please define your DHT22 GPIO Data Pin" #endif /* CONFIG_DHT22_DATA_GPIO == -1 */ static const char *TAG = "DHT22"; deci_percent _dht22_relative_humidity = UINT16_MAX; deci_degrees_c _dht22_temperature = INT16_MIN; void dht22_handle_error(dht22_error e) { if (e == DHT22_OK) { ESP_LOGI(TAG, "No errors reading DHT22 value"); } else if (e == DHT22_CHECKSUM_ERROR) { ESP_LOGE(TAG, "Error calculating checksum"); } else if (e == DHT22_TIMING_ERROR) { ESP_LOGE(TAG, "Timing error while obtaining data"); } } dht22_error dht22_read() { uint8_t data[5] = {0}; uint32_t tick_total = 0; /* * From datasheet: * - Host pulls low "beyond at least 1ms" * - Host pulls up 20us to 40us */ gpio_set_direction(CONFIG_DHT22_DATA_GPIO, GPIO_MODE_OUTPUT); gpio_set_level(CONFIG_DHT22_DATA_GPIO, 0); ets_delay_us(5000); gpio_set_level(CONFIG_DHT22_DATA_GPIO, 1); ets_delay_us(25); /* * From datasheet: * - DHT pulls low 80us * - DHT pulls high 80us */ gpio_set_direction(CONFIG_DHT22_DATA_GPIO, GPIO_MODE_INPUT); // Maybe wait here until it goes high? while (gpio_get_level(CONFIG_DHT22_DATA_GPIO) == 1) { // wait for a while - should only be 20 uS } uint64_t start_time = esp_timer_get_time(); while (gpio_get_level(CONFIG_DHT22_DATA_GPIO) == 0) { tick_total += 1; if (tick_total == UINT32_MAX - 1) { return DHT22_TIMING_ERROR; } } uint64_t next_time = esp_timer_get_time(); uint32_t elapsed_time = next_time - start_time; if (elapsed_time < 75 || elapsed_time > 85) { return DHT22_TIMING_ERROR; } tick_total = 0; start_time = esp_timer_get_time(); while (gpio_get_level(CONFIG_DHT22_DATA_GPIO) == 0) { tick_total += 1; if (tick_total == UINT32_MAX - 1) { return DHT22_TIMING_ERROR; } } next_time = esp_timer_get_time(); elapsed_time = next_time - start_time; portENABLE_INTERRUPTS(); ESP_LOGW(TAG, "etime: %lu", elapsed_time); if (elapsed_time < 70 || elapsed_time > 90) { return DHT22_TIMING_ERROR; } // TODO test that data[x] << 8 will be promoted to 16bits otherwise I'm // shifting them to just zeros _dht22_relative_humidity = data[0] << 8 | data[1]; _dht22_temperature = (data[2] & 0x7f) << 8 | data[3]; if (data[2] & 0x80) { _dht22_temperature = -1 * _dht22_temperature; } uint8_t checksum_val = (data[0] + data[1] + data[2] + data[3]) & 0xff; if (checksum_val != data[4]) { _dht22_relative_humidity = UINT16_MAX; _dht22_temperature = INT16_MIN; return DHT22_CHECKSUM_ERROR; } return DHT22_OK; } deci_percent dht22_relative_humidity() { return _dht22_relative_humidity; } deci_degrees_c dht22_temperature() { return _dht22_temperature; }