Even though the DHT-22 is a sensor used to determine air temperature and relative humidity, what it actually measures are resistances and capacitances which are affected by temperature and humidity of the air, respectively. The DHT-22 combines two different sensors and a little circuit board in one device. The circuit board does calculations and also converts the analog output from the sensors to a digital output signal which can be read from the DHT-22 Data-pin using, for example, the Adafruit DHT sensor library.
In the monitoring station, the DHT-22 will be used to keep track of the air temperature and relative humidity at the pond bank. The collected data will then be transmitted using WiFi to an MQTT Broker.
The first sensor is the temperature sensor which mainly consists of a thermistor, a thermally sensitive resistor. In figure 1, the thermistor is visible in the middle photo underneath the grid of the white casing in the top right. There are two different types of thermistors: NTC thermistors (NTC- Negative Temperature Coefficient) conduct electricity better the higher the temperature, that means their resistance decreases with increasing temperature, typically at a rate of 3 to 6% per °K. The second type of thermistors are PTC thermistors (PTC – Positive Temperature Gradient) whose resistance increases with increasing temperature. Both types can be used in different applications, for example to prevent peak currents, or limit the current during continuous operation. Because the change in resistance due a change in temperature is predictable and reproducible, they are well suited for measuring the temperature.
The second sensor is the capacitive humidity sensor which is used for determining the relative humidity of the air. The sensor consists of a capacitor which uses the air between the contacts as a dielectric. The dielectric of a capacitor isolates the cathode and the anode from each other. The capacitance of the capacitor with vacuum as a dielectric is denoted as $C_0$. The dielectric constant $\kappa$ of a material is the ratio of the capacitance $C$ with the material as dielectric to $C_0$, so $\kappa=C/C_0$ or the ratio of the Electric field strength between anode and cathode in vacuum to the electric field strength with the dielectric $\kappa=E_0/E$. That means for vacuum $\kappa$ equals 1, and the dielectric constant for any material is greater than that. For dry air, the dielectric constant equals 1.00059, which is close to vacuum, so the capacitance is almost the same as in vacuum when the air is dry. For water, the dielectric constant equals approximately 80. With increasing moisture, the dielectric constant of the air increases, which also increases the capacitance of the capacitor. When the sensor is calibrated correctly, it is possible to assign a certain value for the actual vapor density of the air to a certain value of the capacitance. The relative humidity is the ratio of the actual vapor density to the saturation vapor density in percent. The saturation vapor density increases exponentially with increasing temperature. To calculate the relative humidity, it is thus necessary to also measure the temperature to obtain the current saturation vapor density of the air. In the DHT-22, temperature compensation technology is applied to account for the change in saturation vapor density due to temperature changes to give as accurate results for the relative humidity as possible.
The communication between the DHT-22 and the microcontroller (MCU) occurs only via the 1-Wire data-bus connecting an MCU-pin and the Data-pin (Pin 2 in figure 1) of the DHT-22. The 1-Wire bus for the DHT-22 is specifically designed for DHT-xx sensors and is not compatible with the Dallas 1-wire bus used for the DS18B20 temperature sensors. In fact, the data-bus allows only the connection of 1 DHT-22 with an MCU. This is the case because, in this system, the sensors do not have individual addresses, like in the Dallas 1-Wire data-bus or in an I²C-bus. Connecting multiple DHT sensors with one data-bus, will result in all the sensors sending and occupying the only available connection at once, making data transmission impossible. The communication follows a fixed protocol which can be seen in figure 2 below:
During the seven steps, indicated in figure 2, the following happens:
As mentioned before, the data that is transmitted consists of 40 bits. 2 bytes for the relative humidity, 2 bytes for the temperature and 1 byte (check-sum) to check for finding errors in the transmission. The principle becomes clearer when looking at an example transmission:
$\mathrm{0000\; 0010\; 1000\; 1100\;\; 0000\; 0001\; 0101\; 1111\;\; 1110\; 1110}$
Humidity (1) | Temperature (2) | Check-sum (3)
The DHT-22 comes with 4 pins and can be plugged into a breadboard. Pin 1 (VDD) is connected to the power supply, pin 2 (DATA) is the 1-wire data-bus and is connected to GPIO 15, pin 3 (NC) is not connected, and pin 4 (GND) is connected to 0 Volts (figure 3). Information on the technical specifications can be found in table 1.
Table 1 Technical specifications, sensor accuracy and ranges | ||
---|---|---|
Model | AM3202 | |
Power Supply | 3.3 - 5.5 V DC | |
Current (3.3V) | Measuring: 1mA | Stand-by: 50μA |
Power Consumption (3.3V) | Measuring: 3.3 mW | Stand-by: 0.165mW |
Output signal | Digital signal using a 1-wire bus | |
Sensing element | Polymer humidity capacitor | Thermistor |
Operating range | 0 - 100 % RH | -40 - 80 °C |
Accuracy | $\pm$ 2 % RH | $\pm$ 0.5 °C |
Resolution/sensitivity | 0.1 % RH | 0.1 °C |
Repeatability | $\pm$ 1 % RH | $\pm$ 0.2 °C |
The specifications are also available in the AM2302 Datasheet.
The data-bus is pulled to high potential using a 4.7kΩ pullup resistor connecting the data-bus and the VDD pin. The pullup resistor is already included in the DHT-22 sensor module. So, the module already works when the sensor is just connected like described above. Furthermore, the ESP32, just like the Arduino, has built-in pullup and pulldown resistors. The values for the pullup resistors vary from module to module and from pin to pin but are typically in the range of 30 – 80 kΩ. When creating an object from the DHT.h-library that represents the DHT-22, the number of the GPIO pin is given as an argument. To start the sensor, the method begin() is executed; this function configures the pin as an input and activates the ESP32’s internal pullup resistor for that pin. So, in reality, two pullup resistors, one from the DHT-22 and one from the ESP32 are used. The total pullup-resistance between the data-bus and VDD can thus vary between:
$$R_{min}=\left(\frac{1}{30000\Omega}+\frac{1}{4700\Omega}\right)^{-1}=4063.4\Omega$$ and $$R_{max}=\left(\frac{1}{80000\Omega}+\frac{1}{4700\Omega}\right)^{-1}=4439.2\Omega$$
When the sensor data pin and the GPIO of the ESP32 are connected through a longer cable (>50cm), it is advisable to use another external pullup-resistor. This is due to the fact that the wire acts as a capacitor, and the longer the wire is, the larger the capacitance. After a 0V pulse, the wire-capacitor has to be charged again before the data-bus reaches the full 3.3V potential. That means, instead of having a clean pronounced voltage signal, which can be interpreted as a 0 or 1, the signal looks like the charging curve of a capacitor (see figure 4). The longer the cable, the larger the capacitance resulting in a longer charging time and a less pronounced signal, which may lead to errors in the communication. Adding another external pullup resistor, for example a 10kΩ resistor, decreases the total pullup-resistance, because the resistors are connected in parallel. The new minimum and maximum resistances are thus:
$$R'_{min}=\left(\frac{1}{30000\Omega}+\frac{1}{4700\Omega}+\frac{1}{10000\Omega}\right)^{-1}=2889.3\Omega$$ and $$R'_{max}=\left(\frac{1}{80000\Omega}+\frac{1}{4700\Omega}+\frac{1}{10000\Omega}\right)^{-1}=3074.4\Omega$$
As the total pullup resistance decreases, the current increases and the wire-capacitor is charged faster (that means 3.3V on the data-bus is reached faster as well), which steepens the charging curve of the capacitor and thus makes the signal more “square”, so it is more pronounced and leads to less errors during communication between MCU and DHT-22. This effect is demonstrated in figure 4 and also occurs for other wire-connected bus-systems like I²C.
During the setup and testing of the DHT-22, some issues to be considered are:
After supplying power to the DHT-22, the sensor has an unstable status, which requires the user to wait for one second until further commands can be sent.
As the sensor consumes more power during measurements, it is prone to heating up and thus influencing the measured temperature. To ensure that the measurements are not adulterated by the sensor heating up, it is required to keep the sampling rate at a maximum of 0.5 Hz, so 1 measurement every 2 seconds.
When using the ESP32 instead of an Arduino, the Arduino IDE can give a time out error (figure 5) during the upload if the DHT-22 is already connected to the ESP32:
![]() |
---|
Figure 5 Time out error during upload of code to the ESP32 DevkitC VB with the DHT-22 connected to it. |
This seems to be an issue caused by the power supply to the DHT-22 during the upload process. Other users reported to have fixed the problem by
However, in our experiments, the only approach that worked was to
In this sketch the DHT-sensor-library from Adafruit was used to communicate with the DHT-22 and obtain the measurement results.
The following code is only part of the complete code that was uploaded to the ESP32 later on. The aim of this code was to test the DHT-22 with the ESP32 and create a function, that can later be easily implemented into the final code. It contains the function (measureDHTTemHum()) to be implemented later, the necessary variables, definitions and libraries. When the ESP32 with this code is connected to the computer via USB, it measures the temperature and humidity in 2 second intervals, averages the measurements to get more accurate results and prints it to the Arduino IDE's serial monitor.
//DHT 22 Temperature and Relative Humidity Reading Function //Definitions #define DHTTYPE DHT22 //1 const int DHTPIN = 15; //2 //Libraries & Objects #include <DHT.h> //3 DHT dht(DHTPIN, DHTTYPE); //4 //Variable Declaration/Initialization float dht22AirTem = 0; //5 float dht22AirTemSum = 0; String dht22Temperature = ""; float dht22RelHum = 0; float dht22RelHumSum = 0; String dht22Humidity = ""; void setup() { delay(5000); //6 Serial.begin(115200); //7 Serial.println("Measurement is starting ..."); } void loop() { Serial.println("Measuring ..."); measureDHTTemHum(5); //8 Serial.println("Temperature: " + dht22Temperature + " °C"); //9 Serial.println("Relative Humidity: " + dht22Humidity + " %"); Serial.println("=============================="); delay(2000); //10 } void measureDHTTemHum (byte AveragingNumber) //11 { delay(1000); //12 dht.begin(); //13 dht22AirTemSum = 0; //14 dht22RelHumSum = 0; dht22Temperature = ""; dht22Humidity = ""; for (byte i = 0; i < AveragingNumber; i++) //15 { do { //16 dht22AirTem = dht.readTemperature(); //17 dht22RelHum = dht.readHumidity(); if (!isnan(dht22AirTem) && !isnan(dht22RelHum)) //18 { dht22AirTemSum += dht22AirTem; //19 dht22RelHumSum += dht22RelHum; } else delay(2000); //20 } while (isnan(dht22AirTem) || isnan(dht22RelHum)); //21 if (i < (AveragingNumber - 1)) //22 delay(2000); } dht22AirTem = dht22AirTemSum / AveragingNumber; //23 if(dht22AirTem<10) //24 dht22Temperature = '0'; dht22Temperature = dht22Temperature + dht22AirTem; //25 dht22RelHum = dht22RelHumSum / AveragingNumber; if(dht22RelHum<10) dht22Humidity = '0'; dht22Humidity = dht22Humidity + dht22RelHum; }
In the following the different sections of the code are explained in more detail:
As can be seen in the code (code section 1) a DHT-22 was used for testing and its data pin was connected to the GPIO pin 15 of the ESP32 DevkitC VB. As explained before, no additional pullup resistor was necessary.
After uploading, the code, the power supply to the DHT-22 was connected: 3.3V to VDD and GND to GND. After 5 seconds, the following was printed to the serial monitor:
15:54:35.854 -> Measurement is starting ... //1 15:54:35.854 -> Measuring ... //2 15:54:44.864 -> Temperature: 23.70 °C //3 15:54:44.864 -> Relative Humidity: 49.82 % //4 15:54:44.864 -> ============================== //5 15:54:46.904 -> Measuring ... //6 15:54:55.934 -> Temperature: 23.76 °C //7 15:54:55.934 -> Relative Humidity: 48.16 % //8 15:54:55.934 -> ============================== //9
Even though the resolution of the measurements is just 0.1 °C and 0.1 % RH (table 1), the values printed in the serial monitor have numbers other than 0 in the second decimal place; this is due to the values being averaged in the function. The measurements were taken in a living room, so temperature and humidity measurements yielded plausible results.
When observing the timestamps on the left, it is possible to see what was happening in the MCU. After the measurement began (line 2), the MCU needed another 9.01 seconds to print the results in the serial monitor (line 3, 4, 5).
For 5 measurements being taken, the minimum delay time is 1 + 8 = 9 seconds. That means, that no improper results were obtained and the do-while loop was only executed once per execution of the for-loop statement.
Between the printing of the results (line 3, 4, 5) and the start of the next measurement process (line 6) a time difference of 2.04 seconds could be observed. 2 seconds are due to the delay in the main loop (code section 10), the rest is due to the print() functions which consume comparably much time.