树莓派4中避免board与RPi.GPIO冲突,如何配置SCD-40 I2C传感器?
问题描述
我在树莓派4上用Python配置Adafruit SCD-40 I2C温感传感器,示例代码通过board模块初始化I2C:
import board import adafruit_scd4x i2c = board.I2C() # uses board.SCL and board.SDA scd4x = adafruit_scd4x.SCD4X(i2c)
这段代码单独运行正常,但我同时需要用RPi.GPIO控制3个步进电机:
import RPi.GPIO as GPIO
整合代码后触发错误:GPIO.setmode(GPIO.BOARD) ValueError: A different mode has already been set!,提示board模块与RPi.GPIO的GPIO模式冲突。想知道如何不依赖board模块配置I2C传感器?能否通过RPi.GPIO实现?
解决方案
方法1:用busio替代board初始化I2C(保留Adafruit库)
board模块属于Adafruit Blinka项目,它会默认将GPIO模式设置为BCM,和RPi.GPIO指定的BOARD模式冲突。可以直接用busio模块初始化I2C,绕开board的GPIO模式自动设置:
import busio import adafruit_scd4x # 直接指定BCM引脚号:树莓派4默认I2C引脚为SCL=3、SDA=2 i2c = busio.I2C(scl=3, sda=2) scd4x = adafruit_scd4x.SCD4X(i2c)
这种方式既保留了Adafruit SCD-40库的便捷性,又不会触发GPIO模式冲突,可与RPi.GPIO的BOARD模式兼容。
方法2:用smbus2直接操作I2C总线(完全脱离Adafruit高层库)
如果不想依赖Adafruit的库,可以用smbus2直接与SCD-40通信,全程不涉及GPIO模式设置:
- 先安装依赖库:
pip install smbus2
- 基础功能示例代码:
import smbus2 import time # SCD-40的固定I2C地址为0x62 SCD40_I2C_ADDR = 0x62 # 树莓派默认I2C总线编号为1 bus = smbus2.SMBus(1) # 发送启动周期性测量命令 bus.write_i2c_block_data(SCD40_I2C_ADDR, 0x21, [0xb1]) time.sleep(5) # 传感器启动需要约5秒稳定时间 # 循环读取数据 while True: # 查询是否有可用测量数据 bus.write_i2c_block_data(SCD40_I2C_ADDR, 0xe4, [0xb8]) time.sleep(0.1) raw_data = bus.read_i2c_block_data(SCD40_I2C_ADDR, 0, 9) # 检查数据就绪标志位 if (raw_data[0] & 0x07) == 0x07: # 解析CO2、温度、湿度数据 co2 = (raw_data[1] << 8) | raw_data[2] temp_raw = (raw_data[3] << 8) | raw_data[4] hum_raw = (raw_data[5] << 8) | raw_data[6] temperature = -45 + 175 * (temp_raw / (2**16)) humidity = 100 * (hum_raw / (2**16)) print(f"CO2: {co2} ppm | 温度: {temperature:.2f}°C | 湿度: {humidity:.2f}%") time.sleep(2)
该方案完全独立于board模块,与RPi.GPIO的任何模式都兼容。
关键说明
- 无法用
RPi.GPIO实现I2C通信:RPi.GPIO仅提供GPIO引脚的电平控制功能,没有I2C总线的底层协议实现能力,必须使用专门的I2C库(如smbus2、busio)。 - 确保树莓派的I2C功能已启用:通过
raspi-config的Interfacing Options菜单开启I2C。
内容的提问来源于stack exchange,提问作者aviles622
相关产品推荐
相关产品推荐

