用树莓派做温湿度上报与红外控制
有段时间在折腾身边各种数据的采集,其中一个就是房间的温湿度。 一开始是买了个加湿器,但是不知道效果怎么样,就买了个小米的温湿度计,不料这个温湿度计导出数据十分麻烦,要连手机 APP 发到邮箱,所以就想搞一个自动采集并上报温湿度的装置,树莓派+传感器是最优选择了。
树莓派本质上是个带 GPIO 的小主机,GPIO 之外的操作和普通 ARM Linux 没什么区别。 重点就是 GPIO 的玩法,它的存在使得树莓派可以外接很多电子元器件,传感器、屏幕、发动机等等。
树莓派到手之后要先装好系统,跟随 官方教程 就可以了。 为了方便连接在内网给树莓派分配了固定 IP,除了第一次装机用显示器后面都连 SSH 操作了。 貌似玩树莓派的都喜欢 root 用户直接上,大概是因为很多硬件相关的程序都要 root 权限吧 ( 印象中嵌入式设备都不怎么安全呢 ) 。
温湿度传感器 DHT22
为了检测温湿度买了 DHT22 传感器 ( 顺便吐槽下市面上的温湿度计,几百块的湿度计精度也才 5%RH,几块钱的 DHT22 精度都能到 2.5%RH ) ,用 Python 的 CircuitPython 库来读取。 这里 有官方的教程。
有一个入门的时候比较容易迷惑的点,就是传感器如何接线到引脚,以及如何把接好的引脚跟代码里的描述对应起来。
首先是怎么接线。 树莓派自带了一个很好用的工具 Pinout ,只要在命令行输入 pinout
并回车就能看到板子的布局和每个引脚的功能:
,--------------------------------.
| oooooooooooooooooooo J8 +======
| 1ooooooooooooooooooo PoE | Net
| Wi oo +======
| Fi Pi Model 4B V1.4 oo |
| ,----. +====
| |D| |SoC | |USB3
| |S| | | +====
| |I| `----' |
| |C| +====
| |S| |USB2
| pwr |HD| |HD| |I||A| +====
`-| |---|MI|---|MI|----|V|-------'
Revision : b03114
SoC : BCM2711
RAM : 2048Mb
Storage : MicroSD
USB ports : 4 ( excluding power )
Ethernet ports : 1
Wi-fi : True
Bluetooth : True
Camera ports ( CSI ) : 1
Display ports ( DSI ) : 1
J8:
3V3 ( 1 ) ( 2 ) 5V
GPIO2 ( 3 ) ( 4 ) 5V
GPIO3 ( 5 ) ( 6 ) GND
GPIO4 ( 7 ) ( 8 ) GPIO14
GND ( 9 ) ( 10 ) GPIO15
GPIO17 ( 11 ) ( 12 ) GPIO18
GPIO27 ( 13 ) ( 14 ) GND
GPIO22 ( 15 ) ( 16 ) GPIO23
3V3 ( 17 ) ( 18 ) GPIO24
GPIO10 ( 19 ) ( 20 ) GND
GPIO9 ( 21 ) ( 22 ) GPIO25
GPIO11 ( 23 ) ( 24 ) GPIO8
GND ( 25 ) ( 26 ) GPIO7
GPIO0 ( 27 ) ( 28 ) GPIO1
GPIO5 ( 29 ) ( 30 ) GND
GPIO6 ( 31 ) ( 32 ) GPIO12
GPIO13 ( 33 ) ( 34 ) GND
GPIO19 ( 35 ) ( 36 ) GPIO16
GPIO26 ( 37 ) ( 38 ) GPIO20
GND ( 39 ) ( 40 ) GPIO21
样式更丰富的布局也可以在网站 https://pinout.xyz/ 上面找到。 有了板子的布局,按照传感器的说明接线即可。
另一个问题是如何在代码中使用对应的引脚。 不同的程序对树莓派的引脚有不同的编码方式,使用 gpio readall
指令可以查看这些编码:
+-----+-----+---------+------+---+---Pi 4B--+---+------+---------+-----+-----+
| BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
+-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
| | | 3.3v | | | 1 || 2 | | | 5v | | |
| 2 | 8 | SDA.1 | IN | 1 | 3 || 4 | | | 5v | | |
| 3 | 9 | SCL.1 | ALT0 | 1 | 5 || 6 | | | 0v | | |
| 4 | 7 | GPIO. 7 | IN | 1 | 7 || 8 | 1 | ALT5 | TxD | 15 | 14 |
| | | 0v | | | 9 || 10 | 1 | ALT5 | RxD | 16 | 15 |
| 17 | 0 | GPIO. 0 | IN | 1 | 11 || 12 | 0 | OUT | GPIO. 1 | 1 | 18 |
| 27 | 2 | GPIO. 2 | IN | 0 | 13 || 14 | | | 0v | | |
| 22 | 3 | GPIO. 3 | IN | 0 | 15 || 16 | 0 | IN | GPIO. 4 | 4 | 23 |
| | | 3.3v | | | 17 || 18 | 0 | IN | GPIO. 5 | 5 | 24 |
| 10 | 12 | MOSI | ALT0 | 0 | 19 || 20 | | | 0v | | |
| 9 | 13 | MISO | ALT0 | 0 | 21 || 22 | 0 | IN | GPIO. 6 | 6 | 25 |
| 11 | 14 | SCLK | ALT0 | 0 | 23 || 24 | 1 | OUT | CE0 | 10 | 8 |
| | | 0v | | | 25 || 26 | 1 | OUT | CE1 | 11 | 7 |
| 0 | 30 | SDA.0 | IN | 1 | 27 || 28 | 1 | IN | SCL.0 | 31 | 1 |
| 5 | 21 | GPIO.21 | IN | 1 | 29 || 30 | | | 0v | | |
| 6 | 22 | GPIO.22 | IN | 1 | 31 || 32 | 0 | IN | GPIO.26 | 26 | 12 |
| 13 | 23 | GPIO.23 | IN | 0 | 33 || 34 | | | 0v | | |
| 19 | 24 | GPIO.24 | IN | 0 | 35 || 36 | 0 | IN | GPIO.27 | 27 | 16 |
| 26 | 25 | GPIO.25 | IN | 0 | 37 || 38 | 0 | IN | GPIO.28 | 28 | 20 |
| | | 0v | | | 39 || 40 | 0 | IN | GPIO.29 | 29 | 21 |
+-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
| BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
+-----+-----+---------+------+---+---Pi 4B--+---+------+---------+-----+-----+
其中 BCM 列的引脚可以用 board.D<pin>
来表示,例如 BCM=2 的引脚就是 board.D2
。
回到读取温湿度传感器的主题,接好传感器之后,确认数据线对应的引脚,就可以搞软件部分了。 首先安装相关的库:
pip3 install adafruit-circuitpython-dht
sudo apt-get install libgpiod2
之后就可以测试了:
import board
import adafruit_dht
dhtDevice = adafruit_dht.DHT22(board.D2)
temperature_c = dhtDevice.temperature
humidity = dhtDevice.humidity
print(temperature_c, humidity)
dhtDevice.exit()
红外接收器与发射器
搞红外接收与发射是为了自动开关电灯,以及遥控空调来节省空调遥控器的电池浪费。
红外接收器使用的是 1838 红外接收头封装的一个模块,发射器就是普通的红外二极管串联一个 10 欧级别的电阻,不过发射角只有 30° 挺不方便,最好还是买个角度大一点的。
连好线之后就是软件部分。 红外的收发有一个好用不火的 python 包 ircodec 。使用很简单,首先安装 ( 需要 root ) :
pip3 install pigpio ircodec
pigpiod # 启动服务
后面分成两步,接收遥控器信号并记录,以及读取记录的信号并发射。 首先是接收信号以及记录:
from ircodec.command import CommandSet
controller = CommandSet(emitter_gpio=22, receiver_gpio=23, description='xxx')
# Add the volume up key
controller.add('volume_up')
# Connected to pigpio
# Detecting IR command...
# Received.
controller.save_as('test.json')
读取并发射:
controller = CommandSet.load('test.json')
controller.emit('volume_up')
。接收的部分用 Jupyter Notebook 来做会很方便调试。