树莓派第四课之DHT11湿温度传感器
第一课,温度传感器https://www.52pojie.cn/thread-902898-1-1.html第二课,继电器https://www.52pojie.cn/thread-903925-1-1.html
第三课,舵机https://www.52pojie.cn/thread-911228-1-1.html
第四课,DHT11湿温度传感器终于来了
懒了这么久,今天把欠的账还还。第四课,DHT11温湿度传感器,话说有了这玩意可以做自动煮蛋器啊,呀呸,自动孵蛋器,孵蛋器。肉比蛋好吃嘛,呀呸,小动物那么可爱,怎么可以吃小动物,多放孜然,谢谢。
这一期呢,我试了几种不同的方式,最后发现还是网上流传的方式准确率比较高,但是数据读取错误率依旧有30%-50%左右,暂时没找到更好的解决方案,所以说,这期主要讲怎么使用树莓派进行高低电平通信的问题,实际使用中建议采用C语言。
放心,数据读取错误程序是会发现的,不会回传错误数据
解决高低电平通信问题,无非就是两点,发消息和收消息。
发消息上次讲了,GPIO.output(端口号, GPIO.HIGH/ GPIO.LOW)就可以设置引脚的高低电平了,上一节课已经学习过了。
GPIO.HIGH是高电平, GPIO.LOW是低电平。再用time.sleep(秒数)设置下暂停的时间,就能控制波形、频率等等。
如下例程:# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO #引入GPIO模块,重命名为GPIO
import time #引入time模块
GPIO.setmode(GPIO.BCM) #设置gpio引脚编号模式,有两种编号模式可供选择,自己随意设置就好
GPIO.setup(13, GPIO.OUT) #设置13号口为输出模式
while True: #进入死循环
GPIO.output(13, GPIO.HIGH) #13号口输出高电平
time.sleep(0.02) #程序暂停0.02秒
GPIO.output(13, GPIO.LOW) #13号口输出高电平
time.sleep(0.02) #程序暂停0.02秒
GPIO.cleanup() #关闭所有端口
这样,程序在死循环里,每隔0.02秒就将电平翻转,那不就是周期为0.04秒的方波了吗。
这就是发送信号,很简单吗,但是怎么接收信号呢?
这时候同学们肯定发现,上面有一句这个GPIO.setup(13, GPIO.OUT) #设置13号口为输出模式
那我把GPIO.OUT改为GPIO.IN不就行了。
似乎Python会帮我们处理一切心意,但是可以吗?我们先做测试。
我们初步设想是这样1. 将一个端口设置为接收模式。2. 编写一个程序,输出这个模式接收到的信息。3. 我们手动将该端口接到高低电平上,观看效果。
好的,那我们就来试试吧。# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO #引入GPIO模块,重命名为GPIO
import time
GPIO.setmode(GPIO.BCM) #设置gpio引脚编号模式,有两种编号模式可供选择,自己随意设置就好
GPIO.setup(6, GPIO.IN) #设置6号口为输入模式
print(GPIO.input(6)) #输出6号口的状态
启动!
我们发现,我们将6号口置于高电平,则显示是1,置于低电平则显示是0.那么,我们成功了吗?
我们修改下程序,让他不断去侦测,显示。# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO #引入GPIO模块,重命名为GPIO
import time
GPIO.setmode(GPIO.BCM) #设置gpio引脚编号模式,有两种编号模式可供选择,自己随意设置就好
GPIO.setup(6, GPIO.IN) #设置13号口为输出模式
while True:
print(GPIO.input(6))
运行后我们发现,程序会非常快速的输出,即使你的电平没有变化,他依然是快速输出。比如你置为高电平,则一直输出1,以最快速的方式。
其中将6号口悬空,会发生误判断,则随机显示0或1。
好了,我们继续修改测试程序,让他无变化则不显示。# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO #引入GPIO模块,重命名为GPIO
import time
GPIO.setmode(GPIO.BCM) #设置gpio引脚编号模式,有两种编号模式可供选择,自己随意设置就好
GPIO.setup(6, GPIO.IN) #设置13号口为输出模式
while True:
i=GPIO.input(6)
if i != GPIO.input(6):
print(GPIO.input(6))
i=GPIO.input(6)
这样的话,只有在端口发生变化的时候才显示,果然不错。
好了,基础学会了,我们去了解下DHT11传感器的通信方式吧。
啥是DHT11传感器?
估价的话5-6元
它能够测量环境里的温度,湿度数据
DHT11建议每次查询数据的间隔时间要大于2秒钟,否则可能会出现数据不准确的情况。
首先由主机发送起始信号,起始信号为低电平,时间大于18ms
然后传感器开始应答,先输出80μs的低电平,然后输出80μs的高电平,提醒主机准备接收信号。
随后传感器开始传输数据,共发射四十位数据,前八位为温度数据整数位,再往后八位为温度数据小数位,再往后八位是湿度数据整数位,再往后八位是湿度数据小数位,再往后八位是校验位
数据0的表示方式为:50μs的低电平和 26-28μs的高电平。
数据1的表示方式为:50μs的低电平加 70μs的高电平。
校验方式为:
数据传送正确时校验和数据等于“ 8bit 湿度整数数据 +8bit 湿度小数数据+8bi 温度整数数据 +8bit 温度小数数据 ”所得结果的末8位。
说吧,现在多少人去厕所哭了。
网上有人给了一个点子,检测到低电平变为高电平后,开始进入循环,每循环一次就计数加一,如果输入是0,计数会少些,如果输入是1,计数会多些。
经过测试,输入是0时,计数往往低于8次,计数是1时,计数往往多于8次,如此就可以断别。
哦,对了,1秒=1,000,000微秒。
所以,1微秒等于0.000001秒。
对了,上面的参数哪里去挖?后山去挖,可以去网上百度该模块的技术手册,也可以去找淘宝卖家要。
这一次的流程比较复杂,大家注意看流程图
哇,夭寿了,因为用户组限制,这次流程图太大了,传不上去啊,压缩了还看个毛啊,全模糊了怎么看。
流程图和代码一起传了百度网盘,大家去那看吧。
好了,流程图看好了以后,大家心里大概已经清楚了,代码基本上每一步都有注释,大家可以看下。
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO #引入GPIO模块,重命名为GPIO
import time#引入时间模块
channel=6#设置端口号
j=0#初始化计数器为0
data=[]#初始化数据存储数组
GPIO.setmode(GPIO.BCM) #设置gpio引脚编号模式,有两种编号模式可供选择,自己随意设置就好
time.sleep(1)#程序暂停一秒钟
GPIO.setup(channel, GPIO.OUT) #设置6号口为输出模式
GPIO.output(channel, GPIO.LOW)#6号口输出低电平,即发送触发信号
time.sleep(0.02)#低电平维持0.02秒
GPIO.output(channel, GPIO.HIGH)#输出高电平,标志低电平结束
GPIO.setup(channel, GPIO.IN)#设置端口模式为输入
while GPIO.input(channel)==GPIO.LOW:#跳过初始状态的低电平
pass
while GPIO.input(channel)==GPIO.HIGH:#跳过初始状态的高电平
pass
#进入循环
while j < 40:#仅仅存储40个数据
k = 0
while GPIO.input(channel) == GPIO.LOW:#跳过低电平
continue
while GPIO.input(channel) == GPIO.HIGH:#如果是高电平,则进入循环,高电平结束时停止
k += 1#计数器自增
if k > 100:#如果高电平计数器大于100,则跳出循环,数据错误
break
if k < 8:#如果计数器数值小于8次,则认为值为0
data.append(0)
else:#否则认为值为1
data.append(1)
j += 1#数据位数计数器加一
#按位切割数据
humidity_bit = data
humidity_point_bit = data
temperature_bit = data
temperature_point_bit = data
check_bit = data
humidity = 0
humidity_point = 0
temperature = 0
temperature_point = 0
check = 0
#计算各个数据结果和校验值
for i in range(8):
humidity += humidity_bit * 2 ** (7 - i)
humidity_point += humidity_point_bit * 2 ** (7 - i)
temperature += temperature_bit * 2 ** (7 - i)
temperature_point += temperature_point_bit * 2 ** (7 - i)
check += check_bit * 2 ** (7 - i)
#计算检查值
tmp = humidity + humidity_point + temperature + temperature_point
if check == tmp:
print('数据正确')
print("温度: "+str(temperature)+", 湿度: "+str(humidity))
else:
print('数据错误')
print("温度: "+str(temperature)+",湿度: "+str(humidity)+"校验值: "+str(check)+" 检查值: "+str(tmp))
GPIO.cleanup()
这时候可能有人已经要跳出来喊,你是抄袭的。事实上,我并不是抄袭,我引用了网上主流的代码,对其加以修改和注释,其原版仅仅能够在python2.X版本下运行,我将其升级到了python3,同时完善了注释和流程解释。可以说,当前互联网上针对于这个代码最详细,最准确的教程就在我这了。相信意义党也应该觉得这次教程编写的有意义吧。
因为网上对该代码抄袭严重,质量参差不齐,实在难以找到原作者是谁,故无法声明原作者的原著链接,但在此对原作者表示感谢。本次教程本人不声明版权,大家可以引用转载。
流程图和代码都在这里:链接:https://pan.baidu.com/s/13hHWYNpaxhjUlDN1DnKlUw 提取码:jkk8
这里只有代码,流程图放压缩包就超过用户组限制了……
愤怒,愤怒,图片传不上去好痛苦,严重影响教程质量,希望吾爱的文件大小限制放宽些,太痛苦了这样。
这个其实用esp8266刷ESP EASY做很方便的,固件刷进去,然后把线接好,登录到固件页面,选好针脚开启获取信息,比在树莓派上做方便,树莓派可以通过python来获取esp easy 上JSON的数据,这样就可以和设备脱离了,不然树莓派必须放在检测环境的附近,由于线缆连接的原因。 好东西,学习一下 感谢大佬分享 虽然看不懂,但是仍然要支持你。 学习一下 家里的树莓派吃灰了,来学习一下 可以当毕设用了,可以 感谢,感谢:loveliness: 学习了。最近在研究树莓派
页:
[1]
2