4、电机控制核心:PID速度闭环控制、位置环与速度环、PID参数整定方法、梯形加减速算法
做差速底盘,最绕不开的就是电机控制。说白了,轮子转得稳不稳,车才能走得直不直。我刚开始做机器人那会儿,以为给个PWM信号轮子就能听话,结果一跑起来,左右轮转速差得离谱,车原地打转。嗯,从那以后我才真正开始啃PID这块硬骨头。
这一章,咱们就把电机控制的核心掰开揉碎。你想想看,一个轮子要转得又快又准,背后需要哪几层功夫?
核心逻辑:电机控制不是简单给电压,而是形成一个闭环——测量实际转速,跟目标转速比较,算出误差,再用算法去修正。这个闭环就是PID的舞台。
4.1 PID速度闭环控制——让轮子听话的基础
PID,比例-积分-微分控制。名字听着唬人,其实道理很简单。你设定一个目标速度,比如每秒转10圈。编码器反馈回来实际速度,比如只有8圈。差了2圈,这就是误差。
PID要做的,就是根据这个误差,算出一个控制量,去调节PWM占空比,让实际速度追上目标速度。
公式长这样:
输出 = Kp * 误差 + Ki * 误差积分 + Kd * 误差微分
我习惯把三个环节拆开理解:
- 比例项(P):误差越大,输出越大。好比车跑慢了,你多踩点油门。但光有P,系统会震荡,永远到不了目标值——这就是稳态误差。
- 积分项(I):把过去的误差累加起来。误差一直存在,积分就一直增长,直到把误差消除。我在项目中遇到过,积分项太强会导致“积分饱和”,电机响应变慢,甚至超调严重。
- 微分项(D):预测误差的变化趋势。误差突然变大,微分项会提前刹车,抑制震荡。说白了就是“预见性控制”。
我的习惯:调试时先把I和D设为0,只调P。让系统刚好不震荡,再加一点I消除稳态误差。最后加D抑制超调。三步走,稳得很。
4.2 位置环与速度环——串级控制的艺术
差速底盘不仅要控制速度,还要控制位置。比如让机器人前进1米,或者旋转90度。这时候就需要位置环了。
位置环和速度环是串在一起的。我画个逻辑给你看:
目标位置 → [位置环] → 目标速度 → [速度环] → PWM → 电机 → 实际位置
↑
编码器反馈速度
↑
编码器反馈位置
外环是位置环,内环是速度环。位置环的输出,就是速度环的目标值。为什么这么设计?
你想想看,如果只用一个位置环,电机从静止直接冲到目标位置,很容易过冲。加上速度环之后,位置环告诉速度环“慢慢来”,速度环再平滑地控制电机。这样位置控制既准又稳。
我曾经在一个AGV项目里,只用单环位置控制,结果每次停车都前后晃好几下。改成串级之后,停车稳得像钉在地上一样。
注意:内环(速度环)的响应频率一定要比外环(位置环)快。一般速度环运行频率是位置环的5~10倍。否则外环已经发出指令了,内环还没反应过来,系统就会失控。
4.3 PID参数整定方法——调参是个手艺活
调PID参数,说白了就是找平衡。P太大,系统震荡;I太大,响应变慢;D太大,噪声放大。怎么找到那个“刚刚好”的点?
我常用的方法有三种:
| 方法 | 适用场景 | 操作步骤 |
|---|---|---|
| 试凑法 | 经验丰富时快速调参 | 先P后I再D,每次调一个参数,观察响应曲线 |
| 临界比例度法 | 系统容易进入等幅震荡 | 只加P,增大到系统等幅震荡,记录临界增益Ku和周期Tu |
| Ziegler-Nichols法 | 需要公式化整定 | 根据Ku和Tu查表计算Kp、Ki、Kd |
我个人最常用试凑法。为什么?因为实际电机系统总有非线性因素,公式算出来的参数往往还要微调。不如直接上手调,心里更有数。
具体步骤:
- 把I和D设为0,P从0慢慢增大。观察电机响应,直到出现轻微震荡。
- 把P往回退一点,让震荡消失。这时候P基本合适。
- 加一点I,消除稳态误差。注意I不要太大,否则响应变慢。
- 最后加D,抑制超调。D值一般很小,0.1~0.5就够。
避坑指南:我曾经调一个直流有刷电机,P加到很大都不震荡,后来发现是编码器分辨率太低,反馈延迟太大。换了个高分辨率编码器,P值立马降下来了。所以调参之前,先确认传感器没问题。
4.4 梯形加减速算法——让电机平滑启停
差速底盘最怕什么?急启动、急刹车。轮子突然从0转到1000转,电机电流瞬间飙升,搞不好还会丢步。梯形加减速就是解决这个问题的。
梯形加减速,顾名思义,速度曲线像个梯形:
- 加速段:速度从0线性增加到目标速度
- 匀速段:保持目标速度运行
- 减速段:速度从目标速度线性降到0
代码实现也不复杂。我贴一段核心逻辑:
// 梯形加减速核心计算
float calc_target_speed(float current_speed, float target_speed,
float accel, float decel, float distance) {
// 加速段
if (current_speed < target_speed) {
current_speed += accel * dt;
if (current_speed > target_speed) current_speed = target_speed;
}
// 减速段判断:剩余距离是否足够减速
float stop_distance = (current_speed * current_speed) / (2 * decel);
if (remaining_distance <= stop_distance) {
current_speed -= decel * dt;
if (current_speed < 0) current_speed = 0;
}
return current_speed;
}
这里有个关键点:减速点的判断。什么时候开始减速?我习惯用“剩余距离是否小于等于减速所需距离”来判断。这样不管目标速度怎么变,都能准确地在终点停下来。
我的经验:加速度和减速度可以不一样。比如加速用0.5m/s²,减速用0.8m/s²。减速稍微快一点,可以让停车更干脆。但别太快,否则惯性会把车上的东西甩出去。
梯形加减速和PID是配合使用的。加减速算法生成平滑的目标速度曲线,PID再去跟踪这个曲线。一个负责“规划”,一个负责“执行”,缺一不可。
嗯,这一章的内容就到这儿。电机控制的核心,说白了就是让轮子按照你想要的节奏去转。PID是执行器,加减速是规划器,两者配合好了,差速底盘才能走得直、转得准、停得稳。
公众号:蓝海资料掘金营,微信deep3321