树莓派5 Python3读取编码器GPIO报错,求GPIOZero替代实现方案
树莓派5使用GPIOZero读取旋转编码器数据
问题背景
在树莓派5上使用RPi.GPIO库读取编码器数据时,出现错误:RuntimeError: cannot determine SOC peripheral base address。这是因为树莓派5采用了全新的RP1 GPIO控制器,而RPi.GPIO库尚未适配该硬件,因此需要改用官方推荐的GPIOZero库实现功能。
原RPi.GPIO代码:
import RPi.GPIO as GPIO from time import sleep global counter counter = 0 Enc_A = 17 Enc_B = 27 def init(): GPIO.setwarnings(True) GPIO.setmode(GPIO.BCM) GPIO.setup(Enc_A, GPIO.IN) GPIO.setup(Enc_B, GPIO.IN) GPIO.add_event_detect(Enc_A,GPIO.RISING, callback=rotation_decode, bouncetime=1) return def rotation_decode(Ebc_A): global counter Switch_A = GPIO.input(Enc_A) Switch_B = GPIO.input(Enc_B) if (Switch_A == 1) and (Switch_B == 0): counter += 1 print (counter) while Switch_B == 0: Switch_B = GPIO.input(Enc_B) while Switch_B == 1: Switch_B = GPIO.input(Enc_B) return elif (Switch_A == 1) and (Switch_B == 1): counter -= 1 print (counter) while Switch_A == 1: Switch_A = GPIO.input(Enc_A) return else: return def main(): try: init() while True: sleep(1) except KeyboardInterrupt: GPIO.cleanup() if __name__ == '__main__': main()
解决方案(GPIOZero实现)
GPIOZero是树莓派官方推荐的GPIO控制库,原生支持树莓派5的RP1控制器,且API更简洁,自带防抖处理。以下是适配后的编码器读取代码:
from gpiozero import Button from signal import pause # 编码器引脚配置(BCM编号,与原代码一致) ENC_A = Button(17, pull_up=True, bounce_time=0.01) # 防抖时间10ms ENC_B = Button(27, pull_up=True, bounce_time=0.01) counter = 0 last_a_state = ENC_A.is_pressed # 初始化A引脚状态 def update_counter(): global counter, last_a_state current_a = ENC_A.is_pressed current_b = ENC_B.is_pressed # 仅当A引脚状态变化时处理(避免重复触发) if current_a != last_a_state: # 根据A、B引脚的相对状态判断旋转方向 if current_b != current_a: counter += 1 # 正转 else: counter -= 1 # 反转 print(f"当前计数: {counter}") last_a_state = current_a # 为A引脚的按下和释放事件绑定回调 ENC_A.when_pressed = update_counter ENC_A.when_released = update_counter try: pause() # 阻塞程序,等待事件触发 except KeyboardInterrupt: print("\n程序已退出")
代码说明
- 引脚初始化:
Button类默认启用内部上拉电阻(pull_up=True),无需额外配置;bounce_time参数设置防抖时间,避免机械抖动导致的误触发。 - 旋转方向判断:通过对比A、B引脚的实时状态,当A引脚状态变化时,若B引脚状态与A相反则为正转,相同则为反转。
- 事件处理:利用GPIOZero的事件回调机制,无需手动轮询引脚状态,程序效率更高。
- 退出处理:
pause()会保持程序运行,按下Ctrl+C时会触发KeyboardInterrupt,自动清理GPIO资源。
内容的提问来源于stack exchange,提问作者Civil.Shakeri
相关产品推荐
相关产品推荐

