📖 第 18 章:步进电机直线插补(Linear Interpolation)

⚙️ 正点原子《DMF407 电机控制专题教程》V1.0 · Chapter 18
🗨️ 本章金句:「两点之间直线最短,但两台电机得商量着走。」
这一章在干嘛? 单轴只能走横平竖直,画斜线必须 X/Y 两台电机「联合作业」。本章讲数控领域最经典的逐点比较法直线插补:每走一步判一次偏差,用小折线逼近直线,最后用两轴平台画出一个正方形。
18.1 插补是什么18.2 逐点比较法四步循环18.3 四象限扩展18.4 实验实现:两轴平台画正方形

18.1 插补是什么

已知起点和终点,数控装置按算法把中间点「数据密化」出来,刀具实际沿小折线走,宏观上就是那条直线——这个过程叫插补。

原书图 18.1.1
原书图 18.1.1:直线插补图示:折线逼近直线
大类思路适用
脉冲增量插补(行程标量)每次插补输出一个行程增量脉冲,脉冲当量 = 一个脉冲的移动量步进电机开环系统
数字增量插补(时间标量)粗插补算各轴增量 + 精插补出速度指令闭环/半闭环系统

脉冲增量法里有逐点比较法、数字积分法、最小偏差法等,本章主角是逐点比较法:每走一步都与规定图形比较一次,偏了就往回「找补」。

18.2 逐点比较法四步循环

四个步骤周而复始:① 偏差判别 → ② 坐标进给 → ③ 偏差计算 → ④ 终点判别

原书图 18.3.1.1
原书图 18.3.1.1:逐点比较法流程图
原书图 18.3.2.1
原书图 18.3.2.1:第一象限直线插补示意图

设直线终点 $(X_e, Y_e)$、动点 $P(X_i, Y_i)$,偏差判别式

$$F_i = X_e\,Y_i - X_i\,Y_e$$

偏差递推(免乘法,只用到终点坐标和上一步偏差):

$$\text{向 } +X \text{ 进给:}\ F_{i+1} = F_i - Y_e \qquad \text{向 } +Y \text{ 进给:}\ F_{i+1} = F_i + X_e$$

终点判别三种:总步长法($|X_e|+|Y_e|$ 为总步数,每步减 1,减到 0 停——本实验采用)、终点坐标法、投影法。

18.3 四象限扩展

四个象限的进给规则(偏差公式不变,对绝对值坐标计算;符号与第一象限相反的轴电机反向即可):

原书图 18.4.1
原书图 18.4.1:四个象限直线插补图示
象限F > 0 进给F < 0 进给
第一象限+X+Y
第二象限−X+Y
第三象限−X−Y
第四象限+X−Y

18.4 实验实现:两轴平台画正方形

X 轴用接口三(TIM8_CH3=PI7、DIR3=PB2、EN3=PF11),Y 轴用接口四(TIM8_CH4=PC9、DIR4=PH2、EN4=PH3),两根丝杆滑台组成 X-Y 平台,1.0A、8 细分。PWM2 模式:比较值 = Speed、ARR = Speed×2,输出恰好 50% 占空比。

/* 直线增量插补:算总步数并完成第一步进给 */
void line_incmove(uint32_t IncX, uint32_t IncY, uint32_t Speed)
{
    g_pol_par.f_e = 0;                        /* 偏差置零 */
    g_pol_par.end_x = IncX;  g_pol_par.end_y = IncY;
    g_pol_par.end_pulse = g_pol_par.end_y + g_pol_par.end_x;  /* 总步长法 */
    if (g_pol_par.end_y > g_pol_par.end_x) {  /* F=0 按终点定方向 */
        g_pol_par.act_axis = AXIS_Y;          /* 先进给 Y 轴 */
        g_pol_par.f_e = g_pol_par.f_e + g_pol_par.end_x;  /* F += Xe */
    } else {
        g_pol_par.act_axis = AXIS_X;          /* 先进给 X 轴 */
        g_pol_par.f_e = g_pol_par.f_e - g_pol_par.end_y;  /* F -= Ye */
    }
    __HAL_TIM_SET_AUTORELOAD(&g_atimx_handle, Speed * 2);
}
/* 更新中断里完成后续每一步插补 */
if (g_pol_par.f_e > 0) {                      /* 在线上方 → 向 X 进给 */
    g_pol_par.act_axis = AXIS_X;
    g_pol_par.f_e = g_pol_par.f_e - g_pol_par.end_y;
} else if (g_pol_par.f_e < 0) {               /* 在线下方 → 向 Y 进给 */
    g_pol_par.act_axis = AXIS_Y;
    g_pol_par.f_e = g_pol_par.f_e + g_pol_par.end_x;
} else if (g_pol_par.f_e == 0) {              /* 在线上,比较终点再走 */
    if (g_pol_par.end_y > g_pol_par.end_x)
        { g_pol_par.act_axis = AXIS_Y; g_pol_par.f_e += g_pol_par.end_x; }
    else
        { g_pol_par.act_axis = AXIS_X; g_pol_par.f_e -= g_pol_par.end_y; }
}
if (axis != g_pol_par.act_axis) {             /* 换进给轴时切换通道 */
    TIM_CCxChannelCmd(TIM8, st_motor[axis].pulse_channel, TIM_CCx_DISABLE);
    TIM_CCxChannelCmd(TIM8, st_motor[g_pol_par.act_axis].pulse_channel,
                      TIM_CCx_ENABLE);
}
g_pol_par.end_pulse--;                        /* 终点判别:总步数减 1 */
if (g_pol_par.end_pulse == 0) g_motor_sta = STATE_STOP;

实验:KEY0 启动后依次走第一、四、三、二象限(line_inpolation(5*1600, ±5*1600, 2000)),坐标正负号决定各轴电机方向,最终轨迹是一个正方形

🧠 小测验
1. 逐点比较法的四个工作步骤是什么?
偏差判别(判断加工点在直线哪一侧)→ 坐标进给(向减小误差方向走一步)→ 偏差计算(算新点偏差)→ 终点判别(未到终点继续循环,到则停止)。
2. 第一象限直线插补中 F>0、F<0 时各向哪进给?偏差如何递推?
F>0 在直线上方,向 +X 进给,F_{i+1} = F_i − Y_e;F<0 在直线下方,向 +Y 进给,F_{i+1} = F_i + X_e;F=0 时按 X_e ≥ Y_e 决定走 +X 还是 +Y。
3. 脉冲增量插补与数字增量插补各适用什么系统?
脉冲增量插补以脉冲形式输出行程增量(行程标量),适用于步进电机开环系统;数字增量插补先粗插补再精插补(时间标量),适用于闭环/半闭环系统。
← 上一篇🏠 顶层目录下一篇 →