第二十五章 DHT11实验
本章,我们将介绍数字温湿度传感器DHT11的使用,与前一章的温度传感器相比,该传感器不但能测温度,还能测湿度。我们将学习如何获取DHT11传感器的温湿度数据,并把数据显示在LCD上。
本章分为如下几个小节:
25.1 DHT11及其时序简介
25.2 DHT11类
25.3 硬件设计
25.4 程序设计
25.5 下载验证
25.1 DHT11及其时序简介
25.1.1 DHT11简介
DHT11是一款温湿度一体化的数字传感器。该传感器包括一个电阻式测湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。通过单片机等微处理器简单的电路连接就能够实时的采集本地湿度和温度。DHT11与单片机之间能采用简单的单总线进行通信,仅仅需要一个I/O口。传感器内部湿度和温度数据40Bit的数据一次性传给单片机,数据采用校验和方式进行校验,有效的保证数据传输的准确性。DHT11功耗很低,5V电源电压下,工作平均最大电流0.5mA。
DHT11的技术参数如下:
l 工作电压范围:3.3V ~ 5.5V
l 工作电流:平均0.5mA
l 输出:单总线数字信号
l 测量范围:湿度5 ~ 95%RH,温度-20 ~ 60℃
l 精度:湿度±5%,温度±2℃
l 分辨率:湿度1%,温度0.1℃
DHT11的管脚排列如下图所示:
图25.1.1.1 DHT11管脚排列图
25.1.2 DHT11时序简介
虽然DHT11与DS18B20类似,都是单总线访问,但是DHT11的访问,相对DS18B20来说简单很多。下面我们先来看看DHT11的数据结构。
DHT11数字温湿度传感器采用单总线数据格式。即,单个数据引脚端口完成输入输出双向传输。其数据包由5byte(40bit)组成。数据分小数部分和整数部分,一次完整的数据传输为40bit,高位先处。DHT11的数据格式为:8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数部分+8bit校验和。其中校验和数据为前面四个字节相加。
传感器数据输出的是未编码的二进制数据。数据(湿度、温度、整数、小数)之间应该分开处理。例如,某次从DHT11读到的数据如下图所示:
图25.1.2.1 某次读取到DHT11数据
由以上数据就可得到湿度和温度的值,计算方法:
湿度 = byte4 . byte3 = 45.0(%RH)
温度 = byte2 . byte1 = 28.0(℃)
校验 = byte4 + byte3 + byte2 + byte1 = 73 (= 湿度 + 温度) (校验正确)
可以看出,DHT11的数据格式十分简单的,DHT11和MCU的一次通信最大为34ms左右,建议主机连续读取时间间隔不要小于2s。
下面,我们介绍一下DHT11的传输时序。DHT11的数据发送流程如下图所示。
图25.1.2.2 DHT11数据发送流程图
首先主机发送开始信号,即:拉低数据线,保持t1(至少18ms)时间,然后拉高数据线t2(10~35us)时间,然后读取DHT11的响应,正常的话,DHT11会拉低数据线,保持t3(78~88us)时间,作为响应信号,然后DHT11拉高数据线,保持t4(80~92us)时间后,开始输出数据。
DHT11输出数字‘0’时序如下图所示。
图25.1.2.3 DHT11数字‘0’时序图
DHT11输出数字‘1’的时序如下图所示:
图25.1.2.4 DHT11输出数字‘1’时序图
DHT11输出数字‘0’和‘1’时序,一开始都是DHT11拉低数据线54us,后面拉高数据线保持的时间就不一样,数字‘0’就是23~27us,而数字‘1’就是68~74us。
通过以上了解,我们就可以通过ESP32-S3来实现对DHT11的读取了。DHT11的介绍就到这里,更详细的介绍,请参考DHT11的数据手册。
MicroPython源代码已经提供了dht.py脚本代码,读者可以在micropython\lib\micropython-lib\micropython\drivers\sensor\dht找到此文件。从该文件的内容可以看出,它通过调用dht.c(micropython\drivers\dht)C模块来实现单总线协议。
25.2 DHT11类
MicroPython源代码提供了DHT驱动程序,用户可调用此模块来驱动DHT11和DHT22模块,下面是该模块的对象构造方法和使用方法,如下。
1,DHT类的构造方法
DHT的构造对象方法如下:
class dht.DHT11(Pin) 使用示例:dht11 = dht.DHT11(machine.Pin(4))
该构造方法的参数描述,如下表所示。
表25.2.1 dht.DHT11构造方法参数描述
返回值:DHT对象。
2,DHT模块的方法
①:测量数据。
其函数原型如下:
dht11.measure()
返回值:无。
②:提取温度数据。
其函数原型如下:
dht11.temperature()
返回值:温度数值。
③:提取湿度数据。
其函数原型如下:
dht11.humidity()
返回值:湿度数值。
25.3 硬件设计
1. 例程功能
本章实验功能简介:DHT11每隔1000ms左右读取一次数据,并把温度显示在LCD上。 LED闪烁用于提示程序正在运行。
2. 硬件资源
1)XL9555
IIC_INT-IO0(需在P5连接IO0)
IIC_SDA-IO41
IIC_SCL-IO42
2)SPILCD
CS-IO21
SCK-IO12
SDA-IO11
DC-IO40(在P5端口,使用跳线帽将IO_SET和LCD_DC相连)
PWR- IO1_3(XL9555)
RST- IO1_2(XL9555)
3)DHT11
1WIRE_DQ-IO0
3. 原理图
DHT11接口与ESP32-S3的连接关系,如下图所示:
图25.3.1 DHT11接口与ESP32-S3的连接电路图
25.4 程序设计
25.4.1 程序流程图
程序流程图能帮助我们更好的理解一个工程的功能和实现的过程,对学习和设计工程有很好的主导作用。下面看看本实验的程序流程图。
图25.4.1.1 程序流程图
25.4.2 程序解析
本书籍的代码都在main.py脚本下编写的,读者可在光盘资料下找到对应的源码。DHT11实验main.py源码如下:
from machine import Pin,SPI,I2C import atk_xl9555 as io_ex import atk_lcd as lcd import time import dht """ * @brief 程序入口 * @param 无 * @retval 无 """ if __name__ == '__main__': # 初始化LED并输出高电平 led = Pin(1,Pin.OUT,value = 1) # IIC初始化 i2c0 = I2C(0, scl = Pin(42), sda = Pin(41), freq = 400000) # XL9555初始化 xl9555 = io_ex.init(i2c0) # 复位LCD xl9555.write_bit(io_ex.SLCD_RST,0) time.sleep_ms(100) xl9555.write_bit(io_ex.SLCD_RST,1) time.sleep_ms(100) # 初始化SPI spi = SPI(2,baudrate = 80000000, sck = Pin(12), mosi=Pin(11), miso=Pin(13)) # 初始化LCD,lcd = 0为正点原子2.4寸屏幕;lcd = 1为正点原子1.3寸SPILCD屏幕; display = lcd.init(spi,dc = Pin(40,Pin.OUT,Pin.PULL_UP,value = 1), cs = Pin(21,Pin.OUT,Pin.PULL_UP,value = 1),dir = 1,lcd = 0) # 开启背光 xl9555.write_bit(io_ex.SLCD_PWR,1) time.sleep_ms(100) # 提示实验信息 display.string(5, 10, 240, 32, 32, "ESP32-S3",lcd.RED) display.string(5, 43, 240, 24, 24, "DHT11 TEST",lcd.RED) display.string(5, 68, 240, 16, 16, "ATOM@ALIENTEK",lcd.RED) display.string(5, 84, 200, 16, 16, "temperature: 00.00C", lcd.RED) display.string(5, 100, 200, 16, 16, "humidity: 00.00H", lcd.RED) # 创建dht11对象 dht11 = dht.DHT11(Pin(0, Pin.IN, Pin.PULL_UP)) while True: # 测量数据 dht11.measure() # 提取温度数据 temperature = float(dht11.temperature()) # 提取湿度数据 humidity = float(dht11.humidity()) display.num(5 + 13 * 8,84,int(temperature),2,16,lcd.BLUE) display.num(5 + 16 * 8,84,int(temperature * 100 % 100),2,16,lcd.BLUE) display.num(5 + 10 * 8,100,int(humidity),2,16,lcd.BLUE) display.num(5 + 13 * 8,100,int(humidity * 100 % 100),2,16,lcd.BLUE) led_state = led.value() led.value(not led_state) time.sleep(1)
在上述源码中,我们首先调用dht11.measure函数测量数据,然后调用dht11.temperature和dht11.humidity函数提取温湿度数据,最后在SPILCD上显示。另外, LED用来指示程序运行状态。
25.5 下载验证
假定DHT11传感器已经接上去正确的位置,将程序下载到开发板后,可以看到LED不停的闪烁,提示程序已经在运行了。LCD显示当前的温度值的内容如下图所示:
图25.5.1 程序运行效果图
至此,本章实验结束。大家可以将本章通过DHT11读取到的温度值,和前一章的通过DS18B20读取到的温度值对比一下,看看哪个更准确?