2. 逐点比较法(一):直线插补原理,偏差计算公式推导,进给方向判定

各位工程师朋友,咱们今天来啃一块硬骨头——逐点比较法直线插补。说实话,这玩意儿在数控系统里已经存在几十年了,但直到今天,很多国产运动控制卡的核心算法还是它。我当年刚入行时,师傅丢给我一本泛黄的数控原理手册,第一页就是逐点比较法。当时觉得这方法太“笨”了,一步一比较,效率能高吗?后来在调试一台三米龙门铣时,我才真正体会到它的价值——简单、可靠、没有累积误差。嗯,咱们今天就把它彻底讲透。

2.1 逐点比较法的核心思想

逐点比较法,说白了就是“走一步看一步”。刀具每走一步,系统就计算一下当前位置与理想直线的偏差,然后根据偏差决定下一步往哪个方向走。你想想看,这就像蒙着眼睛走直线——每迈一步,就摸一下自己偏了没,偏左就往右调,偏右就往左调。

它的工作流程可以概括为四个步骤,我习惯叫它“四步循环”:

  1. 偏差判别:计算当前点与理想直线的偏差
  2. 进给控制:根据偏差符号决定进给方向
  3. 偏差计算:进给后,计算新位置的偏差值
  4. 终点判别:判断是否到达终点,未到则继续循环

这四步不断重复,直到刀具走到终点。听起来简单吧?但这里面有个关键问题——偏差怎么算?

逐点比较法四步循环流程图 逐点比较法四步循环 ① 偏差判别 计算当前偏差 F ② 进给控制 F≥0 或 F<0 决定方向 ③ 偏差计算 递推公式更新 F ④ 终点判别 是否到达终点? 未到终点 继续循环

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 终点判别

光会走还不行,得知道什么时候停。终点判别有两种常用方法:

  1. 总步数法:预先计算总步数 N = Xe + Ye,每走一步减 1,减到 0 就停。
  2. 坐标比较法:每次进给后判断 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 剩余步数
00—(0,0)08
10+X(1,0)0-3=-37
2-3+Y(1,1)-3+5=26
32+X(2,1)2-3=-15
4-1+Y(2,2)-1+5=44
54+X(3,2)4-3=13
61+X(4,2)1-3=-22
7-2+Y(4,3)-2+5=31
83+X(5,3)3-3=00

走完 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 更新偏差
这三板斧抡熟了,直线插补就没什么秘密了。