树莓派基础实验27:温湿度传感器DHT11 实验

一、介绍

   数字温湿度传感器DHT11是一种复合传感器,包含温度和湿度的校准数字信号输出。采用专用数字模块采集技术和温湿度传感技术,确保产品具有高可靠性和优异的长期稳定性。
   该传感器包含一个电阻湿感元件和一个NTC温度测量设备,并与一个高性能8位微控制器连接。其精度:湿度±5%RH, 温度±2℃。量程:湿度20-90%RH, 温度0~50℃。采样周期:大于等于1秒/次。
   在我们刚开始练习写传感器的时序时,DHT11非常适合新手入门练习如何写时序。


二、组件

★Raspberry Pi 3主板*1

★树莓派电源*1

★40P软排线*1

★湿度传感器DHT11模块*1

★面包板*1

★跳线若干

三、实验原理

温湿度传感器

温湿度传感器模块原理图

   DHT11是一款价格便宜,易于使用的温度湿度测量二合一传感器。它具有超小体积、极低功耗的特点。它使用单根总线与单片机进行双向的串行数据传输,信号传输距离可达20米以上。非常适用于对精度和实时性要求不高的温湿度测量场合。

DHT11硬件原理图

   数据总线DATA使用上拉电阻拉高,因此总线空闲时为高电平。上拉电阻阻值推荐范围:4.7K~5.1K。必要时在VDD和GND之间并一个100nF的去耦电容。

1. DHT11的数据格式:

  DATA 用于树莓派与DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,操作流程如下:

   DHT11用的是单总线协议,一次传送40位的数据。 注意了,看到这一句话,也就是说我们每次读取DHT11的数据时,都要一次性读取40次,也就是读取40位。并且数据前16位是与湿度相关的,中间16位是与温度相关的,最后八位是用来校验的,当我们校验成功后,证明这一次的温湿度结果正确的,我们的树莓派就可以使用这个温湿度值;如果校验不通过,那么就代表我们这次读取出来的温湿度值,是错误的(也许是我们的时序错误了,也许是传感器的问题),我们不进行采样。

 DHT11数据格式示例

2. DHT11的工作原理:

数据时序图

DHT11的总体通信流程:
第一步:主机(树莓派)先发送开始信号,从机(DHT11)会返回一个相应信号进行应答。
第二步:主机信号线拉高准备接收数据。
第三步:开始接收数据(一次接收40位)。

   DHT11使用单一总线通信,即DATA引脚和单片机连接的线。总线总是处于空闲状态和通信状态这个2个状态之间。当树莓派没有与DHT11交互时,总线处于空闲状态,在上拉电阻的作用下,处于高电平状态。

   当单片机和DHT11正在通信时,总线处于通信状态,一次完整的通信过程如下:

   第一步: DHT11 上电后(DHT11 上电后要等待 1秒以越过不稳定状态在此期间不能发送任何指令),测试环境温湿度数据,幵记录数据,同时 DHT11 的 DATA 数据线由上拉电阻拉高一直保持高电;此时 DHT11 的DATA 引脚处于输入状态,时刻检测外部信号。

   第二步: 微处理器的 I/O 设置为输出,同时输出低电平,且低电平保持时间不能小于 18ms,然后输出高电平20~40us,再树莓派的 I/O设置为输入状态,等待 DHT11 作出回答信号,发送信号如图所示:

主机发送起始信号

   第三步: DHT11 的 DATA 引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后 DHT11 的 DATA引脚处于输出状态,输出 80 微秒的低电平作为应答信号,紧接着输出 80 微秒的高电平通知外设准备接收数据,树莓派的 I/O 此时处于输入状态,检测到 I/O 有低电平(DHT11 回应信号)后,等待 80 微秒的高电平后的数据接收,发送信号如图所示:

DHT11应答信号

   第四步: 由 DHT11 的 DATA 引脚输出 40 位数据,树莓派根据 I/O 电平的变化接收 40 位数据,位数据“0”的格式为: 50 微秒的低电平和 26-28 微秒的高电平;位数据“1”的格式为: 50 微秒的低电平加 70微秒的高电平。位数据“0”、“1”格式信号如图所示:

位数据“0”、“1”的格式

   我们可以把这一段的时序理解为,DHT11先把数据线拉低50us,然后我们再去对比高电平持续的时间,如果持续时间较短,则为位“0”;如果持续时间较长,则为位“1”。

   结束信号: DHT11 的 DATA 引脚输出 40 位数据后,继续输出低电平 50 微秒后转为输入状态,由于上拉电阻随之变为高电平。但 DHT11 内部重测环境温湿度数据,幵记录数据,等待外部信号的到来。

注意事项:

1、DHT11上电后,要等待 1秒 以越过不稳定状态,在此期间不能发送任何指令。

2、DHT11属于低速传感器,两次通信请求之间的间隔时间不能太短,一般来说要不能低于1秒。

对DHT11的时序做一个总结:
一. 主机(单片机)发送起始信号:
  1.主机先拉高data。
  2.拉低data延迟18ms。
  3.拉高data(单片机引脚设置为输入)。

二. 从机(DHT11)收到起始信号后进行应答:
  从机拉低data,主机读取到data线被拉低持续80us后从机拉高data线, 持续80us,直到高电平结束,意味着主机可以开始接受数据。

三. 主机开始接收数据:
  1.主机先把data线拉高(io设置为输入)。
  2.从机把data线拉低,主机读取data线电平,直到低电平结束(大约50us)从机拉高data线后,对比高电平持续的时间,如果持续时间较短,则为位“0”;如果持续时间较长时,则为位“1”。
  3.继续重复上述1,2步骤累计40次。

四. data线拉低50us代表读取结束

五. 校验数据

更多资料请参考DHT11 官方手册:
https://www.dfrobot.com.cn/image/data/DFR0067/DFR0067_DS_10.pdf

四、实验步骤

  第1步: 连接电路。

树莓派T型转接板温湿度传感器
GPIO0G17OUT(DATA)
5V5VVCC
GNDGNDGND

温湿度传感器DHT11 实验电路图

温湿度传感器DHT11 实验实物接线图

  第2步: 编写控制程序。将提取的二进制数据转化为十进制数据,校验后打印出来。
  本次编程中将用到NumPy(Numerical Python)扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。详情参考NumPy 教程:
  https://www.runoob.com/numpy/numpy-tutorial.html

  为便于对比DHT11高电平持续的时间,我们设置了一个计数器参数k,如果持续时间较短,则k值较小;如果持续时间较长时,则k值较大。当然,也可以使用时间函数直接对比时间长短,但是程序相对要复杂一些。比如使用GPIO.add_event_detect()和time.time()函数

执行结果截图

  从上面的截图中可以看出,高电平持续的时间较短,26-28 微秒时,参数k等于5或6;高电平持续的时间较长,70 微秒时,参数k等于17或18。

#!/usr/bin/env python
import RPi.GPIO as GPIO
import numpy as np
import time
 
DHTPIN = 17			#引脚号17

GPIO.setmode(GPIO.BCM)		#以BCM编码格式

def read_dht11_dat():
	
	GPIO.setup(DHTPIN, GPIO.OUT)
	GPIO.output(DHTPIN, GPIO.LOW)
	#给信号提示传感器开始工作,并保持低电平18ms以上
	time.sleep(0.02)				#这里保持20ms	
	GPIO.output(DHTPIN, GPIO.HIGH)  #然后输出高电平
	
	GPIO.setup(DHTPIN, GPIO.IN)    
	# 发送完开始信号后得把输出模式换成输入模式,不然信号线上电平始终被拉高
 
	while GPIO.input(DHTPIN) == GPIO.LOW:
		continue
	#DHT11发出应答信号,输出 80 微秒的低电平
	
	while GPIO.input(DHTPIN) == GPIO.HIGH:
		continue
	#紧接着输出 80 微秒的高电平通知外设准备接收数据
	
	
	#开始接收数据
	j = 0				#计数器
	data = []			#收到的二进制数据
	kk=[]				#存放每次高电平结束后的k值的列表
	while j < 40:
		k = 0
		while GPIO.input(DHTPIN) == GPIO.LOW:  # 先是 50 微秒的低电平
			continue
		
		while GPIO.input(DHTPIN) == GPIO.HIGH: # 接着是26-28微秒的高电平,或者 70 微秒的高电平
			k += 1
			if k > 100:
				break
		kk.append(k)
		if k < 8:		#26-28 微秒时高电平时通常k等于5或6
			data.append(0)		#在数据列表后面添加一位新的二进制数据“0”
		else:			#70 微秒时高电平时通常k等于17或18
			data.append(1)		#在数据列表后面添加一位新的二进制数据“1”
 
		j += 1
 
	print("sensor is working.")
	print '初始数据高低电平:\n',data	#输出初始数据高低电平
	print '参数k的列表内容:\n',kk		#输出高电平结束后的k值
	
	m = np.logspace(7,0,8,base=2,dtype=int)	#logspace()函数用于创建一个于等比数列的数组
	#即[128 64 32 16 8 4 2 1],8位二进制数各位的权值
	data_array = np.array(data)	#将data列表转换为数组

	#dot()函数对于两个一维的数组,计算的是这两个数组对应下标元素的乘积和(数学上称之为内积)
	humidity = m.dot(data_array[0:8])			#用前8位二进制数据计算湿度的十进制值
	humidity_point = m.dot(data_array[8:16])
	temperature = m.dot(data_array[16:24])
	temperature_point = m.dot(data_array[24:32])
	check = m.dot(data_array[32:40])
	
	print humidity,humidity_point,temperature,temperature_point,check
	
	tmp = humidity + humidity_point + temperature + temperature_point
	#十进制的数据相加
 
	if check == tmp:	#数据校验,相等则输出
		return humidity, temperature
	else:		        #错误输出错误信息
		return False
 
def main():
	print "Raspberry Pi DHT11 Temperature test program\n"
	time.sleep(1)			#通电后前一秒状态不稳定,时延一秒
	while True:
		result = read_dht11_dat()
		if result:
			humidity, temperature = result
			print "humidity: %s %%,  Temperature: %s  ℃" % \
			      (humidity, temperature)
			print '\n' 
			time.sleep(1)

		if result == False:
			print "Data are wrong,skip\n"
			time.sleep(1)
			
def destroy():
	GPIO.cleanup()

if __name__ == '__main__':
	try:
		main()
	except KeyboardInterrupt:
		destroy() 



  

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Maker 张

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值