树莓派控制MG995 360°舵机 程序结束后持续转动故障咨询
问题描述
我购买了MG995 55g 360°舵机,尝试使用树莓派对其进行控制,所用代码如下:
from gpiozero import Servo from time import sleep from gpiozero.pins.pigpio import PiGPIOFactory factory = PiGPIOFactory() myGPIO = 12 servo = Servo(myGPIO, min_pulse_width=0.9/1000, max_pulse_width=2.1/1000, pin_factory=factory) try: print("start in the middle") servo.mid() sleep(5) print("go to min") servo.min() sleep(5) print("go to max") servo.max() sleep(5) print("and back to the middle") servo.mid() sleep(5) except KeyboardInterrupt: print("keyboard interrupt") except: print("some error") finally: print("finishing...") servo.value = None
程序运行结束后,舵机开始持续转动,或是在随机时间移动到随机位置,只有拔掉舵机供电线才能使其停止,该故障是什么原因导致的,该如何解决?
故障原因
- 硬件类型适配错误:MG995 360°版本为连续旋转舵机,控制逻辑和常规180°位置舵机存在本质区别:位置舵机的PWM信号对应目标角度,到位后自动锁止,无有效信号时保持阻尼静止;连续旋转舵机的PWM信号仅对应转向和转速,不存在位置锁止逻辑,信号线只要出现符合频率范围的电平波动就会触发转动。
- 引脚浮空引入干扰:代码末尾
servo.value = None会触发gpiozero释放对应GPIO控制权,引脚进入高阻浮空状态,无固定输出电平,此时信号线会耦合空间电磁干扰、板上电源杂波产生无效PWM信号,被舵机误判为控制指令,就会出现随机转动、持续空转的现象。 - 供电设计不符合要求:MG995舵机堵转峰值电流可达2A以上,若直接通过树莓派GPIO引脚的5V端口给舵机供电,树莓派板载供电回路无法满足电流需求,会导致GPIO输出电平漂移、PWM波形失真,不仅会引发舵机失控,还存在烧坏树莓派引脚、拉崩系统的风险。
解决方法
按优先级依次操作即可:
- 修正供电方案
舵机必须使用独立外部5V/3A以上规格的电源供电,禁止直接从树莓派GPIO引脚取电。外部电源的GND必须和树莓派的GND引脚共地,否则控制信号无参考电平,舵机无法正常识别指令。 - 调整程序逻辑
优先使用gpiozero专门为连续旋转舵机封装的ContinuousRotationServo类,默认脉宽参数即可匹配MG995的停止/转动逻辑,无需手动校准:value属性取值范围为-1~1,对应全速反转到全速正转,取值0时舵机停止。
程序退出时不要直接释放GPIO引脚,先输出1~2秒的停止信号(对应1.5ms脉宽,即value=0/中位状态);如果需要程序退出后舵机保持静止,不要执行引脚释放操作,持续输出停止信号即可;如果必须释放引脚,要同步切断舵机供电回路。
修正后的参考代码如下:from gpiozero import ContinuousRotationServo from time import sleep from gpiozero.pins.pigpio import PiGPIOFactory factory = PiGPIOFactory() myGPIO = 12 servo = ContinuousRotationServo(myGPIO, min_pulse_width=0.9/1000, max_pulse_width=2.1/1000, pin_factory=factory) try: print("start stopped") servo.value = 0 # 输出停止信号 sleep(5) print("full speed reverse") servo.value = -1 # 全速反转 sleep(5) print("full speed forward") servo.value = 1 # 全速正转 sleep(5) print("back to stop") servo.value = 0 sleep(2) # 留足时间确保舵机接收到停止指令 except KeyboardInterrupt: print("keyboard interrupt") servo.value = 0 sleep(0.5) except Exception as e: print(f"runtime error: {e}") servo.value = 0 sleep(0.5) finally: print("finishing...") # 保持停止信号输出,不要执行servo.value = None或servo.close()释放引脚 # 若必须释放引脚,请先切断舵机电源再执行释放操作 - 硬件抗干扰优化
如果调整程序后仍存在偶发误转,可在舵机信号线和GND之间焊接一个10kΩ下拉电阻,引脚浮空时信号线会被强制拉到低电平,不会耦合杂波产生误触发信号。
内容的提问来源于stack exchange,提问作者Bird
相关产品推荐
相关产品推荐

