使用Adafruit adafruit_servokit库设置舵机角度时触发ZeroDivisionError错误
解决PCA9685舵机控制的ZeroDivisionError问题
你遇到的这个错误是因为同时初始化了两个PCA9685控制实例导致的硬件寄存器冲突,进而触发了除以0的异常。我来拆解下原因和具体的解决方案:
错误原因分析
你的代码里同时创建了adafruit_pca9685.PCA9685对象(pca)和ServoKit对象(kit),这两个对象都会直接操作同一个PCA9685硬件板。当你设置pca.frequency = 60后,创建ServoKit时它会重新初始化PCA9685的寄存器,这会干扰之前的频率设置,最终导致prescale_reg(预分频寄存器)被置为0,在计算频率时就出现了ZeroDivisionError。
其实ServoKit内部已经封装了PCA9685的所有操作逻辑,完全不需要再单独初始化一次PCA9685。
修正方案
你只需要选择一种方式来控制硬件,不要混用两个实例。这里提供两种可行的写法:
方案1:只用ServoKit同时控制LED和舵机
ServoKit内部已经包含了PCA9685的控制逻辑,你可以直接通过它的内部属性来操作LED通道:
from adafruit_servokit import ServoKit # 初始化ServoKit,自动处理I2C连接和PCA9685初始化 kit = ServoKit(channels=16) # 设置舵机常用的60Hz频率 kit._pca.frequency = 60 # 控制8号通道的LED(0x7FFF是50%占空比,对应中等亮度) kit._pca.channels[8].duty_cycle = 0x7FFF # 控制2号通道的舵机转到180度 kit.servo[2].angle = 180
方案2:直接使用PCA9685和Servo类
如果你更倾向于底层控制,可以直接用PCA9685对象配合Servo类来操作:
import board import busio import adafruit_pca9685 from adafruit_motor.servo import Servo # 初始化I2C总线和PCA9685 i2c = busio.I2C(board.SCL, board.SDA) pca = adafruit_pca9685.PCA9685(i2c) pca.frequency = 60 # 控制8号通道的LED pca.channels[8].duty_cycle = 0x7FFF # 初始化2号通道的舵机对象 servo = Servo(pca.channels[2]) # 设置舵机角度 servo.angle = 180
额外注意事项
- 确保你的PCA9685有足够的外部电源:舵机的耗电量远大于LED,不要只靠树莓派的USB供电给PCA9685,否则可能出现供电不足导致的硬件异常。
- 检查舵机的接线:信号脚接PCA9685的2号通道,电源和地线要对应接好,接反可能损坏舵机或驱动板。
内容的提问来源于stack exchange,提问作者Pascal Burkard
相关产品推荐
相关产品推荐

