stm32四轴飞行器BUG篇

📅 2026/7/4 3:50:58
stm32四轴飞行器BUG篇
偏航推杆导致油门失控问题分析问题现象当偏航YAW推杆推到最大值1820或最小值1180后油门完全失控——油门会自动飙到最大值用户此时只能控制油门在最大值和最小值之间切换无法正常调节油门大小。根本原因pidYaw.desired偏航角期望值没有上限/下限限制在偏航推杆持续处于极限位置时会无限增长/衰减导致外环偏航PID输出暴涨最终通过串级PID传导至电机混控吞掉所有PWM余量油门基线形同虚设。详细分析1. 问题触发路径偏航推杆极限位 (YAW 1820 或 YAW 1180) ↓ FlyPidControl() 每 3ms 调用一次 ↓ pidYaw.desired 持续累加/累减 0.75无上下限 ↓ pidYaw.out kp × (desired - measured) 急剧增大 ↓ pidRateZ.desired pidYaw.out 内环期望值飙升 ↓ pidRateZ.out kp × (pidRateZ.desired - gyro_Z) 内环输出飙升 ↓ 电机混控中 ± pidRateZ.out 成为主导项 ↓ 油门基线 (THR-1000)*0.7 被完全淹没 ↓ 油门失控2. 关键代码位置文件Fly/FlyContrl.c函数FlyPidControl()第 220-227 行if(FlyRecData.YAW1820){pidYaw.desired-0.75f;// 每3ms减0.75每秒减250度}elseif(FlyRecData.YAW1180){pidYaw.desired0.75f;// 每3ms加0.75每秒加250度}问题pidYaw.desired没有任何Limit()约束。如果偏航推杆持续在极限位置 1 秒期望值就会漂移±250 度持续 4 秒就是±1000 度。3. 定量推算失控过程假设偏航推杆推到最大值YAW 1820持续 3 秒时间pidYaw.desiredpidYaw.out (kp6.0)pidRateZ.out (kp2.0)0s0000.5s-125-750-15001.0s-250-1500-30002.0s-500-3000-60003.0s-750-4500-9000电机混控公式FlyContrl_Motor_3ms()第 44-47 行MOTOR1pidRateX.out-pidRateY.out-pidRateZ.out;// -(-9000) 9000 → 限幅到1000MOTOR2pidRateX.outpidRateY.outpidRateZ.out;// (-9000) -9000 → 限幅到0MOTOR3-pidRateX.outpidRateY.out-pidRateZ.out;// -(-9000) 9000 → 限幅到1000MOTOR4-pidRateX.out-pidRateY.outpidRateZ.out;// (-9000) -9000 → 限幅到0结果电机1和3满转(1000)电机2和4停转(0)油门基线(THR-1000)*0.7最大仅700完全被 ±9000 级别的PID输出淹没。无论用户如何操作油门推杆电机输出都被死死限制在 0 或 1000。4. 为什么只能控制油门在最大值到最小值因为Limit()函数将每个电机PWM限制在[0, 1000]范围内。当pidRateZ.out绝对值超过 1000 后电机输出就变成了纯开关量——不是 0 就是 1000中间没有任何过渡。用户推油门时只能看到电机从 0 跳到 1000或反之中间没有任何线性控制区间。修复方案方案一限制pidYaw.desired的范围推荐在FlyPidControl()中对pidYaw.desired添加限幅// 在 FlyPidControl() 的 case 2 中偏航期望值计算后添加if(FlyRecData.YAW1820){pidYaw.desired-0.75f;}elseif(FlyRecData.YAW1180){pidYaw.desired0.75f;}// ★ 添加以下限幅代码 ★if(pidYaw.desired360.0f)pidYaw.desired360.0f;if(pidYaw.desired-360.0f)pidYaw.desired-360.0f;偏航角正常情况下不需要超过 ±360 度的期望值合理限幅即可。方案二将偏航期望值改为绝对位置映射更优当前的累加模式存在漂移问题。更好的做法是将摇杆位置直接映射为偏航角速度期望值// 替换当前的累加逻辑if(FlyRecData.YAW1820){pidRateZ.desired150.0f;// 直接设定期望角速度度/秒而不是不断累加角度}elseif(FlyRecData.YAW1180){pidRateZ.desired-150.0f;}else{pidRateZ.desired0.0f;}这样做的好处偏航期望值不会无限累加摇杆回中后偏航立即停止移除外环偏航角PID简化控制结构这是大多数穿越机/无人机飞控的通用做法——偏航直接控制角速度而非角度方案三对PID输出增加总限幅兜底保护无论采用哪种方案建议在pidUpdate()函数中增加输出限幅voidpidUpdate(PidObject*pid,constfloatdt){// ... 原有计算 ...pid-outpid-kp*errorpid-ki*pid-integpid-kd*deriv;// ★ 增加输出限幅 ★if(pid-out500.0f)pid-out500.0f;if(pid-out-500.0f)pid-out-500.0f;pid-prevErrorerror;}同时在pidRest()中也要重置desired和measuredvoidpidRest(PidObject**pid,constuint8_tlen){uint8_ti;for(i0;ilen;i){pid[i]-integ0;pid[i]-prevError0;pid[i]-out0;pid[i]-desiredpid[i]-measured;// ★ 复位时期望值同步到当前测量值 ★}}额外发现解锁/锁定逻辑的竞争条件在FlyContrl_Unlock_10ms()第 98 行立即锁定条件是if(FlyRecData.THR1100(FlyRecData.YAW1100||FlyRecData.YAW1900))这意味着只有当油门同时也处于低位时偏航极限位才会触发锁定。如果用户在飞行中油门较高时推偏航到极限此条件不满足飞机不会锁定但pidYaw.desired已经开始疯狂漂移——这正是本次bug的触发场景。建议增加一个飞行中偏航极限位的保护逻辑例如检测到pidYaw.desired超过阈值时自动钳位而不是依赖解除锁定。总结项目内容问题根因pidYaw.desired无限累加无上下限保护影响范围偏航推杆极限位时油门完全失控严重程度严重- 飞行中触发会导致炸机推荐修复方案一 方案三双重保护长远考虑方案二重构偏航控制策略修复文件Fly/FlyContrl.cFlyPidControl函数、Fly/pid.cpidUpdate和pidRest函数