ESP8266开发学习笔记_DHT11温湿度传感器

ESP8266 开发学习笔记_By_GYC 【DHT11 温湿度传感器】

本章介绍ESP8266 IDF 框架下 如何使用GPIO口进行单总线时序模拟,介绍DHT11温湿度传感器的使用方法,实现对温湿度的采集。

一、准备材料

①开发板:NodeMcu (ESP8266)

②环境:Ubuntu 18.04 、 ESP-IDF 操作系统( ESP8266_RTOS_SDK V3.2)

③传感器:DHT11

④辅助材料:杜邦线、面包板

二、硬件连接

原理图

DHT11的硬件只包含三个引脚,分别是VCC、GND和数据输出引脚DATA。其模块输入电压VCC的输入范围是3.3V~5V。采样周期为1秒。传感器接3.3V电源、GND和ESP8266的GPIO5,信号引脚DATA接5kΩ上拉电阻,完成DHT11的硬件系统。

链接图

三、软件编程

DHT11能够使用单总线传输协议与ESP8266进行通信。其中ESP8266作为主机,DHT11作为从机。主机给传感器DHT11发送起始信号,收到从机应答信号后初始化成功,能够进行数据传输。

DHT11回复响应信号后,会发送40bit的传感器数据,包括两个字节的湿度数据(一个字节整数、一个字节小数),两个字节的温度数据整数(一个字节整数、一个字节小数),最后是一个字节的校验和数据。通过求和校验的数据将会作为最后发送的数据。

DHT11 通信时序图

本次例程是基于EPS8266 IDF的example “project_template” 进行开发,直接在模板基础上进行新内容的添加。

1、修改工程名

首先,将MakeFile中模板中的工程名字

1
PROJECT_NAME := project_template

修改为

1
PROJECT_NAME := project_DHT11

2、添加组件

然后添加工程组件文件夹 dht11_driver 到自己工程的 components (组件) 下

(PS:本次首先提供C++版本的驱动,工程中C++的具体使用方法可以参考我的系列博客内容)

3、编程

修改user_main.c 为 user_main.cpp

添加 dht11驱动的头文件 “dht11_driver.hpp”

为 void app_main(void) 函数添加修饰符 extern “C” 如下:

1
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
#include <stdio.h>
#include "esp_system.h"

#include "dht11_driver.hpp"

//生成 DHT11 的实例化对象
DHT_Sensor my_DHT11(GPIO_NUM_5,DHT11);
/******************************************************************************
* FunctionName : app_main
* Description : entry of user application, init user function here
* Parameters : none
* Returns : none
*******************************************************************************/
extern "C" void app_main(void)
{
printf("SDK version:%s\n", esp_get_idf_version());
my_DHT11.DHTInit();

while(1)
{
my_DHT11.DHTRead();
ESP_LOGI("DHT11","DHT: Temperature*100 = %d *C, Humidity*100 = %d %% (GPIO%d)",
(int) (my_DHT11.Sensor_Data.temperature * 100), (int) (my_DHT11.Sensor_Data.humidity * 100), my_DHT11.data_pin);

vTaskDelay(1000 / portTICK_RATE_MS);
}
}

4、反馈结果

打印反馈

5、核心代码

1
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
//温湿度传感器数据读取(并将数据写入到传入指针)

bool DHT_Sensor::DHTRead(DHT_Sensor_Data* output)
{
int counter = 0;
int laststate = 1;
int i = 0;
int j = 0;
int checksum = 0;
int data[100];
data[0] = data[1] = data[2] = data[3] = data[4] = 0;
gpio_num_t pin = (gpio_num_t)data_pin;

gpio_set_direction(pin,GPIO_MODE_OUTPUT);
// Wake up device, 250ms of high

gpio_set_level(pin, 1);
sleepms(250);
// Hold low for 20ms
gpio_set_level(pin, 0);
sleepms(20);

// High for 40ns
gpio_set_level(pin, 1);
delay_us(40);

// Set DHT_PIN pin as an input
gpio_set_direction(pin,GPIO_MODE_INPUT); //GPIO_DIS_OUTPUT(pin);

// wait for pin to drop?
while (gpio_get_level(pin) == 1 && i < DHT_MAXCOUNT) {
delay_us(1);
i++;
}

if(i == DHT_MAXCOUNT)
{
DHT_DEBUG("DHT: Failed to get reading from GPIO%d, dying\r\n", pin);
return false;
}

// read data
for (i = 0; i < DHT_MAXTIMINGS; i++)
{
// Count high time (in approx us)
counter = 0;

while (gpio_get_level(pin) == laststate)
{
counter++;
delay_us(1);
if (counter == 1000)
break;
}

laststate = gpio_get_level(pin);

if (counter == 1000)
break;
// store data after 3 reads
if ((i>3) && (i%2 == 0)) {
// shove each bit into the storage bytes
data[j/8] <<= 1;
if (counter > DHT_BREAKTIME)
data[j/8] |= 1;
j++;
}
}
if (j >= 39) {
checksum = (data[0] + data[1] + data[2] + data[3]) & 0xFF;
DHT_DEBUG("DHT%s: %02x %02x %02x %02x [%02x] CS: %02x (GPIO%d)\r\n",
sensor_type==DHT11?"11":"22",
data[0], data[1], data[2], data[3], data[4], checksum, pin);

if (data[4] == checksum) {
// checksum is valid
output->temperature = scale_temperature(data);
output->humidity = scale_humidity(data);

DHT_DEBUG("DHT: Temperature*100 = %d *C, Humidity*100 = %d %% (GPIO%d)\n",
(int) (output->temperature * 100), (int) (output->humidity * 100), pin);
} else {
DHT_DEBUG("DHT: Checksum was incorrect after %d bits. Expected %d but got %d (GPIO%d)\r\n",
j, data[4], checksum, pin);
return false;
}
} else {
DHT_DEBUG("DHT: Got too few bits: %d should be at least 40 (GPIO%d)\r\n", j, pin);
return false;
}
return true;
}

四、总结

驱动DHT11主要就是遵从时序图,按照时序图中规定的时序控制和读取单线的DHT11传感器数据,最终通过原始数据换算得到最终的温湿度数据的值。

本次的工程我会开源到自己的github上(https://github.com/gengyuchao),欢迎大家来和我一起交流呀。

Comments

:D 一言句子获取中...

Loading...Wait a Minute!