DHT22 not working with ESP32-C3

chirmac
Posts: 1
Joined: Mon Nov 14, 2022 11:46 pm

DHT22 not working with ESP32-C3

Postby chirmac » Mon Nov 14, 2022 11:51 pm

I've been trying to make a temperature sensor based on the ESP32-C3-DevKitM-1 and using a driver from GitHub. I already tried 2 and both timeout trying to read from the sensor. Once I plug it into an Arduino, with the same pin configuration, it works.

I'm connecting the sensor's Vcc -> 5V / GND -> GND / OUT -> GPIO4
With a 1K pull up resistor.

The current driver is as follows:
  1. /*
  2.  * Copyright (c) 2016 Jonathan Hartsuiker <https://github.com/jsuiker>
  3.  * Copyright (c) 2018 Ruslan V. Uss <unclerus@gmail.com>
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions are met:
  7.  *
  8.  * 1. Redistributions of source code must retain the above copyright notice,
  9.  *    this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright notice,
  11.  *    this list of conditions and the following disclaimer in the documentation
  12.  *    and/or other materials provided with the distribution.
  13.  * 3. Neither the name of the copyright holder nor the names of itscontributors
  14.  *    may be used to endorse or promote products derived from this software without
  15.  *    specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  18.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20.  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  21.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  23.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  25.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  26.  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /**
  30.  * @file dht.c
  31.  *
  32.  * ESP-IDF driver for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321), Itead Si7021
  33.  *
  34.  * Ported from esp-open-rtos
  35.  *
  36.  * Copyright (c) 2016 Jonathan Hartsuiker <https://github.com/jsuiker>\n
  37.  * Copyright (c) 2018 Ruslan V. Uss <unclerus@gmail.com>\n
  38.  *
  39.  * BSD Licensed as described in the file LICENSE
  40.  */
  41. #include "dht.h"
  42.  
  43. #include <freertos/FreeRTOS.h>
  44. #include <string.h>
  45. #include <esp_log.h>
  46. #include <ets_sys.h>
  47. #include <esp_idf_lib_helpers.h>
  48.  
  49. // DHT timer precision in microseconds
  50. #define DHT_TIMER_INTERVAL 2
  51. #define DHT_DATA_BITS 40
  52. #define DHT_DATA_BYTES (DHT_DATA_BITS / 8)
  53.  
  54. /*
  55.  *  Note:
  56.  *  A suitable pull-up resistor should be connected to the selected GPIO line
  57.  *
  58.  *  __           ______          _______                              ___________________________
  59.  *    \    A    /      \   C    /       \   DHT duration_data_low    /                           \
  60.  *     \_______/   B    \______/    D    \__________________________/   DHT duration_data_high    \__
  61.  *
  62.  *
  63.  *  Initializing communications with the DHT requires four 'phases' as follows:
  64.  *
  65.  *  Phase A - MCU pulls signal low for at least 18000 us
  66.  *  Phase B - MCU allows signal to float back up and waits 20-40us for DHT to pull it low
  67.  *  Phase C - DHT pulls signal low for ~80us
  68.  *  Phase D - DHT lets signal float back up for ~80us
  69.  *
  70.  *  After this, the DHT transmits its first bit by holding the signal low for 50us
  71.  *  and then letting it float back high for a period of time that depends on the data bit.
  72.  *  duration_data_high is shorter than 50us for a logic '0' and longer than 50us for logic '1'.
  73.  *
  74.  *  There are a total of 40 data bits transmitted sequentially. These bits are read into a byte array
  75.  *  of length 5.  The first and third bytes are humidity (%) and temperature (C), respectively.  Bytes 2 and 4
  76.  *  are zero-filled and the fifth is a checksum such that:
  77.  *
  78.  *  byte_5 == (byte_1 + byte_2 + byte_3 + byte_4) & 0xFF
  79.  *
  80.  */
  81.  
  82. static const char *TAG = "dht";
  83.  
  84. #if HELPER_TARGET_IS_ESP32
  85. static portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
  86. #define PORT_ENTER_CRITICAL() portENTER_CRITICAL(&mux)
  87. #define PORT_EXIT_CRITICAL() portEXIT_CRITICAL(&mux)
  88.  
  89. #elif HELPER_TARGET_IS_ESP8266
  90. #define PORT_ENTER_CRITICAL() portENTER_CRITICAL()
  91. #define PORT_EXIT_CRITICAL() portEXIT_CRITICAL()
  92. #endif
  93.  
  94. #define CHECK_ARG(VAL) do { if (!(VAL)) return ESP_ERR_INVALID_ARG; } while (0)
  95.  
  96. #define CHECK_LOGE(x, msg, ...) do { \
  97.         esp_err_t __; \
  98.         if ((__ = x) != ESP_OK) { \
  99.             PORT_EXIT_CRITICAL(); \
  100.             ESP_LOGE(TAG, msg, ## __VA_ARGS__); \
  101.             return __; \
  102.         } \
  103.     } while (0)
  104.  
  105.  
  106. /**
  107.  * Wait specified time for pin to go to a specified state.
  108.  * If timeout is reached and pin doesn't go to a requested state
  109.  * false is returned.
  110.  * The elapsed time is returned in pointer 'duration' if it is not NULL.
  111.  */
  112. static esp_err_t dht_await_pin_state(gpio_num_t pin, uint32_t timeout,
  113.        int expected_pin_state, uint32_t *duration)
  114. {
  115.     /* XXX dht_await_pin_state() should save pin direction and restore
  116.      * the direction before return. however, the SDK does not provide
  117.      * gpio_get_direction().
  118.      */
  119.     gpio_set_direction(pin, GPIO_MODE_INPUT);
  120.     for (uint32_t i = 0; i < timeout; i += DHT_TIMER_INTERVAL)
  121.     {
  122.         // need to wait at least a single interval to prevent reading a jitter
  123.         ets_delay_us(DHT_TIMER_INTERVAL);
  124.         if (gpio_get_level(pin) == expected_pin_state)
  125.         {
  126.             if (duration)
  127.                 *duration = i;
  128.             return ESP_OK;
  129.         }
  130.     }
  131.  
  132.     return ESP_ERR_TIMEOUT;
  133. }
  134.  
  135. /**
  136.  * Request data from DHT and read raw bit stream.
  137.  * The function call should be protected from task switching.
  138.  * Return false if error occurred.
  139.  */
  140. static inline esp_err_t dht_fetch_data(dht_sensor_type_t sensor_type, gpio_num_t pin, uint8_t data[DHT_DATA_BYTES])
  141. {
  142.     uint32_t low_duration;
  143.     uint32_t high_duration;
  144.  
  145.     // Phase 'A' pulling signal low to initiate read sequence
  146.     gpio_set_direction(pin, GPIO_MODE_OUTPUT_OD);
  147.     gpio_set_level(pin, 0);
  148.     ets_delay_us(sensor_type == DHT_TYPE_SI7021 ? 500 : 20000);
  149.     gpio_set_level(pin, 1);
  150.  
  151.     // Step through Phase 'B', 40us
  152.     CHECK_LOGE(dht_await_pin_state(pin, 40, 0, NULL),
  153.             "Initialization error, problem in phase 'B'");
  154.     // Step through Phase 'C', 88us
  155.     CHECK_LOGE(dht_await_pin_state(pin, 88, 1, NULL),
  156.             "Initialization error, problem in phase 'C'");
  157.     // Step through Phase 'D', 88us
  158.     CHECK_LOGE(dht_await_pin_state(pin, 88, 0, NULL),
  159.             "Initialization error, problem in phase 'D'");
  160.  
  161.     // Read in each of the 40 bits of data...
  162.     for (int i = 0; i < DHT_DATA_BITS; i++)
  163.     {
  164.         CHECK_LOGE(dht_await_pin_state(pin, 65, 1, &low_duration),
  165.                 "LOW bit timeout");
  166.         CHECK_LOGE(dht_await_pin_state(pin, 75, 0, &high_duration),
  167.                 "HIGH bit timeout");
  168.  
  169.         uint8_t b = i / 8;
  170.         uint8_t m = i % 8;
  171.         if (!m)
  172.             data[b] = 0;
  173.  
  174.         data[b] |= (high_duration > low_duration) << (7 - m);
  175.     }
  176.  
  177.     return ESP_OK;
  178. }
  179.  
  180. /**
  181.  * Pack two data bytes into single value and take into account sign bit.
  182.  */
  183. static inline int16_t dht_convert_data(dht_sensor_type_t sensor_type, uint8_t msb, uint8_t lsb)
  184. {
  185.     int16_t data;
  186.  
  187.     if (sensor_type == DHT_TYPE_DHT11)
  188.     {
  189.         data = msb * 10;
  190.     }
  191.     else
  192.     {
  193.         data = msb & 0x7F;
  194.         data <<= 8;
  195.         data |= lsb;
  196.         if (msb & BIT(7))
  197.             data = -data;       // convert it to negative
  198.     }
  199.  
  200.     return data;
  201. }
  202.  
  203. esp_err_t dht_read_data(dht_sensor_type_t sensor_type, gpio_num_t pin,
  204.         int16_t *humidity, int16_t *temperature)
  205. {
  206.     CHECK_ARG(humidity || temperature);
  207.  
  208.     uint8_t data[DHT_DATA_BYTES] = { 0 };
  209.  
  210.     gpio_set_direction(pin, GPIO_MODE_OUTPUT_OD);
  211.     gpio_set_level(pin, 1);
  212.  
  213.     PORT_ENTER_CRITICAL();
  214.     esp_err_t result = dht_fetch_data(sensor_type, pin, data);
  215.     if (result == ESP_OK)
  216.         PORT_EXIT_CRITICAL();
  217.  
  218.     /* restore GPIO direction because, after calling dht_fetch_data(), the
  219.      * GPIO direction mode changes */
  220.     gpio_set_direction(pin, GPIO_MODE_OUTPUT_OD);
  221.     gpio_set_level(pin, 1);
  222.  
  223.     if (result != ESP_OK)
  224.         return result;
  225.  
  226.     if (data[4] != ((data[0] + data[1] + data[2] + data[3]) & 0xFF))
  227.     {
  228.         ESP_LOGE(TAG, "Checksum failed, invalid data received from sensor");
  229.         return ESP_ERR_INVALID_CRC;
  230.     }
  231.  
  232.     if (humidity)
  233.         *humidity = dht_convert_data(sensor_type, data[0], data[1]);
  234.     if (temperature)
  235.         *temperature = dht_convert_data(sensor_type, data[2], data[3]);
  236.  
  237.     ESP_LOGD(TAG, "Sensor data: humidity=%d, temp=%d", *humidity, *temperature);
  238.  
  239.     return ESP_OK;
  240. }
  241.  
  242. esp_err_t dht_read_float_data(dht_sensor_type_t sensor_type, gpio_num_t pin,
  243.         float *humidity, float *temperature)
  244. {
  245.     CHECK_ARG(humidity || temperature);
  246.  
  247.     int16_t i_humidity, i_temp;
  248.  
  249.     esp_err_t res = dht_read_data(sensor_type, pin, humidity ? &i_humidity : NULL, temperature ? &i_temp : NULL);
  250.     if (res != ESP_OK)
  251.         return res;
  252.  
  253.     if (humidity)
  254.         *humidity = i_humidity / 10.0;
  255.     if (temperature)
  256.         *temperature = i_temp / 10.0;
  257.  
  258.     return ESP_OK;
  259. }
  260.  
It always timesout on Phase B.
I don't get what I'm doing wrong and would really appreciate the help.

posteego
Posts: 1
Joined: Fri Jun 28, 2024 7:26 pm

Re: DHT22 not working with ESP32-C3

Postby posteego » Fri Jun 28, 2024 7:59 pm

from my experience, the DHT Phase B error comes from improper initialization due to potential interference coming from the GPIO pin.

I was initially using a GPIO pin on an ESP32-CAM that initialized to LOW at first, and was getting the Phase B issue.
After switching to another pin that initialized to HIGH, the DHT sensor worked for me and was giving me accurate readings.

As a side note, Phase C issues from the DHT sensors may be due to faulty wiring.

Who is online

Users browsing this forum: No registered users and 73 guests