树莓派4上BH1750 I2C Python代码运行异常排查求助
问题诊断与解决方案
问题概述
- BH1750光照传感器在树莓派4上运行简易代码正常,可多次重启运行
- 加入GPIO控制等必需模块后,代码运行失败,抛出
TimeoutError: [Errno 110] Connection timed out - 运行脚本前执行
i2cdetect -y 1能检测到传感器地址0x23,脚本失败后再执行该命令无法检测到任何I2C设备
核心原因分析
这类问题大概率是GPIO控制模块与I2C总线的资源冲突,常见场景包括:
- 部分GPIO库(如RPi.GPIO)会修改I2C总线使用的GPIO引脚(SDA=GPIO2、SCL=GPIO3)的模式,将其从I2C复用模式切换为普通GPIO输入/输出模式,导致I2C总线通信中断
- 多个模块同时尝试初始化或占用I2C总线,造成总线锁定或资源竞争
分步解决方案
1. 检查GPIO模块的引脚占用
确保你的GPIO控制代码没有直接操作GPIO2(SDA)和GPIO3(SCL)引脚。如果必须使用这两个引脚,需采用支持I2C复用的方式操作,避免直接修改引脚模式。
2. 统一使用Adafruit Blinka生态的GPIO控制模块
放弃使用RPi.GPIO等老旧库,改用adafruit_blinka兼容的GPIO模块(如digitalio),保证I2C和GPIO操作共用同一套底层资源,避免冲突:
# 替换RPi.GPIO的示例代码 import board import digitalio # 初始化GPIO输出 led = digitalio.DigitalInOut(board.D18) led.direction = digitalio.Direction.OUTPUT led.value = True
3. 确保I2C总线只被初始化一次
在复杂代码中,检查是否存在多次初始化I2C总线的情况(比如不同模块各自创建board.I2C()实例)。应全局共享同一个I2C对象:
# 全局初始化I2C,其他模块复用该对象 import board i2c = board.I2C() # 传感器初始化 import adafruit_bh1750 sensor = adafruit_bh1750.BH1750(i2c) # GPIO模块初始化(示例) import digitalio led = digitalio.DigitalInOut(board.D18) led.direction = digitalio.Direction.OUTPUT
4. 强制重置I2C总线(临时修复方案)
如果脚本崩溃后I2C设备消失,可通过以下命令重置I2C总线,无需重启树莓派:
# 卸载I2C驱动 sudo rmmod i2c_bcm2835 # 重新加载驱动 sudo modprobe i2c_bcm2835
可以将该逻辑加入脚本的异常处理中,在捕获TimeoutError时自动执行总线重置:
import board import time import adafruit_bh1750 import digitalio import subprocess def reset_i2c(): subprocess.run(["sudo", "rmmod", "i2c_bcm2835"], capture_output=True) subprocess.run(["sudo", "modprobe", "i2c_bcm2835"], capture_output=True) time.sleep(0.5) i2c = board.I2C() sensor = adafruit_bh1750.BH1750(i2c) led = digitalio.DigitalInOut(board.D18) led.direction = digitalio.Direction.OUTPUT try: while True: print("%.2f Lux"%sensor.lux) led.value = not led.value time.sleep(0.1) except TimeoutError: print("I2C连接超时,正在重置总线...") reset_i2c() # 可选择添加重启脚本的逻辑 except KeyboardInterrupt: led.value = False
5. 检查树莓派系统设置
- 确保
raspi-config中已启用I2C接口(路径:Interfacing Options > I2C) - 更新系统和相关库到最新版本:
sudo apt update && sudo apt upgrade -y pip3 install --upgrade adafruit-circuitpython-bh1750 adafruit-blinka
验证步骤
- 运行修改后的复杂代码,观察是否仍出现TimeoutError
- 若出现错误,执行
i2cdetect -y 1,确认重置总线后设备是否重新出现 - 长期运行测试,确认稳定性
内容的提问来源于stack exchange,提问作者lemmyBarnet
相关产品推荐
相关产品推荐

