这一章在干嘛?

单轴只能走横平竖直,画斜线必须 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:第一象限直线插补示意图

设直线终点 、动点 偏差判别式

  • :恰在直线上;:在直线上方,向 走一步;:在直线下方,向 走一步;
  • 时看终点坐标:,否则走

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

终点判别三种:总步长法( 为总步数,每步减 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)),坐标正负号决定各轴电机方向,最终轨迹是一个正方形