树莓派RP2040执行move_motor后警报立即触发问题求助
问题描述
我正在编写用于远程控制电机转速的代码,出于安全考虑,设置电机在收到指令后1秒内未收到新指令则停止运行。定义的motor结构体如下:
motor mt = { .m_pwm_pin=M_PWM, .timeout=1000, .freq=50.0, .cycle_time=0.000000008, .divider=256.0, .forward_period=2.0, .neutral_period=1.5, .backward_period=1.0, .motor_kv=2150 };
核心控制代码如下:
int64_t cb_stop_motor(long id, void *mot) { motor *m = mot; stop_motor(m); return 0; } int stop_motor(motor *m) { gpio_put(16, 1); pwm_set_chan_level(m->slice, PWM_CHAN_B, getDuty(m->neutral_period)); return 0; } int move_motor(motor *m, int rpm) { double period_per_rpm; double m_period; if (rpm == 0) { stop_motor(m); } else if (rpm < 0) { period_per_rpm = (m->neutral_period - m->backward_period) / ((double) m->motor_kv); m_period = m->neutral_period - (period_per_rpm * (double) rpm * -1.0); } else if (rpm > 0) { period_per_rpm = (m->forward_period - m->neutral_period) / ((double) m->motor_kv); m_period = m->neutral_period + (period_per_rpm * (double) rpm); } pwm_set_chan_level(m->slice, PWM_CHAN_B, getDuty(m_period)); cancel_alarm(m->alarm_id); m->alarm_id = add_alarm_in_ms(m->timeout, cb_stop_motor, m, true); }
当前遇到的问题:执行move_motor指令后警报会立即触发,通过示波器观察到PWM周期瞬间变为1.72ms后又回到1.5ms。
问题排查与分析
以下是可能导致该异常的几个原因:
alarm_id未初始化:motor结构体中的alarm_id字段如果没有初始化为平台定义的无效值(比如0),第一次调用cancel_alarm(m->alarm_id)时会传入随机的内存值,可能误取消了系统中已存在的有效警报,触发异常逻辑导致当前警报被错误执行。add_alarm_in_ms参数误用:检查最后一个重复触发参数,若平台中true表示立即触发一次再进入周期,而你需要的是单次超时停止,参数传递错误会导致警报立即执行。另外部分平台要求回调返回非0值终止重复触发,当前返回0配合true参数可能引发冲突。m_period计算异常:当传入的rpm值过大时,计算出的m_period可能超出合理范围,导致getDuty返回错误的占空比,PWM异常触发系统保护逻辑,间接调用stop_motor。可在设置PWM前打印m_period值,确认是否为示波器捕捉到的1.72ms。- GPIO操作干扰:
stop_motor中的gpio_put(16, 1)若与电机控制、PWM模块存在联动,可能在设置PWM后触发意外中断或状态变化,导致停止逻辑被提前调用。可暂时注释该行代码测试是否恢复正常。 - 警报API精度问题:部分平台的
add_alarm_in_ms存在时间戳初始化异常,导致超时时间被判定为已过期,触发立即执行回调。
内容的提问来源于stack exchange,提问作者lasb3tas
相关产品推荐
相关产品推荐

