3、Python编程基础:Python语法速览、虚拟环境搭建、常用库安装(RPi.GPIO、gpiozero、smbus2等)
在Raspberry Pi上进行IoT传感器数据采集,Python是最核心的编程语言。本章将聚焦于三个关键环节:Python语法速览(确保你能够读懂并编写基础脚本)、虚拟环境搭建(隔离项目依赖,避免系统级库冲突)、以及常用硬件操作库的安装与验证(RPi.GPIO、gpiozero、smbus2)。这三者构成了从“写代码”到“控制硬件”的完整桥梁。我们将通过一个实际的光照传感器数据采集案例,将语法、环境与库的使用串联起来,帮助你建立工程化的开发习惯。
3.1 Python语法速览:面向硬件操作的核心子集
对于IoT数据采集场景,我们不需要掌握Python的全部语法,但必须精通以下核心子集:变量与数据类型、条件判断、循环、函数定义、异常处理以及模块导入。这些语法元素将覆盖90%以上的传感器读取和数据处理需求。
核心原理:Python是一种动态类型语言,变量无需声明类型。在硬件编程中,我们经常处理整数(引脚编号)、浮点数(电压值)、字节串(I2C原始数据)和布尔值(开关状态)。理解bytes与int的转换尤为重要,因为I2C和SPI总线返回的往往是原始字节。
# 硬件编程中常用的语法模式
import time
import RPi.GPIO as GPIO
# 变量与类型
sensor_value = 0 # int
voltage = 3.3 # float
is_connected = True # bool
raw_data = b'\x01\x02' # bytes
# 条件判断与循环
while True:
if GPIO.input(17) == GPIO.HIGH:
print("引脚17为高电平")
else:
print("引脚17为低电平")
time.sleep(0.5) # 延时500ms
操作流程:建议按照“变量→流程控制→函数→异常”的顺序学习。在编写传感器驱动时,务必使用try-except捕获I2C通信异常,因为硬件设备可能未连接或地址错误。
GPIO.setmode(GPIO.BCM) 是推荐模式,它使用BCM引脚编号(如GPIO17),而非物理引脚编号(如11)。BCM模式更稳定,且与大多数库(如gpiozero)兼容。
3.2 虚拟环境搭建:隔离项目依赖
树莓派系统自带的Python环境通常包含系统级包,直接使用pip install安装库可能会污染系统环境,导致版本冲突。虚拟环境(venv)为每个项目创建独立的Python运行空间,这是工程化开发的标准实践。
核心原理:虚拟环境通过复制Python解释器并创建独立的site-packages目录,使得不同项目可以使用不同版本的库。在树莓派上,我们推荐使用python3 -m venv命令创建。
| 操作步骤 | 命令 | 说明 |
|---|---|---|
| 1. 创建虚拟环境 | python3 -m venv sensor_env |
在当前目录创建名为sensor_env的虚拟环境 |
| 2. 激活虚拟环境 | source sensor_env/bin/activate |
激活后终端提示符前会出现(sensor_env) |
| 3. 安装依赖 | pip install smbus2 gpiozero |
在虚拟环境内安装库,不影响系统环境 |
| 4. 退出虚拟环境 | deactivate |
返回系统全局Python环境 |
常见误区:很多初学者直接使用sudo pip install,这会将包安装到系统级目录,且可能覆盖系统依赖。在树莓派上,如果遇到权限问题,应优先考虑使用虚拟环境,而非sudo。另外,虚拟环境创建后,每次新开终端都需要重新激活。
3.3 常用库安装与验证:RPi.GPIO、gpiozero、smbus2
这三个库分别对应GPIO控制、高级设备抽象和I2C通信。RPi.GPIO是底层库,直接操作寄存器;gpiozero提供了更友好的API,适合快速开发;smbus2是I2C通信的标准库,用于读取传感器数据。
核心原理:RPi.GPIO通过sysfs接口操作GPIO,而gpiozero在底层封装了RPi.GPIO或pigpio,提供了如LED、Button、MCP3008等高级类。smbus2则通过/dev/i2c-1设备文件与I2C总线通信。
# 安装命令(在虚拟环境内执行)
pip install RPi.GPIO gpiozero smbus2
# 验证安装是否成功
python3 -c "import RPi.GPIO; print('RPi.GPIO OK')"
python3 -c "import gpiozero; print('gpiozero OK')"
python3 -c "import smbus2; print('smbus2 OK')"
案例拆解:读取BH1750光照传感器
假设我们需要采集环境光照强度(单位:lux),BH1750是一款数字I2C光照传感器,地址为0x23。以下是完整的采集流程:
- 硬件连接:VCC→3.3V,GND→GND,SDA→GPIO2(物理引脚3),SCL→GPIO3(物理引脚5)。
- 启用I2C接口:运行
sudo raspi-config,在Interface Options中启用I2C。 - 编写采集脚本:
import time
from smbus2 import SMBus
# 初始化I2C总线(总线1对应/dev/i2c-1)
bus = SMBus(1)
BH1750_ADDR = 0x23
CONTINUOUS_HIGH_RES_MODE = 0x10
def read_lux():
"""读取BH1750光照强度"""
try:
# 发送测量命令
bus.write_byte(BH1750_ADDR, CONTINUOUS_HIGH_RES_MODE)
time.sleep(0.2) # 等待测量完成
# 读取2字节数据(高字节在前)
data = bus.read_i2c_block_data(BH1750_ADDR, 0x00, 2)
lux = (data[0] << 8) | data[1]
lux = lux / 1.2 # 根据数据手册换算
return lux
except Exception as e:
print(f"读取失败: {e}")
return -1
if __name__ == "__main__":
for _ in range(5):
lux_value = read_lux()
print(f"光照强度: {lux_value:.2f} lux")
time.sleep(1)
结果对比与复盘:首次运行时,如果返回读取失败: [Errno 121] Remote I/O error,说明I2C地址错误或设备未正确连接。此时应使用i2cdetect -y 1命令扫描总线,确认设备地址。如果返回0x23,则硬件连接正常;否则检查SDA/SCL是否接反,或是否缺少上拉电阻(树莓派内部已有1.8kΩ上拉,通常无需外接)。
time.sleep(0.1),等待I2C总线稳定。
3.4 常见误区与总结复盘
在树莓派Python开发中,以下误区最为常见:
- 误区一:使用
sudo pip install安装库,导致系统环境混乱。正确做法是使用虚拟环境。 - 误区二:混淆BCM引脚编号与物理引脚编号。例如,GPIO17在BCM模式下是物理引脚11,但很多初学者误以为是物理引脚17。
- 误区三:忽略I2C地址冲突。多个I2C设备可能共享同一地址,此时需要使用地址选择引脚或I2C多路复用器。
- 误区四:在读取传感器时未处理异常。硬件设备可能随时断开,必须使用
try-except保证程序健壮性。
总结复盘:本章的核心目标是建立“语法→环境→库”的完整开发链路。通过虚拟环境隔离依赖,通过smbus2读取I2C传感器,通过gpiozero控制GPIO输出。建议读者在树莓派上实际运行上述代码,并尝试修改参数(如测量模式、延时时间),观察输出变化。下一阶段,我们将深入GPIO中断与PWM输出,实现更复杂的传感器数据采集与执行器控制。