DHT11 Temperature and Humidity Sensor
The DHT11 digital temperature and humidity sensor is a composite sensor that contains calibrated digital signal output. It features low cost, long-term stability, and can measure relative humidity and temperature using only a single data line for data acquisition.
Module Source
Purchase link: https://item.taobao.com/item.htm?spm=a230r.1.14.23.735720126ougj3&id=522553143872&ns=1&abbucket=12#detail Materials download link: https://pan.baidu.com/s/1HQEL699-Yl5Jh3Hp87_FlQ Materials extraction code: 2sgq
Specifications
Operating voltage: 3-5.5V Operating current: 1MA Measurement resolution: 8 bit Humidity range: 20 - 90 %RH Humidity accuracy: ±5 %RH Temperature range: 0 - 50 ℃ Temperature accuracy: ±2 ℃ Communication protocol: Single-wire bus Number of pins: 3 Pin (2.54mm pitch header) For the information on the left, please refer to the manufacturer's document 1.2-1 Product Specification.
Principle Analysis
The DHT11 uses single-wire bus communication, meaning that both sending and receiving data occur on a single data line, controlled through specified timing sequences. For data information, please refer to document 1.2-1 Product Specification.
Looking from left to right, at the beginning of the timing sequence, the host signal maintains a high level, so when the pin initialization is complete, the pin should output a high level promptly. Because the module's data line is required to remain in a high level state when idle. (In fact, a pull-up resistor is already connected on the module to keep the data line at a high level all the time.) According to the timing diagram, the host (ESP32S3) sends a start signal once, and after the host's start signal ends, the DHT11 sends a response signal, sends out temperature and humidity data, and triggers a data acquisition to prepare for the next data reading. Therefore, completing one data reading requires a start signal, response signal, data reception, and end signal. Data reading steps:
- Start signal: The host (ESP32S3) I/O connected to the data line outputs a low level, and the low level duration cannot be less than 18ms.
DATA_GPIO_OUT(0); //Data line outputs low level
delay_1ms(19); //Start signal hold time 19ms
DATA_GPIO_OUT(1); //Host releases the bus
delay_uus( 20 ); //Pull high and wait2
3
4
- Response signal: Wait for the module's response signal to arrive. Change the data line to input mode. If a low level is detected, it means the module's response is received.
DHT11_GPIO_Mode_IN();//Switch data line to input mode
//If there is no error in the previous steps, the module will send a low-level response signal,
//so directly wait for DHT11 to pull high, 83us
timeout = 5000;
while( (! DATA_GPIO_IN ) && ( timeout >0 ) )
{
timeout--; //Wait for the high level to arrive
}
//The module is currently pulled high and ready to output data,
//so directly wait for DHT11 to pull low, 87us
timeout = 5000;//Set timeout
while( DATA_GPIO_IN && ( timeout >0 ) )
{
timeout-- ; //Wait for the low level to arrive
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
- Data transmission: The host receives the 40 bits of data sent by the module. Among them, bit data '0' represents a 54us low level and 27us high level; bit data '1' represents a 54us low level and 74us high level. The two formats are distinguished mainly by the different high-level output durations.
- End signal: After the module's data line outputs 40 bits of data, it ends with a low level. It will continue to output a low level for 54 microseconds before switching to the input state. The host needs to switch to the output state and output a high level to release the bus.
DHT11_GPIO_Mode_OUT();//Switch to output mode
DATA_GPIO_OUT(1);//Host releases the bus2
Data reception is complete, but how do these 40 bits of data convert to temperature and humidity data? And how to ensure that the transmitted data has no errors? A complete data transmission of the DHT11 module is 40 bits, with the high bit first. Data format:
Note: The humidity decimal part data is always 0.
When the data is transmitted correctly, the checksum data is equal to the last 8 bits of the result of "8bit humidity integer data + 8bit humidity decimal data + 8bit temperature integer data + 8bit temperature decimal data". Here are a few examples. Example 1: The received 40 bits of data are:
Checksum is 0011 0101 + 0000 0000 + 0001 1000 + 0000 0100 = 0101 0001, which is consistent with the received data. Humidity is 0011 0101 + 0000 0000 = 35 + 0 = 35%RH Temperature is 0001 1000 0000 0100 = 24 + 4 = 24.4℃
Example 2: The received 40 bits of data are:
Checksum is 0011 0101 + 0000 0000 + 0001 1000 + 0000 0100 = 0101 0001, which is inconsistent with the received data. The calculated data is 0101 0001, and the received data is 0100 1001. The inconsistency means the data is inaccurate, so discard this data and receive again.
Porting Process
Pin Selection
This module has 3 pins. For specific pin connections, see Table 1.4-1 Pin Connections.
Port to Project
Our goal is to port the example to the ESP32-S3 dev board. Complete driver code has been provided for you. Follow the steps below to complete the porting.
- First, create a folder [dht11], and in the [dht11] folder, create two new files (a .c file and a .h file).
- Open your project and import the .c and .h files we just created into the paths.
- In VSCode, open the CMakeLists.txt file in the main folder.
- Add these paths.
Write Code
In the bsp_dht11.c file, write:
/*
* LCSC-Openkits (LCKFB) software and hardware materials and related expansion board software and hardware materials are all open source on the official website.
* Dev board official website: www.lckfb.com
* Technical support resides on the forum; any technical questions are welcome for exchange and learning at any time.
* LCKFB Forum: club.szlcsc.com
* Follow our Bilibili account: [LCSC-Openkits (LCKFB)] to keep up with our latest updates!
* We do not make money by selling boards; we take cultivating engineers as our mission.
* Change Logs:
* Date Author Notes
* 2023-11-02 LCKFB-yzh first version
*/
#include "bsp_dht11.h"
#include <stdio.h>
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "esp_err.h"
#include "nvs_flash.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/ledc.h"
#include <stdio.h>
#include "driver/uart.h"
#include "driver/gpio.h"
#include "rom/ets_sys.h"
float temperature = 0;
float humidity = 0;
void Delay_ms(uint16 ms)
{
vTaskDelay(ms / portTICK_PERIOD_MS);
}
//Temperature and humidity definitions
uchar ucharFLAG,uchartemp;
float Humi,Temp;
uchar ucharT_data_H,ucharT_data_L,ucharRH_data_H,ucharRH_data_L,ucharcheckdata;
uchar ucharT_data_H_temp,ucharT_data_L_temp,ucharRH_data_H_temp,ucharRH_data_L_temp,ucharcheckdata_temp;
uchar ucharcomdata;
uchar Humi_small;
uchar Temp_small;
static void InputInitial(void)//Set port as input
{
esp_rom_gpio_pad_select_gpio(GPIO_DHT11);
gpio_set_direction(GPIO_DHT11, GPIO_MODE_INPUT);
}
static void OutputHigh(void)//Output 1
{
esp_rom_gpio_pad_select_gpio(GPIO_DHT11);
gpio_set_direction(GPIO_DHT11, GPIO_MODE_OUTPUT);
gpio_set_level(GPIO_DHT11, 1);
}
static void OutputLow(void)//Output 0
{
esp_rom_gpio_pad_select_gpio(GPIO_DHT11);
gpio_set_direction(GPIO_DHT11, GPIO_MODE_OUTPUT);
gpio_set_level(GPIO_DHT11, 0);
}
static uint8 getData()//Read status
{
return gpio_get_level(GPIO_DHT11);
}
//Read one byte of data
static void COM(void)
{
uchar i;
for(i=0;i<8;i++)
{
ucharFLAG=2;
//Wait for IO to go low. After going low, determine 0 or 1 through delay
while((getData()==0)&&ucharFLAG++) ets_delay_us(10);
ets_delay_us(35);//Delay 35us
uchartemp=0;
//If this bit is 1, after 35us it is still 1, otherwise 0
if(getData()==1)
uchartemp=1;
ucharFLAG=2;
//Wait for IO to go high. After going high, it means the next bit can be read
while((getData()==1)&&ucharFLAG++)
ets_delay_us(10);
if(ucharFLAG==1)
break;
ucharcomdata<<=1;
ucharcomdata|=uchartemp;
}
}
void DHT11(void) //Temperature and humidity sensor start
{
OutputLow();
Delay_ms(19); //>18MS
OutputHigh();
InputInitial(); //Input
ets_delay_us(30);
if(!getData())//Indicates the sensor pulls the bus low
{
ucharFLAG=2;
//Wait for the bus to be pulled high by the sensor
while((!getData())&&ucharFLAG++)
ets_delay_us(10);
//Wait for the bus to be pulled low by the sensor
while((getData())&&ucharFLAG++)
ets_delay_us(10);
COM();//Read the 1st byte
ucharRH_data_H_temp=ucharcomdata;
COM();//Read the 2nd byte
ucharRH_data_L_temp=ucharcomdata;
COM();//Read the 3rd byte
ucharT_data_H_temp=ucharcomdata;
COM();//Read the 4th byte
ucharT_data_L_temp=ucharcomdata;
COM();//Read the 5th byte
ucharcheckdata_temp=ucharcomdata;
OutputHigh();
//Check whether the checksum is consistent
uchartemp=(ucharT_data_H_temp+ucharT_data_L_temp+ucharRH_data_H_temp+ucharRH_data_L_temp);
if(uchartemp==ucharcheckdata_temp)
{
//Checksum is consistent
ucharRH_data_H=ucharRH_data_H_temp; // Humidity high 8 bits
ucharRH_data_L=ucharRH_data_L_temp; // Humidity low 8 bits
ucharT_data_H=ucharT_data_H_temp; // Temperature high 8 bits
ucharT_data_L=ucharT_data_L_temp; // Temperature low 8 bits
ucharcheckdata=ucharcheckdata_temp;
//Save temperature and humidity
Humi = ucharRH_data_H;
Humi_small = ucharRH_data_L * 0.1;
Humi = Humi + Humi_small;
Temp = ucharT_data_H;
Temp_small = ucharT_data_L * 0.1;
Temp = Temp + Temp_small;
}
else
{
Humi=100;
Temp=100;
}
}
else //Read failed, return 0
{
Humi=0,
Temp=0;
}
OutputHigh(); //Output
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
In the bsp_dht11.h file, write:
#ifndef _BSP_DHT11_H_
#define _BSP_DHT11_H_
#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_rom_sys.h"
#include "esp_timer.h"
#define uchar unsigned char
#define uint8 unsigned char
#define uint16 unsigned short
/**************Modify pins here****************/
#define GPIO_DHT11 1
void Delay_ms(uint16 ms);
void DHT11(void); //Temperature and humidity sensor start
#endif2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
The porting is now complete. Please proceed to section 1.5 for porting verification.
Porting Verification
Enter the following code in main.c:
#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_timer.h"
#include "freertos/FreeRTOSConfig.h"
#include "esp_task_wdt.h"
#include "dht11/bsp_dht11.h"
extern float Temp;
extern float Humi;
void app_main(void)
{
while(1)
{
//Read temperature and humidity
DHT11();
//Display the read temperature data
printf("temperature = %.2f\r\n", Temp );
//Display the read humidity data
printf("humidity = %.2f\r\n", Humi );
Delay_ms(1000); //Delay
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Power-on effect:
Driver code:
File Download
📌 Materials Download Center (Click to Jump)
📌 In the Materials Download Center -> Module Porting Materials Download, inside the compressed package of this chapter.