2. 逐点比较法(一):直线插补原理,偏差计算公式推导,进给方向判定
各位工程师朋友,咱们今天来啃一块硬骨头——逐点比较法直线插补。说实话,这玩意儿在数控系统里已经存在几十年了,但直到今天,很多国产运动控制卡的核心算法还是它。我当年刚入行时,师傅丢给我一本泛黄的数控原理手册,第一页就是逐点比较法。当时觉得这方法太“笨”了,一步一比较,效率能高吗?后来在调试一台三米龙门铣时,我才真正体会到它的价值——简单、可靠、没有累积误差。嗯,咱们今天就把它彻底讲透。
2.1 逐点比较法的核心思想
逐点比较法,说白了就是“走一步看一步”。刀具每走一步,系统就计算一下当前位置与理想直线的偏差,然后根据偏差决定下一步往哪个方向走。你想想看,这就像蒙着眼睛走直线——每迈一步,就摸一下自己偏了没,偏左就往右调,偏右就往左调。
它的工作流程可以概括为四个步骤,我习惯叫它“四步循环”:
- 偏差判别:计算当前点与理想直线的偏差
- 进给控制:根据偏差符号决定进给方向
- 偏差计算:进给后,计算新位置的偏差值
- 终点判别:判断是否到达终点,未到则继续循环
这四步不断重复,直到刀具走到终点。听起来简单吧?但这里面有个关键问题——偏差怎么算?
2.2 偏差计算公式推导
好,咱们来推导偏差公式。假设我们要插补一条从原点 O(0,0) 到终点 E(Xe,Ye) 的直线。注意,这里 Xe 和 Ye 都是正数,咱们先讨论第一象限的情况。
直线上任意一点 P(x,y) 满足什么关系?斜率相等:
y / x = Ye / Xe
交叉相乘得到:
y · Xe = x · Ye
移项:
y · Xe - x · Ye = 0
这个等式就是直线方程。如果点 P 在直线上,等式成立。如果不在呢?
我们定义偏差函数 F:
F = y · Xe - x · Ye
现在来分析 F 的符号含义:
- F = 0:点在直线上
- F > 0:点在直线上方(相对于进给方向)
- F < 0:点在直线下方
核心要点:偏差 F 的符号直接决定了下一步的进给方向。这就是逐点比较法的“决策依据”。
我在项目中遇到过一个问题:有同事直接用浮点数计算 F,结果在高速插补时 CPU 开销太大,导致丢步。后来我改成整数递推,问题就解决了。所以接下来咱们重点讲递推公式——这才是工程实践中的关键。
2.3 递推公式——避免重复计算
如果每走一步都重新计算 F = y·Xe - x·Ye,那得做两次乘法和一次减法。对于几十 kHz 的插补频率,这个计算量不可忽视。更聪明的做法是利用上一步的偏差值,通过简单的加减法递推出新偏差。
咱们分两种情况讨论:
情况一:当前 F ≥ 0(点在直线上或上方)
进给方向:沿 X 轴正向走一步(+X)
新坐标:x' = x + 1, y' = y
新偏差:
F' = y' · Xe - x' · Ye
= y · Xe - (x + 1) · Ye
= (y · Xe - x · Ye) - Ye
= F - Ye
看到了吗?新偏差 F' 只需要用旧偏差 F 减去 Ye 就能得到。一次减法搞定!
情况二:当前 F < 0(点在直线下方)
进给方向:沿 Y 轴正向走一步(+Y)
新坐标:x' = x, y' = y + 1
新偏差:
F' = y' · Xe - x' · Ye
= (y + 1) · Xe - x · Ye
= (y · Xe - x · Ye) + Xe
= F + Xe
同样,一次加法搞定。
工程技巧:我建议在代码里把 Xe 和 Ye 存成整数,递推时只用加减法。这样不仅速度快,还能避免浮点精度问题。我曾经在一个激光切割项目里,用这个技巧把插补周期从 200μs 降到了 50μs。
2.4 进给方向判定规则
把上面的推导整理成判定表,一目了然:
| 当前偏差 F | 进给方向 | 新偏差 F' |
|---|---|---|
| F ≥ 0 | +X(沿 X 轴正向) | F' = F - Ye |
| F < 0 | +Y(沿 Y 轴正向) | F' = F + Xe |
这里有个细节要注意:当 F = 0 时,我们把它归到 F ≥ 0 的情况,走 +X 方向。为什么?因为这样处理可以保证插补轨迹始终偏向直线的一侧,不会出现来回振荡。嗯,这是工程上的约定俗成。
2.5 终点判别
光会走还不行,得知道什么时候停。终点判别有两种常用方法:
- 总步数法:预先计算总步数 N = Xe + Ye,每走一步减 1,减到 0 就停。
- 坐标比较法:每次进给后判断 x == Xe 且 y == Ye。
我个人习惯用总步数法。原因很简单——只需要一个计数器,不需要每次比较两个坐标值。在硬件实现中,这能省好几个逻辑门。
注意:总步数法要求 Xe 和 Ye 是整数步数。如果你的系统使用脉冲当量(比如 1 脉冲 = 0.001mm),记得先把终点坐标换算成脉冲数。我曾经见过有人直接用毫米数做总步数,结果插补跑过了头——因为小数被截断了。
2.6 完整插补流程示例
咱们拿一个具体例子走一遍。假设终点 E(5, 3),即 Xe=5, Ye=3。
初始状态:x=0, y=0, F=0, 总步数 N = 5+3 = 8
| 步数 | 当前 F | 进给方向 | 新坐标 (x,y) | 新 F | 剩余步数 |
|---|---|---|---|---|---|
| 0 | 0 | — | (0,0) | 0 | 8 |
| 1 | 0 | +X | (1,0) | 0-3=-3 | 7 |
| 2 | -3 | +Y | (1,1) | -3+5=2 | 6 |
| 3 | 2 | +X | (2,1) | 2-3=-1 | 5 |
| 4 | -1 | +Y | (2,2) | -1+5=4 | 4 |
| 5 | 4 | +X | (3,2) | 4-3=1 | 3 |
| 6 | 1 | +X | (4,2) | 1-3=-2 | 2 |
| 7 | -2 | +Y | (4,3) | -2+5=3 | 1 |
| 8 | 3 | +X | (5,3) | 3-3=0 | 0 |
走完 8 步,正好到达终点 (5,3)。你仔细看这个轨迹,它其实是在理想直线上下摆动,但整体趋势是沿着直线前进的。这就是逐点比较法的精髓——用“锯齿”逼近直线。
2.7 第一象限到其他象限的推广
刚才咱们只讨论了第一象限。实际加工中,直线可能出现在任何象限。怎么办?
方法很简单:坐标变换。把其他象限的直线映射到第一象限来处理,进给时再根据实际象限做符号变换。
举个例子,如果终点在第二象限 (-Xe, Ye),我们可以:
- 取绝对值 Xe' = |Xe|, Ye' = |Ye|
- 用第一象限的算法计算进给方向
- 实际进给时,X 轴方向取反(走 -X 而不是 +X)
这样,一套算法就能覆盖所有象限。我在做四轴联动系统时,就是用这个思路把直线插补扩展到任意方向。
总结一下:逐点比较法直线插补的核心就三件事——
① 用 F = y·Xe - x·Ye 判断偏差
② 根据 F 符号决定走 +X 还是 +Y
③ 用递推公式 F' = F - Ye 或 F' = F + Xe 更新偏差
这三板斧抡熟了,直线插补就没什么秘密了。