3. 逐点比较法(二):直线插补的终点判别方法,插补计算流程与实例
上一章我们把逐点比较法的核心——偏差判别和进给方向讲清楚了。但有个问题一直悬着:什么时候停下来?
你想想看,电机每走一步,我们就算一次偏差、判一次方向、发一次脉冲。如果不知道终点在哪,电机就会一直跑下去,要么撞限位,要么画出一条无限长的线。所以,终点判别是插补算法里不可或缺的一环。
我个人习惯把终点判别比作「导航里的目的地提醒」。没有它,你开再好的车也到不了站。
3.1 终点判别的三种常见方法
在实际的数控系统和运动控制器里,终点判别主要有三种实现方式。我挨个给你讲清楚。
| 方法名称 | 原理简述 | 适用场景 |
|---|---|---|
| 总步数法 | 预先计算 X 和 Y 方向的总步数,每走一步减 1,减到 0 即停止 | 最常用,适合绝大多数直线插补 |
| 坐标比较法 | 实时比较当前坐标与终点坐标,两者相等时停止 | 需要绝对位置反馈的场合 |
| 象限投影法 | 将终点坐标投影到各轴,分别判断各轴是否到达 | 多轴联动或非正交坐标系 |
重点提醒:绝大多数商用数控系统和运动控制卡,默认采用总步数法。原因很简单——计算量小、逻辑清晰、不容易出错。
3.2 总步数法详解
总步数法的思路非常直接:
- 设起点为 (0, 0),终点为 (Xe, Ye)。
- 总步数 N = |Xe| + |Ye|。
- 每走一步,N = N - 1。
- 当 N = 0 时,插补结束。
这里有个细节我当年踩过坑——绝对值。不管终点在哪个象限,步数永远是正的。你想想,如果终点在第二象限,Xe 是负数,直接相加会出问题。
我曾经在调试一台三轴雕刻机时,忘了对终点坐标取绝对值。结果电机在负方向一直走,走到机械限位才停下来。那次差点把丝杠顶弯。从那以后,我写终点判别代码时,第一行一定是 abs()。
3.3 插补计算完整流程
把偏差判别、进给方向和终点判别串起来,就是逐点比较法直线插补的完整流程。我习惯用下面这张图来给团队新人做培训:
这个流程看起来有点复杂,但核心就三个动作:判方向 → 走一步 → 减步数。循环往复,直到步数为零。
3.4 完整实例:第一象限直线插补
光讲理论不够,我们跑一个完整的例子。假设终点为 (4, 3),起点为 (0, 0)。
先算总步数:N = |4| + |3| = 7。
下面是每一步的详细计算过程:
| 步数 | 当前点 | 偏差 F | F ≥ 0 ? | 进给方向 | 新偏差计算 | 新坐标 | 剩余步数 |
|---|---|---|---|---|---|---|---|
| 0 | (0, 0) | 0 | 是 | +X | F = 0 - 3 = -3 | (1, 0) | 6 |
| 1 | (1, 0) | -3 | 否 | +Y | F = -3 + 4 = 1 | (1, 1) | 5 |
| 2 | (1, 1) | 1 | 是 | +X | F = 1 - 3 = -2 | (2, 1) | 4 |
| 3 | (2, 1) | -2 | 否 | +Y | F = -2 + 4 = 2 | (2, 2) | 3 |
| 4 | (2, 2) | 2 | 是 | +X | F = 2 - 3 = -1 | (3, 2) | 2 |
| 5 | (3, 2) | -1 | 否 | +Y | F = -1 + 4 = 3 | (3, 3) | 1 |
| 6 | (3, 3) | 3 | 是 | +X | F = 3 - 3 = 0 | (4, 3) | 0 |
你看,走了 7 步,正好到达终点 (4, 3)。每一步的偏差计算和进给方向都符合我们上一章讲的规则。
一个小技巧:我习惯在调试时把每一步的坐标打印出来,然后用 Excel 画个散点图。一眼就能看出插补轨迹是不是对的。如果轨迹明显偏离理论直线,多半是偏差计算公式写反了。
3.5 其他象限的处理
刚才的例子只针对第一象限。其他象限怎么办?
其实原理一样,只是进给方向要跟着象限变。我直接给你一个对照表:
| 象限 | F ≥ 0 进给方向 | F < 0 进给方向 |
|---|---|---|
| 第一象限 | +X | +Y |
| 第二象限 | -X | +Y |
| 第三象限 | -X | -Y |
| 第四象限 | +X | -Y |
嗯,这里要注意:偏差计算公式不变,变的只是进给方向。我见过不少新手把偏差公式也改了,结果轨迹全乱套。
3.6 代码实现示例
最后,给你一段 C 风格的伪代码。这是我当年在 STM32 上跑过的版本,稍微简化了一下:
// 逐点比较法直线插补(第一象限)
void line_interpolate(int Xe, int Ye) {
int F = 0; // 偏差
int N = abs(Xe) + abs(Ye); // 总步数
int X = 0, Y = 0; // 当前坐标
while (N > 0) {
if (F >= 0) {
// +X 方向进给
X++;
F = F - Ye;
} else {
// +Y 方向进给
Y++;
F = F + Xe;
}
N--; // 步数减一
// 输出脉冲或更新位置
output_step(X, Y);
}
}
这段代码虽然简单,但核心逻辑都在里面了。实际工程中,你还需要考虑象限判断、加减速处理、脉冲输出频率控制等。不过那是后面章节的内容了。
核心要点回顾:
- 终点判别最常用的是总步数法,N = |Xe| + |Ye|
- 插补流程:初始化 → 终点判别 → 偏差判别 → 进给 → 更新 → 循环
- 不同象限只改变进给方向,不改变偏差计算公式
- 调试时建议打印每一步坐标,用图表验证轨迹