1、概述
使用DHT11温湿度传感器,传感周期为1s。
DHT11模块一般由3/4个引脚组成,每一次收集数据为40bit。 分别为:
高位在前、8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和
我们需要解决的问题,如何使用1个引脚一次获取40位的数据,必须增加另外的维度、即“时间”。
数据按照某种协议发送,一组低电平+高电平组成一次的位数据,通过高电平保持时间的不同,来确定这一位是0还是1。
时序图:
黑色为触发信号,即设备端触发DHT11模块
灰色为回响信号,即DHT11返回给主机
主机的触发信号为拉低并保持20ms,拉高保持40us以上。
设备的回响信号为拉低并保持80us,拉高并保持80us。
这两次“握手”非常重要,因为在收集数据之前,我们得先保证主机与传感器设备之间的数据通路。主机触发设备表示主机告诉设备:“我需要数据”,设备返回回响信号。
没有这两次“握手”,无法保证数据通路,即不知道设备是不是“激活”的。
握手完毕之后,传感器发送40个bit数据。每一位数据有低电平+高电平组成。
低电平保持50us表示准备发送,切换高电平后,主机由高电平的维持时间来判断这一位数据是0还是1.
如果保持26-28us,则为0,如果保持70us则为1。
2、Python代码实现
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
pin = 18
def get_data(pin):
# 触发信号 保持20ms以上的低电平,并拉高
GPIO.setup(pin, GPIO.OUT)
GPIO.output(pin, GPIO.LOW)
time.sleep(0.02)
GPIO.output(pin, GPIO.HIGH)
# 切换输入,等待回响,主机拉高维持20-40us,先忽略
GPIO.setup(pin, GPIO.IN)
time.sleep(0.00004)
# 回响信号,拉低80us
k = 0
while GPIO.input(pin) == GPIO.LOW:
k += 1
if k > 2000:
return (0,0,)
# 回响信号,拉高80us
k = 0
while GPIO.input(pin) == GPIO.HIGH:
k += 1
if k > 2000:
return (0,0,)
res = []
# 数据传输开始
for i in range(0, 5):
data = 0
for j in range(0, 8):
# 8次获取位数据,放到data里
# 50us 低电平
k = 0
while GPIO.input(pin) == GPIO.LOW:
k += 1
if k > 2000:
return (0,0,)
k = 0
while GPIO.input(pin) == GPIO.HIGH:
k += 1
if k > 2000:
return (0,0,)
# 根据k的大小,判断时间短是0 长是1
data *= 2
if k > 12: # 1
data += 1
res.append(data)
hum = res[0] + res[1] / 100
tem = res[2] + res[3] / 100
# 没有校验和的判断
return (hum, tem)
try:
while True:
hum, tem = get_data(pin)
print('hum : %f tem : %f' % (hum, tem))
time.sleep(2)
except KeyboardInterrupt:
GPIO.cleanup()
3、C语言转 转python
由于python微妙级延时非常不精准,因此涉及到微秒级操作,则python并不适合。因此如此类传感器我们更多使用C语言实现,封装成模块之后,再由 python直接使用。
https://blog.csdn.net/weixin_45114627/article/details/143286399?sharetype=blogdetail&sharerId=143286399&sharerefer=PC&sharesource=weixin_45114627&spm=1011.2480.3001.8118