树莓派4B与DHT11、TTP223和BF1750(FVI)

本文最后更新于:2023年4月15日 晚上

DHT11

硬件及接线等说明

在开始之前,先放出一个DHT11的数据手册,需要参考的可以点击跳转:DHT11数据手册
这里我自己买的是三脚的DHT11,不过三脚和四脚的接线都是一样的,要接的是VCCDATAGND
DHT11引脚说明
再看到我们的树莓派4B的引脚:
树莓派4B引脚说明
然后把我们的VCC连接到任意3.3V5V引脚上,GND连接至任意Ground引脚上,DATA连接到任意GPIO引脚上,我这里以连接到7号引脚上做示例。

编程环境准备

这里自己用的IDE就是树莓派官方烧录自带的Thonny,编程语言用的Python,然后还需要安装一个第三方库Adafruit_DHT,安装该库使用以下命令:

1
2
sudo git clone https://github.com/adafruit/Adafruit_Python_DHT.git
cd Adafruit_Python_DHT

OK,现在先停一下,因为这个库最后更新是19年,会导致树莓派4B无法使用,因为驱动未支持树莓派4B的处理器BCM2711,我们需要手动为其添加支持。打开当前目录下的Adafruit_DHT,编辑platform_detect.py,并添加以下内容(如果你没动过代码,那么下列语句应该添加在第111行之后,如果博文内容过期了也没关系,因为你应该能很好地看出来下面这句应该放在哪里):

1
2
3
elif match.group(1) == 'BCM2711':
# Pi 4b
return 3

这里插入一点题外话,树莓派4B虽然用的是BCM2711但是某些命令显示出来会是BCM2835(貌似),查了下原因没懂(逃
如果你觉得需要权限编辑很麻烦,建议多使用控制台,遇事不决命令前加sudo
编辑完成后就是安装库了,执行该命令:sudo python setup.py install,当然我不知道你的树莓派上pythonpython3是不是一个版本(有人的树莓派装了python2python3),不是的话就再执行下sudo python3 setup.py install
在网上看到的其他博文都说要更新软件包,反正我没更新,如果硬要更新的话,记得注意sudo apt-get install build-essential python-dev输出的说明,可能是把python3的卸了装python2的(?)

编写程序

当然你也可以不写,因为Adafruit提供了示例程序,可以直接运行程序测试,示例程序就在Adafruit_Python_DHT目录下的examples文件夹里,在当前目录的终端下执行:python AdafruitDHT.py 11 4即可。

如果你不知道怎么进入目录,我还是那句话,建议多使用控制台,记住最基本的命令是好的。现在就先参考下面的命令吧:

1
2
cd ~
cd Adafruit_Python_DHT/examples

那么python AdafruitDHT.py 11 4后面的114是什么意思呢?看到源码里面写的:

1
2
3
4
5
6
7
# Parse command line parameters.
sensor_args = { '11': Adafruit_DHT.DHT11,
'22': Adafruit_DHT.DHT22,
'2302': Adafruit_DHT.AM2302 }
if len(sys.argv) == 3 and sys.argv[1] in sensor_args:
sensor = sensor_args[sys.argv[1]]
pin = sys.argv[2]

所以在这里,第一个参数11代表传感器的型号,这里支持三种传感器的数据读取;而第二个参数4代表的是GPIO的编号,注意不是板编号,虽然我用的GPIO 4是7号引脚,但是GPIO编号是4,所以这里传入的参数是4
下面就由我们自己来编写程序。在这里,我编写的是一个每秒读一次数据并打印到终端的程序。

1
2
3
4
5
6
7
8
9
10
11
12
import Adafruit_DHT

sensor=Adafruit_DHT.DHT11
gpio=4

while (1):
humidity, temperature = Adafruit_DHT.read_retry(sensor, gpio)
if humidity is not None and temperature is not None:
print('Temp={0:0.1f}*C Humidity={1:0.1f}%'.format(temperature, humidity))
else:
print('Failed to get reading. Try again!')
time.sleep(1)

可以看到代码简洁易懂,直接调库就行,省略了复杂的读取数据、计算数据和校验数据的步骤(坏处是没学到什么东西.jpg)。

TTP223

我买的是这样的:TTP223
这个就好懂了,VCCGND和上面的DHT11的一样,剩下的SIG也是接任意一个GPIO引脚即可,下面的程序我接的是GPIO_17

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import RPi.GPIO as GPIO
from time import sleep
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.IN)
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)

try:
while True:
sleep(1)
if GPIO.input(17) == GPIO.HIGH:
print('touch!')
else:
print('nothing happen.')
except KeyboardInterrupt:
GPIO.cleanup()
print('GPIO cleanup()')

现在来解释一下,引入RPi.GPIO这个库,GPIO引脚编码设置为BCM编码,然后把BCM编码下的17号引脚设置为输入模式,因为我们需要从中读取引脚电平状态来知道传感器是否被触摸;GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)这一句的话,翻译一下就是设置上拉电阻,关于上下拉电阻有什么作用,可以百度一下(
当我们触摸板检测到触摸时,引脚就会输出高电平,所以我们只需要通过检测引脚此刻电平状态,就能知道是否存在触摸,然后进行我们需要进行的操作即可。

BH1750(FVI)

硬件及接线说明

前排提示:这个东西是要自己焊的,如果你不会焊或者从来没接触过焊接引脚的,我的建议是找找焊接好的,不要折磨自己(
BH1750引脚说明
BH1750是通过I2C协议进行数据传输的,所以在这里我们需要用到树莓派的3号引脚(GPIO 2)和5号引脚(GPIO 3),分别是SDASCL
BH1750的接线也十分简单明了,VCCGND与前面接线说明一样,另外两个SDASCL引脚也是刚好对应树莓派4B上的两个GPIO引脚。
不过需要注意的是,如果在终端使用gpio readall命令的话,我们会发现树莓派4B提供了SDA 1SCL 1SDA 0SCL 0两对I2C接口,但是我们需要用到的是1,并且这个0在默认情况下应该是无法使用的(看别人说的,自己貌似没试过),也有说把摄像头关了就能使用,如果有兴趣可以自己试试。
BH1750功能说明
上面这些图的功能说明,就是告诉我们,向BH1750送入这些数据,BH1750会执行什么操作,可以理解为命令。

树莓派4B开启I2C和下载i2c-tools

接完线后,我们仍需要配置一些东西。现在先来打开树莓派4B的I2C功能。
首先,打开终端,然后在终端输入命令sudo raspi-config,进入设置界面。
使用方向键移动,使用回车确认,进入3 Interface Options,选择第五项I5 I2C,然后选择Yes,退出并重启系统(重启可使用sudo reboot)。至此,就启用了树莓派的I2C功能了。
接下来是安装i2c-tools,打开终端输入命令:sudo apt-get install i2c-tools等待安装完成即可。
安装成功后,输入sudo i2cdetect -l来检查一下我们使用的接口:

出现i2c-1说明使用的是I2C1的接口,也就是SDA 1SCL 1
然后再检查一下我们接入的传感器BH1750,在终端输入命令:sudo i2cdetect -y 1进行查看:

截图上的23就是我们的BH1750的默认地址。
至此,配置完成。

编写程序

终于到编写程序环节了,可喜可贺捏~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import json
import time
import RPi.GPIO as GPIO
import smbus
from paho.mqtt import client as mqtt_client

GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT)

# BH1750FVI config
DEVICE = 0x23 # Default device I2C address
POWER_DOWN = 0x00
POWER_ON = 0x01
RESET = 0x07
CONTINUOUS_LOW_RES_MODE = 0x13
CONTINUOUS_HIGH_RES_MODE_1 = 0x10
CONTINUOUS_HIGH_RES_MODE_2 = 0x11
ONE_TIME_HIGH_RES_MODE_1 = 0x20
ONE_TIME_HIGH_RES_MODE_2 = 0x21
ONE_TIME_LOW_RES_MODE = 0x23
bus = smbus.SMBus(1)

# MQTT broker config
broker = '******'
port = ******
topic = '***'
client_id = '******'
username = '***'
password = '***'

def read_light():
data = bus.read_i2c_block_data(DEVICE, ONE_TIME_HIGH_RES_MODE_1)
light_level = round((data[1] + (256 * data[0])) / 1.2, 2)
return light_level


def connect_mqtt():
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)
client = mqtt_client.Client(client_id)
client.username_pw_set(username, password)
client.on_connect = on_connect
client.connect(host=broker, port=port)
return client


def publish(client):
msg_count = 0
try:
while True:
time.sleep(1)
light_level = read_light()
if light_level > 55:
GPIO.output(17, GPIO.LOW)
else:
GPIO.output(17, GPIO.HIGH)
publish_msg = {'lightLevel': light_level}
result = client.publish(
topic,
payload=json.dumps(publish_msg)
)
# result: [0, 1]
status = result[0]
if status == 0:
print(publish_msg)
else:
print(f"Failed to send message to topic {topic}")
except KeyboardInterrupt:
GPIO.cleanup()
print('GPIO.cleanup()')


def run():
client = connect_mqtt()
client.loop_start()
publish(client)


if __name__ == "__main__":
run()

这边解释一些比较重要的语句。bus = smbus.SMBus(1)这里就是实例化,1代表的是/dev/i2c-1
read_i2c_block_data(i2c_addr, register, length),就是从给定的寄存器中读取字节数据块,其中三个参数分别表示:i2c设备的地址、给定的寄存器、读取的长度(最多32位),返回一个字节组成的列表。
(data[1] + (256 * data[0])) / 1.2就是单纯的计算公式,不用管太多。其他代码的话都是MQTT的模板代码,可以通过官网的文档了解到这些代码的用途:使用Python SDK接入


这里有一只爱丽丝

希望本文章能够帮到您~


树莓派4B与DHT11、TTP223和BF1750(FVI)
https://map1e-g.github.io/2023/04/09/raspberrypi-essay-1/
作者
MaP1e-G
发布于
2023年4月9日
许可协议