树莓派python实战_树莓派高级GPIO库,wiringpi2 for python使用笔记(四)实战DHT11解码...

DHT11是一款有已校准数字信号输出的温湿度传感器。 精度湿度+-5%RH, 温度+-2℃,量程湿度20-90%RH, 温度0~50℃。

我买的封装好的模块,上边自带了上拉电阻,直接查到树莓派上即可灰、紫、蓝分别代表数据、3.3V、0V,接到树莓派的3,1,10脚,分别对应PIN8,3.3V,0V。

DHT11与单片机通讯协议为单线协议(1-wire),其实单线协议蛮厉害的,一个GPIO就能实现数据的读取,但是这个协议没有同步脉冲,所以对时序要求比较高,比如DHT11对高低电平定义如下:

低电平50us,然后一个26-28us的高电平,代表0

低电平50us,然后一个70us的高电平,代表1

也就是说,需要能分辨出40us以下的时间才能准确的测出,下边看看具体的时序:

总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号.主机发送开始信号结束后,延时等待20-40us后, 读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可, 总线由上拉电阻拉高。

数字0表示如下图:

数字1表示如下图:

可以看出,每一位包括一开始的响应信号,都是由一个低电平跟一个高电平组成,其中响应信号为80us+80us=160us

数字0为50+26=76us

数字1为50+70=120us

为读到DHT11的状态,我编写了以下的程序:

importwiringpi2 as gpio

owpin=8 #第8脚为1-wire脚

tl=[] #存放每个数据位的时间

gpio.wiringPiSetup() #初始化wiringpi库

gpio.pinMode(owpin,1) #设置针脚为输出状态

gpio.digitalWrite(owpin,1) #输出高电平

gpio.delay(1)###发开始指令,要求DHT11传输数据

gpio.digitalWrite(owpin,0) #拉低25ms开始指令

gpio.delay(25)

gpio.digitalWrite(owpin,1) #输出高电平,开始指令结束

gpio.pinMode(owpin,0) #设针脚为输入状态###开始指令发送完毕,把管脚设置为高电平,并等待DHT11拉低管脚。传输数据

while(gpio.digitalRead(owpin)==1): pass #如果管脚一直是1,则一直等待。###若被拉低,说明传输开始,应答信号+40位数据+结束标志共42位###下边共循环45次,故意多循环几次看结果。

for i in range(45): #测试每个数据周期的时间(包括40bit数据加一个发送开始标志

tc=gpio.micros() #记下当前us数(从初始化开始算起,必要时重新初始化)

'''一个数据周期,包括一个低电平,一个高电平,从DHT11第一次拉低信号线开始

到DHT11发送最后一个50us的低电平结束(然后被拉高,一直维持高电平,所以

最后的完成标志是一直为高,超过500ms)'''

while(gpio.digitalRead(owpin)==0):pass #一位数据由一个低电平

while(gpio.digitalRead(owpin)==1): #加一个高电平组成

if gpio.micros()-tc>500: #如果超过500us就结束了本次循环,传输结束后

break #会被上拉电阻拉成高电平,防止进入死循环

tl.append(gpio.micros()-tc) #记录每个周期时间的us数,存到tl这个列表

print(tl) #打印结果

程序里有详细的解释,我就不再赘述,这里贴出我这里的执行结果:

[116, 68, 74, 67, 124, 64, 120, 120, 76, 71, 73, 73, 73, 73, 73, 73, 74, 67, 73, 73, 123, 120, 70, 72, 73, 79, 71, 73, 73, 74, 73, 74, 73, 70, 73, 122, 74, 117, 120, 119, 70, 508, 506, 512, 512]

现在分析一下结果:

第一个116us是应答信号,按照说明应该是160us估计是我手里这个DHT11做的不是很标准后边40个(从68us开始到最后一个70us)为40位数据,后边因为没有收到任何数据,所以都超过了500us(时间超过500us就跳出循环防止死循环)

第一个116us不管,60-80us的为0,120左右的为1,则收到的数据为:

湿度整数 湿度小数 温度整数 温度小数 校验

0001 0110 0000 0000 0001 1000 0000 0000 0010 1110

16+4+2=22 0 16+8=24 0 32+8+4+2=46

故读到的结果是湿度22%,温度24度,校验和为22+24=46,读取成功。

我又加了一些数据处理,以及读取失败重新读取的附加代码,最终代码如下:

importwiringpi2 as gpio

owpin=8 #第8脚为1-wire脚

defgetval(owpin):

tl=[] #存放每个数据位的时间

tb=[] #存放数据位

gpio.wiringPiSetup() #初始化wiringpi库

gpio.pinMode(owpin,1) #设置针脚为输出状态

gpio.digitalWrite(owpin,1) #输出高电平

gpio.delay(1)

gpio.digitalWrite(owpin,0)#拉低20ms开始指令

gpio.delay(25)

gpio.digitalWrite(owpin,1) #抬高20-40us

gpio.delayMicroseconds(20)

gpio.pinMode(owpin,0)#设针脚为输入状态

while(gpio.digitalRead(owpin)==1): pass #等待DHT11拉低管脚

for i in range(45): #测试每个数据周期的时间(包括40bit数据加一个发送开始标志

tc=gpio.micros() #记下当前us数(从初始化开始算起,必要时重新初始化)

'''一个数据周期,包括一个低电平,一个高电平,从DHT11第一次拉低信号线开始

到DHT11发送最后一个50us的低电平结束(然后被拉高,一直维持高电平,所以

最后的完成标志是一直为高,超过500ms)'''

while(gpio.digitalRead(owpin)==0):pass

while(gpio.digitalRead(owpin)==1):if gpio.micros()-tc>500: #如果超过500ms就结束了

break

if gpio.micros()-tc>500: #跳出整个循环

breaktl.append(gpio.micros()-tc) #记录每个周期时间的us数,存到tl这个列表

#print(tl) #反注释后可打印时间列表

tl=tl[1:] #去掉第一项,剩下40个数据位

for i intl:if i>100: #若数据位为1,时间为50us低电平+70us高电平=120us

tb.append(1)else:

tb.append(0)#若数据位为0,时间为50us低电平+25us高电平=75us

#这里取大于100us就为1#print(tb) #反注释可查看每一位状态

returntbdefGetResult(owpin):for i in range(10):

SH=0;SL=0;TH=0;TL=0;C=0

result=getval(owpin)#print(len(result))

if len(result)==40:for i in range(8):#计算每一位的状态,每个字8位,以此为湿度整数,湿度小数,温度整数,温度小数,校验和

SH*=2;SH+=result[i]

SL*=2;SL+=result[i+8]

TH*=2;TH+=result[i+16]

TL*=2;TL+=result[i+24]

C*=2;C+=result[i+32]if ((SH+SL+TH+TL)%256)==C and C!=0:break

else:print("Read Sucess,But checksum error! retrying")else:print("Read failer! Retrying")

gpio.delay(200)returnSH,SL,TH,TL

SH,SL,TH,TL=GetResult(owpin)print("湿度:",SH,SL,"温度:",TH,TL)

运行结果如下:

湿度: 20 0 温度: 24 0

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值