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

各位同学,欢迎来到《多轴联动插补算法深度解析》的第一章。

今天咱们聊一个非常经典、也非常基础的东西——逐点比较法。说实话,这方法听起来有点土,对吧?但你别小看它。我当年刚入行做数控系统时,第一块调通的插补代码就是逐点比较法。那时候没有现成的库,全靠自己一行行写。嗯,现在回想起来,那段经历让我对插补的本质理解得特别透彻。

逐点比较法,说白了就是「走一步,看一步」。每走一步,都算一下当前位置跟理想轨迹的偏差,然后决定下一步往哪走。你想想看,这不就是咱们平时走路找方向的感觉吗?

一、直线插补的基本思想

先说说直线插补。我们要让刀具从起点A走到终点B,走一条直线。但问题是,数控系统的进给轴只能走正交的步进——要么走X方向,要么走Y方向,不能同时走斜线。

那怎么办?

逐点比较法的思路是:用折线逼近直线。每一步都判断当前位置是在直线的哪一侧,然后朝着靠近直线的方向走一步。

我举个例子。假设起点是(0,0),终点是(4,3)。理想轨迹是一条斜线。实际走出来的路径,是一系列台阶状的折线。只要步长足够小,这条折线跟直线的误差就在允许范围内。

这里有个关键点:每一步只走一个脉冲当量。要么X走一步,要么Y走一步。这就是「逐点比较」这个名字的由来——每走一个点,都要比较一下。

核心思想总结:逐点比较法是一种基于偏差判别和误差补偿的插补方法。它不依赖复杂的三角函数计算,而是通过简单的加减法和符号判断来实现轨迹逼近。

二、偏差计算公式推导

好,接下来咱们推导偏差公式。这部分是重点,也是很多同学觉得头疼的地方。别急,我带你一步步来。

假设我们要插补的直线起点为原点O(0,0),终点为E(Xe, Ye)。当前刀具位置为P(Xi, Yi)。

怎么判断P点在直线的哪一侧?

矢量叉积。直线OE的矢量是(Xe, Ye),当前点P的矢量是(Xi, Yi)。这两个矢量的叉积,就是判断P点相对于直线OE的位置。

叉积公式:

F = Xe × Yi - Xi × Ye

这个F就是我们的偏差值

为什么是这个公式?我简单解释一下。叉积的几何意义是平行四边形面积。如果F > 0,说明P点在直线的上方(或左侧,取决于坐标系定义);如果F < 0,说明P点在直线的下方(或右侧);如果F = 0,说明P点正好在直线上。

嗯,这里要注意:F的正负决定了进给方向

那问题来了:每次都要重新算这个乘法,计算量是不是太大了?

别担心,我们有递推公式。这才是逐点比较法的精髓。

三、递推公式的推导

假设当前点P(Xi, Yi)的偏差为Fi = Xe×Yi - Xi×Ye。

情况一:Fi ≥ 0

说明P点在直线上方或线上。这时候我们走一步+X方向。新位置为(Xi+1, Yi)。

新偏差:

Fi+1 = Xe × Yi - (Xi+1) × Ye
     = Xe × Yi - Xi × Ye - Ye
     = Fi - Ye

情况二:Fi < 0

说明P点在直线下方。这时候我们走一步+Y方向。新位置为(Xi, Yi+1)。

新偏差:

Fi+1 = Xe × (Yi+1) - Xi × Ye
     = Xe × Yi + Xe - Xi × Ye
     = Fi + Xe

你看,递推公式只需要做加减法,没有乘法!这在早期的数控系统里,可是大大的优势。我记得当年用8位单片机做插补,乘法指令要几十个时钟周期,而加减法只要几个周期。这个优化,直接决定了系统能不能跑实时。

个人经验:我在做一款经济型数控系统时,CPU主频只有16MHz。如果用直接公式做插补,每步要算乘法,根本跑不到目标进给速度。改成递推公式后,插补周期从200μs降到了30μs。这个优化,让系统从「勉强能用」变成了「流畅运行」。

四、进给方向判定规则

有了偏差公式,进给方向的判定就很简单了。我整理成一张表,方便你查阅。

偏差符号 进给方向 偏差递推公式
Fi ≥ 0 +X方向 Fi+1 = Fi - Ye
Fi < 0 +Y方向 Fi+1 = Fi + Xe

这个规则适用于第一象限的直线插补。其他象限的规则类似,只是符号需要调整。后面章节我会详细讲。

这里有个容易踩的坑:终点判断。你不能一直走,得知道什么时候停下来。

终点判断的方法很简单:

  • 方法一:累计步数。总步数 = Xe + Ye(以脉冲当量计)。每走一步,计数器减1。减到0就停。
  • 方法二:坐标比较。当X坐标达到Xe且Y坐标达到Ye时,停止。

我个人习惯用方法一,因为实现简单,而且不容易出错。

避坑指南:我曾经在一个项目中,用坐标比较法做终点判断。结果因为累加误差,X坐标永远达不到Xe的精确值,导致插补停不下来。后来改成步数计数法,问题就解决了。所以,能用计数法就别用比较法,这是血的教训。

五、完整插补流程

把上面的内容串起来,逐点比较法直线插补的完整流程如下:

  1. 初始化:设置起点(0,0),终点(Xe,Ye),总步数N = Xe + Ye,偏差F = 0。
  2. 偏差判别:判断F的符号。
  3. 进给:根据F符号,决定走+X还是+Y。
  4. 偏差计算:用递推公式更新F值。
  5. 终点判断:步数计数器减1。如果为0,停止;否则回到步骤2。

你看,就这么简单。没有复杂的数学,没有高深的算法。但就是这套方法,支撑了早期数控系统的半壁江山。

六、代码示例

最后,我给出一个C语言的实现片段。你可以在自己的平台上跑一跑,感受一下。

// 逐点比较法直线插补(第一象限)
void line_interpolate(int Xe, int Ye) {
    int F = 0;          // 偏差
    int step = Xe + Ye; // 总步数
    int x = 0, y = 0;   // 当前位置
    
    while (step > 0) {
        if (F >= 0) {
            // +X方向进给
            x++;
            F -= Ye;
        } else {
            // +Y方向进给
            y++;
            F += Xe;
        }
        step--;
        
        // 输出当前点坐标(实际应用中发送脉冲)
        printf("(%d, %d)\n", x, y);
    }
}

这段代码虽然简单,但包含了逐点比较法的全部核心逻辑。你可以在自己的开发板上试试,看看走出来的轨迹是不是一条直线。

七、小结

这一章我们讲了逐点比较法的基本原理、偏差公式的推导、递推公式的优化,以及进给方向的判定规则。

说白了,逐点比较法就是「走一步看一步」的智慧。它不需要高深的数学,不需要昂贵的硬件,靠的是巧妙的递推思想和简单的加减法运算。

下一章,我会讲逐点比较法在其他象限的推广,以及如何处理圆弧插补。到时候你会发现,核心思想是一样的,只是偏差公式的形式变了。

好,今天就到这里。如果你在实现中遇到问题,欢迎交流。记住,动手写代码才是最好的学习方式