串级PID实战:位置环与速度环的协同控制策略

张开发
2026/4/18 3:11:23 15 分钟阅读

分享文章

串级PID实战:位置环与速度环的协同控制策略
1. 串级PID控制的基本原理我第一次接触串级PID是在做智能小车项目的时候。当时为了让小车能精准走直线和转弯单靠速度环控制总会出现各种问题——要么转弯角度不准要么直线走歪。后来才发现位置环速度环的串级控制才是解决这类问题的银弹。串级PID的核心思想很简单把两个PID控制器像俄罗斯套娃一样嵌套起来。外层的位置环负责宏观规划决定应该以什么速度移动内层的速度环则负责微观执行控制如何达到这个速度。这就好比开车时你先决定要开到80km/h位置环决策然后通过踩油门来实际达到这个速度速度环执行。实际工程中位置环的输出值直接作为速度环的输入目标值。这种层级关系有个重要特性内环速度环的响应速度必须比外环位置环快5-10倍。就像打篮球时大脑先判断投篮角度位置环手臂肌肉快速执行动作速度环。如果肌肉反应比大脑还慢那投篮肯定不准。2. 位置环与速度环的代码实现2.1 速度环的增量式PI控制速度环通常采用增量式PI算法就足够了D参数容易引入噪声。这是我调过最稳的参数组合float Velocity_KP_A400, Velocity_KI_A300; int Incremental_PI_A(float Encoder, float Target) { static float Bias, Pwm, Last_bias; Bias Target - Encoder; //计算偏差 Pwm Velocity_KP_A*(Bias-Last_bias) Velocity_KI_A*Bias; //输出限幅 if(Pwm7200) Pwm7200; if(Pwm-7200) Pwm-7200; Last_bias Bias; //保存上一次偏差 return Pwm; }这里有个工程细节PWM输出限幅非常必要。我有次忘记加限幅电机直接满速撞上障碍物。7200这个值要根据电机驱动器的最大输入调整。2.2 位置环的全量式PID控制位置环建议使用全量式算法KD参数对抑制超调很有效float Location_KP1.2, Location_KI0, Location_KD0.8; int Location_pid(float Encoder, float Target) { static float Bias, Speed, Last_bias, Integral_bias; Bias Target - Encoder; //计算偏差 Integral_bias Bias; //积分项 Speed Location_KP*Bias Location_KI*Integral_bias Location_KD*(Bias-Last_bias); Last_bias Bias; //保存上次偏差 return Speed; }实测发现位置环的KI参数可以设为零因为速度环已经包含积分项。KD参数对转弯场景特别重要——它能预测位置变化趋势提前减速防止过冲。3. 双环协同的工程实践3.1 物理量转换技巧在智能车系统中需要把移动距离和旋转角度转换为编码器脉冲数。这个转换公式很关键#define WD 0.045f //轮胎直径(m) #define MD 20 //电机减速比 #define Hall_13 13 //编码器线数 //距离转脉冲 Target_Encoder distance/(PI*WD)*(EncoderMultiples*MD*Hall_13); //角度转脉冲以90度转弯为例 float spin90_val 0.25*PI*Half_wheelspacing*2; Car_Turn_val spin90_val/(PI*WD)*(EncoderMultiples*MD*Hall_13);这里有个坑不同电机的减速比可能不同。我有次左右轮减速比差5%结果小车永远走不直。后来在代码里为每个电机单独配置了转换系数。3.2 双环串联的实现核心逻辑在Drive_Motor()函数里完成双环串联void Drive_Motor() { //位置环计算目标速度 float A_Target Location_pid(-Encoder_A_sum, Target_Encoder_sum_A); //转换为实际速度值(m/s) MOTOR_A.Target A_Target*CONTROL_FREQUENCY*(WD*PI)/(EncoderMultiples*MD*Hall_13); //速度环计算PWM输出 MOTOR_A.Motor_Pwm Incremental_PI_A(MOTOR_A.Encoder, MOTOR_A.Target); }注意这里的位置环输出要乘以控制频率CONTROL_FREQUENCY因为PID计算的是每个控制周期的增量。我当初漏掉这一步导致小车像喝醉了一样缓慢蠕动。4. 典型场景的参数整定4.1 直线行走调试直线场景下建议这样调参先关闭位置环单独调速度环KP从100开始每次增加100观察电机响应KI设为KP的1/3~1/2消除静差然后加入位置环KP从0.5开始观察小车是否快速响应KD从0.5开始抑制终点振荡调试时可以用手机慢动作录像观察车轮启动/停止时的抖动情况。我的经验值是速度环KP400/KI300位置环KP1.2/KD0.8时最稳。4.2 旋转运动调试转弯时需要特别注意内外轮速差要合理//左转时右轮正转左轮反转 MOTOR_A.Target -abs(MOTOR_A.Target); MOTOR_C.Target abs(MOTOR_C.Target);降低转向时的速度限幅//直线速度限幅1m/s转向限幅0.5m/s float amplitude1, Turn_amplitude0.5;位置环KD参数要加大我调180度转向时KD从0.8加到1.5才不超调5. 常见问题排查遇到过最头疼的问题是小车到达目标点后抖动。排查发现几个关键点编码器消抖在中断服务函数里加20ms的软件滤波if(filter_count 2){ //3次检测一致才更新 Encoder_Real Encoder_Temp; filter_count 0; }控制周期一致性用硬件定时器确保100Hz的控制频率HAL_TIM_Base_Start_IT(htim3); //10ms定时中断机械结构检查有次发现电机联轴器打滑导致编码器读数不准还有个经验位置环完成判断要留余量。比如理论上需要1000个脉冲到达目标实际判断用990个脉冲就认为完成这样可以避免系统在临界点振荡。if(Encoder_A_sum (Target_Encoder*0.99)){ //认为位置环已完成 }这套控制方案在四轮智能车上实测直线行走误差1cm90度转向误差3度。关键是要耐心调参建议准备个笔记本记录每次参数修改的效果。

更多文章