这一章在干嘛?

梯形加减速在变速转折点不平滑,启动/停止冲击大。S 形曲线把加速度也做成渐变,冲击噪音更小、启停更柔和,适合精密搬运。本章用五段式模型 + 查表法实现,适合资源紧张的嵌入式系统。

17.1 从梯形到 S 形

17.2 原理:加加速度 J 与速度表

17.3 控制实现:中断查表输出

17.1 从梯形到 S 形

传统 S 曲线是七段式(加加速、恒加速、减加速、匀速、加减速、恒减速、减减速),参数复杂。本章简化为五段式并令 T1=T2、T4=T5:

原书图 17.2.1 原书图 17.2.1:S 曲线加减速七段式模型

原书图 17.2.2 原书图 17.2.2:S 曲线加减速五段式模型

五段:加加速段(加速度 a 从 0 升到最大)→ 减加速段(a 从最大降回 0,速度仍在增加)→ 匀速 → 加减速 → 减减速。减速段与加速段完全对称(速度倒序),只需算一半。

对比梯形S 形
加速度突变(阶跃)连续渐变
冲击/噪音较大
启停耗时
典型应用定长送料、打印机精密工件搬运

17.2 原理:加加速度 J 与速度表

核心量是加加速度 J(加速度的变化率)。加加速段 ,积分得 ,再积分得位移:

加速度达到最大值时速度恰好走到中点速度 ,于是 。减加速段 ,位移 ,加速段总步数

S 形比梯形好算的地方:

速度的倒数就是每步周期,——不需要梯形那套开方递推!程序里离线算好一张「速度表」,中断里查表即可。

/* 生成 S 形速度表:jerk = 2*(vm-vo)/time^2,逐点填表 */
vm = (g_calc_t.vo + g_calc_t.vt) / 2;                    /* 中点速度 */
jerk = fabs(2.0f * (vm - g_calc_t.vo) / (time * time));  /* 加加速度 */
inc_acc_stp = (int32_t)(g_calc_t.vo * time + INCACCELSTEP(jerk, time)); /* S1 */
dec_acc_stp = (int32_t)((g_calc_t.vt + g_calc_t.vo) * time - inc_acc_stp);
velocity_tab = (float*)mymalloc(SRAMIN, (accel_step + 1) * sizeof(float));
ti_cube = 6.0f * 1.0f / jerk;          /* 第 1 步时间: ti^3 = 6*1/jerk */
ti = pow(ti_cube, (1 / 3.0f));
sum_t += ti;
delta_v = 0.5f * jerk * pow(sum_t, 2);
velocity_tab[0] = g_calc_t.vo + delta_v;   /* 第一步速度 */

for (i = 1; i < accel_step; i++) {
    ti = 1.0f / velocity_tab[i-1];         /* 每步时间 ti = 1/Vn-1 */
    sum_t += ti;
    if (i < inc_acc_stp) {                 /* 加加速段 */
        delta_v = 0.5f * jerk * pow(sum_t, 2);
        velocity_tab[i] = g_calc_t.vo + delta_v;
    } else {                               /* 减加速段 */
        delta_v = 0.5f * jerk * pow(fabs(time - sum_t), 2);
        velocity_tab[i] = g_calc_t.vt - delta_v;
    }
}

17.3 控制实现:中断查表输出

状态机 STATE_ACCEL → STATE_AVESPEED → STATE_DECEL → STATE_STOP。速度表动态申请(mymalloc),加减速完成后必须 myfree 释放。翻转模式下比较值再除 2:

case STATE_ACCEL:   /* 中断中查表输出脉冲 */
    Tim_Pulse = T1_FREQ / (*g_calc_t.ptr);   /* Cn = ft / vn,查表 */
    g_calc_t.ptr++;
    Toggle_Pulse = (uint16_t)(Tim_Pulse / 2); /* 翻转模式除以 2 */
    if (g_calc_t.step_pos >= g_calc_t.accel_step) {
        myfree(SRAMIN, g_calc_t.accel_tab);   /* 释放加速表内存 */
        g_motor_sta = STATE_AVESPEED;         /* 进入匀速段 */
    }
    break;

实验硬件与第 16 章完全相同(接口三、8 细分 1600 脉冲/圈)。KEY0 开启 S 形加减速(stepmotor_move_rel(V_START, V_END, ACCELTIME, DECELTIME, g_step_angle*SPR)),KEY1/KEY2 增减步数(1~50 循环)。注意:总步数必须 ≥ 加速步数 + 减速步数,否则报「参数设置错误」。现象:与梯形相比启停明显更柔和、冲击更小