4. 运动控制基础

梯形速度曲线,说白了就是运动控制里最基础、最常用的速度规划方式。你想想看,名字里带「梯形」,是因为它的速度-时间图像长得像个梯形——匀加速、匀速、匀减速三段。我在刚入行那会儿,第一个上手的电子凸轮项目用的就是梯形曲线,简单、直观、好调。

但简单归简单,里面坑也不少。今天咱们就把它的原理、数学模型和加减速控制掰开揉碎了讲清楚。

4.1 梯形速度曲线的原理

梯形速度曲线的核心思想就一句话:让速度按固定斜率上升,保持一段时间,再按固定斜率下降。整个过程分为三个阶段:

  • 加速段:从初始速度 v₀ 匀加速到目标速度 v_max
  • 匀速段:以 v_max 匀速运行
  • 减速段:从 v_max 匀减速到终止速度 vₑ(通常 vₑ = v₀)

为什么叫「梯形」?你把速度画出来,横轴是时间,纵轴是速度,三段连起来就是个梯形。如果加速时间和减速时间相等,那就是个等腰梯形。如果距离太短,连匀速段都没有,那就变成三角形了——嗯,这种情况我后面会讲。

关键点:梯形曲线的加速度是分段常数。加速段 a = a_max,匀速段 a = 0,减速段 a = -a_max。加速度突变发生在拐点处,这是梯形曲线的一个固有缺陷。

4.2 数学模型

搞运动控制,数学是躲不开的。不过别怕,梯形曲线的数学很简单,初中物理水平就够了。

咱们先定义几个参数:

符号 含义 单位
v₀ 初始速度 mm/s 或 deg/s
v_max 目标速度(最大速度) mm/s 或 deg/s
vₑ 终止速度 mm/s 或 deg/s
a_max 最大加速度 mm/s² 或 deg/s²
t_a 加速时间 s
t_d 减速时间 s
t_c 匀速时间 s
S 总位移 mm 或 deg

加速段时间:

t_a = (v_max - v₀) / a_max

减速段时间:

t_d = (v_max - vₑ) / a_max

加速段位移:

S_a = v₀ * t_a + 0.5 * a_max * t_a²

减速段位移:

S_d = v_max * t_d - 0.5 * a_max * t_d²

匀速段位移:

S_c = S - S_a - S_d

匀速段时间:

t_c = S_c / v_max

总时间:

T = t_a + t_c + t_d

我的习惯:在实际项目中,我一般先算 S_a + S_d,如果这个值已经大于等于总位移 S,那就说明没有匀速段了。这时候要重新算,变成三角形曲线。我曾经在一个贴标机项目里吃过这个亏——没判断边界条件,结果算出来的匀速时间是负数,电机直接报错。

4.3 加减速控制策略

梯形曲线的加减速控制,说白了就是怎么把上面那套数学公式变成实际可执行的指令。这里有几个关键点:

4.3.1 对称 vs 非对称加减速

对称加减速:t_a = t_d,v₀ = vₑ。这是最常见的情况,计算简单,曲线对称好看。

非对称加减速:t_a ≠ t_d,v₀ ≠ vₑ。比如启动时负载轻可以加速快,停止时负载重需要减速慢。我在一个包装机项目里就遇到过——空载启动加速很快,但满载停止时惯性大,减速必须拉长,不然会过冲。

4.3.2 速度规划流程

实际写代码时,我一般按这个步骤来:

  1. 输入参数:v₀, v_max, vₑ, a_max, S
  2. 计算 t_a 和 t_d:用上面的公式
  3. 计算 S_a 和 S_d:判断是否超过总位移
  4. 分支处理:
    • 如果 S_a + S_d < S:有匀速段,正常梯形
    • 如果 S_a + S_d ≥ S:无匀速段,退化为三角形
  5. 生成速度曲线:按时间分段输出速度值

我曾经踩过的坑:梯形曲线在加速段结束和减速段开始的时刻,加速度会突变。这种突变会产生冲击力(加加速度无穷大),在高速高精度场合会引起振动。如果你做的是半导体设备或精密加工,建议用 S 形曲线代替梯形曲线。

4.4 梯形曲线的代码实现

下面是一个简单的梯形速度规划函数,C 语言风格,方便移植到嵌入式系统:

typedef struct {
    float v0;      // 初始速度
    float v_max;   // 最大速度
    float ve;      // 终止速度
    float a_max;   // 最大加速度
    float S;       // 总位移
    float t_a;     // 加速时间
    float t_d;     // 减速时间
    float t_c;     // 匀速时间
    float T;       // 总时间
} TrapezoidProfile;

int TrapezoidPlan(TrapezoidProfile *p) {
    float S_a, S_d, S_c;
    
    // 计算加速和减速时间
    p->t_a = (p->v_max - p->v0) / p->a_max;
    p->t_d = (p->v_max - p->ve) / p->a_max;
    
    // 计算加速和减速位移
    S_a = p->v0 * p->t_a + 0.5f * p->a_max * p->t_a * p->t_a;
    S_d = p->v_max * p->t_d - 0.5f * p->a_max * p->t_d * p->t_d;
    
    // 判断是否有匀速段
    if (S_a + S_d >= p->S) {
        // 三角形曲线,需要重新计算最大速度
        // 这里简化处理,实际需要解二次方程
        p->t_c = 0;
        // 实际项目中需要重新计算 v_max
        return -1;  // 需要重新规划
    }
    
    S_c = p->S - S_a - S_d;
    p->t_c = S_c / p->v_max;
    p->T = p->t_a + p->t_c + p->t_d;
    
    return 0;
}

// 获取某时刻的速度
float GetTrapezoidSpeed(TrapezoidProfile *p, float t) {
    if (t <= p->t_a) {
        // 加速段
        return p->v0 + p->a_max * t;
    } else if (t <= p->t_a + p->t_c) {
        // 匀速段
        return p->v_max;
    } else if (t <= p->T) {
        // 减速段
        float t_dec = t - p->t_a - p->t_c;
        return p->v_max - p->a_max * t_dec;
    } else {
        return p->ve;  // 结束
    }
}

我建议:实际项目中,梯形曲线的计算最好放在上位机或预处理阶段完成,把速度-时间表下发给运动控制器。如果必须在控制器里实时计算,注意浮点数精度问题——我曾经在 STM32 上遇到过因为浮点运算太慢导致速度曲线抖动的案例,后来改成定点数才解决。

4.5 梯形曲线的知识体系

下面这张图是我自己总结的梯形速度曲线知识框架,方便你理解各个知识点之间的关系:

梯形速度曲线知识体系 梯形速度曲线知识体系 梯形速度曲线 匀加速原理 匀速保持原理 匀减速原理 速度-时间公式 位移-时间公式 加速度分段常数 对称/非对称加减速 边界条件判断 三角形曲线退化 代码实现与参数整定 冲击力与振动抑制 梯形曲线是电子凸轮最基础的加减速模型,掌握它才能理解更复杂的 S 形曲线和多项式曲线

4.6 实际项目中的注意事项

最后,分享几个我在实际项目中积累的经验:

  • 加速度不能设太大:理论上加速度越大加速越快,但实际受限于电机扭矩和机械结构刚性。我见过有人把加速度设到理论值的 80%,结果电机堵转报警。
  • 注意速度单位换算:电子凸轮里常用 deg/s,但机械传动比换算到末端可能是 mm/s。搞混单位会出大问题——我曾经在调试时把 deg/s 当成了 mm/s,结果轴直接飞出去了。
  • 梯形曲线适合低速场合:如果速度不高、负载不大、精度要求一般,梯形曲线完全够用。但高速高精度场合,建议用 S 形曲线或多项式曲线。
  • 别忘了加安全余量:理论计算出来的加减速时间,实际跑的时候建议留 10%-20% 的余量。机械磨损、温度变化都会影响实际性能。

重要提醒:梯形曲线的加速度突变会产生加加速度(Jerk)无穷大的问题。如果你发现设备在加减速切换时有明显振动或异响,先检查是不是梯形曲线引起的。如果是,考虑改用 S 形曲线或者限制加加速度值。

嗯,梯形速度曲线就讲到这里。内容不多,但都是干货。你把这个搞明白了,后面学 S 形曲线和多项式曲线就会轻松很多。