4、运动控制层:梯形加减速算法、S形加减速算法、位置与速度模式切换

各位同学,今天我们聊聊运动控制层。这一层说白了,就是决定电机怎么跑、跑多快、什么时候停。我做了这么多年步进电机驱动,发现很多工程师把精力都放在底层驱动上,结果上层运动规划一塌糊涂,电机跑起来不是抖就是丢步。嗯,今天咱们就把这块掰开揉碎了讲清楚。

4.1 梯形加减速算法:简单但够用

梯形加减速,顾名思义,速度曲线像个梯形。加速段、匀速段、减速段,三段式结构。我个人习惯把它叫做「入门级运动规划」,因为实现起来确实简单,资源消耗也小。

核心思路是这样的:

  • 加速阶段:从起始速度开始,每个周期增加一个固定的加速度值,直到达到目标速度。
  • 匀速阶段:保持目标速度运行。
  • 减速阶段:从目标速度开始,每个周期减少一个固定的减速度值,直到降为停止速度。

代码实现其实不复杂,我贴一段我项目里用过的伪代码:

// 梯形加减速状态机
typedef enum {
    ACCEL_PHASE,
    CRUISE_PHASE,
    DECEL_PHASE,
    STOP_PHASE
} motion_phase_t;

void trapezoidal_plan(motion_ctx_t *ctx) {
    switch(ctx->phase) {
        case ACCEL_PHASE:
            ctx->current_speed += ctx->accel;
            if(ctx->current_speed >= ctx->target_speed) {
                ctx->current_speed = ctx->target_speed;
                ctx->phase = CRUISE_PHASE;
            }
            break;
        case CRUISE_PHASE:
            // 检查是否需要开始减速
            if(need_to_decel(ctx)) {
                ctx->phase = DECEL_PHASE;
            }
            break;
        case DECEL_PHASE:
            ctx->current_speed -= ctx->decel;
            if(ctx->current_speed <= ctx->stop_speed) {
                ctx->current_speed = 0;
                ctx->phase = STOP_PHASE;
            }
            break;
        default:
            break;
    }
}
我的经验:梯形加减速最大的坑在于「减速点计算」。我曾经在一个3D打印机项目里,因为减速点算晚了,电机直接撞到限位才停下来。后来我加了个「提前减速距离」的预判逻辑,才彻底解决。建议你在减速阶段预留10%~20%的余量。

4.2 S形加减速算法:丝滑但费资源

梯形加减速有个硬伤——加速度突变。加速刚开始那一下,电机猛地一抖,这就是「急动度」问题。S形加减速就是为了解决这个。

S形加减速的核心是:加速度本身也是平滑变化的。它把加速段又分成了「加加速」、「匀加速」、「减加速」三个阶段。减速段同理。整个速度曲线看起来像个拉长的S。

数学上,S形曲线通常用七段式描述:

阶段 加速度变化 速度变化
加加速 加速度从0线性增加到最大 速度二次上升
匀加速 保持最大加速度 速度线性上升
减加速 加速度从最大线性减到0 速度二次上升(变缓)
匀速 加速度为0 速度恒定
加减速 加速度从0线性减到负最大 速度二次下降
匀减速 保持负最大加速度 速度线性下降
减减速 加速度从负最大线性升到0 速度二次下降(变缓)

你想想看,七段状态机,每段都要算当前速度、位置、加速度,计算量比梯形大了好几倍。但换来的是电机运行极其丝滑,几乎没有抖动。

注意:S形加减速对MCU的算力要求较高。我曾经在Cortex-M0上跑S形曲线,结果CPU占用率飙到80%以上,其他任务全被卡死了。后来我改用查表法,把预计算的S形曲线数据存到Flash里,运行时直接查表插值,才把CPU占用降下来。如果你的MCU资源紧张,建议用查表法。

4.3 位置模式与速度模式切换

实际项目中,电机不可能永远只跑一种模式。比如一个机械臂,粗定位时用速度模式快速移动,精定位时切到位置模式慢慢对准。这就涉及模式切换。

位置模式:目标是到达指定位置。控制器根据当前位置和目标位置的差值,实时调整速度。说白了就是「我要去那里,不管多快,到了就行」。

速度模式:目标是达到指定速度。控制器只管加速到目标速度并保持,至于跑了多远,不关心。说白了就是「我要跑这么快,至于跑到哪,再说」。

模式切换时最容易出问题的是「速度跳变」。举个例子:你在速度模式下以1000rpm运行,突然切到位置模式,位置环发现当前位置和目标位置差很远,直接给一个很大的速度指令,电机瞬间从1000rpm跳到3000rpm——结果就是丢步甚至过冲。

我建议的切换策略是这样的:

  1. 切换前先减速:无论从哪个模式切,先把当前速度降到安全阈值以下。
  2. 平滑过渡:在切换瞬间,把当前速度作为新模式的初始速度,避免突变。
  3. 加个软切换标志:不要硬切,而是设置一个切换请求标志,等当前运动周期结束后再执行切换。

核心要点总结:

  • 梯形加减速:简单、资源少,适合对平滑度要求不高的场景。
  • S形加减速:丝滑、无抖动,适合精密定位和高速运动。
  • 模式切换:注意速度平滑过渡,避免突变导致丢步。

好了,这一章的内容就这些。下一章我们会讲「闭环控制与堵转检测」,到时候我会分享一个我踩过的坑——用电流检测判断堵转,结果被反电动势干扰得怀疑人生。嗯,到时候细聊。