之前的章节我们学习了很多树莓派的基础知识,这节我们来进行一个小小的实战操作,使用树莓派以及DHT11测量温湿度,以及实现个简单的温湿度报警器。
原本以为这个应该是这个狠容易的事,毕竟以前在Arduino上没少折腾DHT11,想必树莓派上应该不会麻烦多少,结果发现可能不麻烦,但是走了很多弯路呢,听我慢慢道来。
DHT11硬件连接
常见的DHT11有两种,一种是带电路板的(三针),一种是简单的DHT11模块(四针),其中四线的模块正面视图的第三只针脚没啥用。另外信号管脚需要上拉,电路板那种模块信号脚和VCC之间加了个10K的上拉电阻。
我用的是四针的模块,所以要自己加个上拉电阻,用面包板连接后实物图如下:
安装支持库
其实我相信用GPIO Zero Python库也能实现,不过没有找到现成的封装,懒得去做移植,网上不少例子都是用的Adafruit_DHT的库,咱也试试。
安装啥的都没问题,结果发现运行时出一堆错误:
其中主要一条错误信息如下:
ImportError: cannot import name 'Beaglebone_Black_Driver' from 'Adafruit_DHT' (/usr/local/lib/python3.7/dist-packages/Adafruit_DHT/init.py)
我分析一下代码,是代码不支持树莓派4所导致的,网上看到一些修改方案,比如说这条:
... elif match.group(1) == 'BCM2711': #Pi 4b return 3 else: return None
我觉得这个修改应该可行,不过搜索信息时发现,Adafruit_Python_DHT其实已经被adafruit放弃了:
This library has been deprecated! We are leaving this up for historical and research purposes but archiving the repository.
We are now only supporting the use of our CircuitPython libraries for use with Python.
所以还是不折腾这个了,用官方推荐的新库才是正道啊。
安装:
sudo pip3 install adafruit-circuitpython-dht sudo apt-get install libgpiod2
示例代码
import time import board import adafruit_dht # Initial the dht device, with data pin connected to: dhtDevice = adafruit_dht.DHT11(board.D4) while True: try: # Print the values to the serial port temperature_c = dhtDevice.temperature temperature_f = temperature_c * (9 / 5) + 32 humidity = dhtDevice.humidity print( "Temp: {:.1f} F / {:.1f} C Humidity: {}% ".format( temperature_f, temperature_c, humidity ) ) except RuntimeError as error: # Errors happen fairly often, DHT's are hard to read, just keep going print(error.args[0]) time.sleep(2.0) continue except Exception as error: dhtDevice.exit() raise error time.sleep(2.0)
以上代码来自这里并略作修改。
运行代码
将上述代码保存为dht11_test.py,并执行如下指令,就可以运行啦:
python3 dht11_test.py
这里列举一下我遇到的问题,避免大家踩坑。
踩坑一
弄完代码后,我随手使用如下指令运行:
python dht11_test.py
结果被提示:
File "dht11_test.py", line 2, in <module> import board ImportError: No module named board
检查了一下发现,这是因为我树莓派上有python2 和python3两个版本,支持库装的是python3版本,所以要用python3指令来执行。
踩坑二
使用python3执行指令后,出现了如下提示:
DHT sensor not found, check wiring
检查后,发现原来示例代码中使用的是GPIO 18,而我使用的是GPIO 4,所以要做对应的修改。将board.D18改为board.D4。
踩坑三
执行后出现如下提示:
Received unplausible data. Try again.
这又是啥错误呢?莫非是我DHT11坏掉了?果断换枚DHT11,结果依旧失败。仔细检查代码,我才发现,原本示例代码中使用的是DHT22。所以需要将这句:
dhtDevice = adafruit_dht.DHT22(board.D4)
修改为:
dhtDevice = adafruit_dht.DHT11(board.D4)
执行效果
使用修改后的代码,运行效果如下:
哈,我书房的温湿度,还不错吧。
简单的报警器
接下来我们尝试给这个温湿度测量仪(这个测量仪有些昂贵,哈哈哈)加上一个报警功能。比如说当温度高于某一阈值,报警器就会哗哗哗地叫。
为了实现这个功能,我们首先要搞定蜂鸣器,这次我使用的是一枚有源蜂鸣器模块(无源的死活没搞定,我晕)。
从上图可见,蜂鸣器模块有三个有用的管脚(NC无用):
SIG(信号、数据针脚)
VCC(+、正极)
GND(—、负极)
我们只需将VCC接到3.3V上,GND接到Ground上,SIG接任意GPIO就可以啦。我这里接的是GPIO 22。
连线后效果如图:
以下为简单测试代码,让蜂鸣器哔哔哔叫5秒后关闭:
import time from gpiozero import Buzzer bz = Buzzer(22) bz.beep(0.2, 0.1) time.sleep(5) bz.off()
其中beep函数声明如下:
beep(on_time=1, off_time=1, n=None, background=True)
我们也可以传入n值来控制beep的次数,比如这段代码让蜂鸣器响beep十次:
import time from gpiozero import Buzzer bz = Buzzer(22) bz.beep(0.2, 0.1, 10) time.sleep(5)
接下来将上述代码集成到温湿度的代码中,完整代码如下:
import time import board import adafruit_dht from gpiozero import Buzzer bz = Buzzer(22) # Initial the dht device, with data pin connected to: dhtDevice = adafruit_dht.DHT11(board.D4) while True: try: # Print the values to the serial port temperature_c = dhtDevice.temperature temperature_f = temperature_c * (9 / 5) + 32 if temperature_c >= 30.0: bz.beep(0.2, 0.1, 10) humidity = dhtDevice.humidity print( "Temp: {:.1f} F / {:.1f} C Humidity: {}% ".format( temperature_f, temperature_c, humidity ) ) except RuntimeError as error: # Errors happen fairly often, DHT's are hard to read, just keep going print(error.args[0]) time.sleep(2.0) continue except Exception as error: dhtDevice.exit() raise error time.sleep(2.0)
为了测试,我用电吹风吹我的DHT11,使其升温到30摄氏度以上,蜂鸣器就会开始报警啦:
其它一些补充
其实温湿度模块或者蜂鸣器模块可以拿来做好多好玩的事情,比如温湿度模块可以结合一块LCD 1602做一个实时显示温湿度的温湿度计,也可以将采集到的温湿度数据写入到网络数据库中,加一些其它模块做个小小的气象站。
蜂鸣器的场景就更多了,很多需要监控&提醒的地方都可以加上蜂鸣器模块,比如监控燃气泄漏,或者监控应用程序运行等等。
这里我们只是演示了基本的操作,剩下的,大家可以自行发挥啦。
好了,这次的分享先到这里,后续内容,敬请期待哦。