逐点比较法直线插补:从原理到FPGA实现

各位同学,今天我们来聊聊逐点比较法。这个方法,说白了就是让刀具一步一步「摸着石头过河」。我在做数控系统那会儿,第一次接触这个算法,觉得它特别朴素——但你别小看它,在FPGA里跑起来,效率高得吓人。

逐点比较法的核心思想

逐点比较法,名字已经说得很清楚了:每走一步,都比较一下当前位置和目标位置的偏差。然后根据偏差决定下一步往哪走。就像你闭着眼睛走路,每走一步就问自己:「我偏左了还是偏右了?」然后调整方向。

具体到直线插补,我们关心的是四个环节:

  • 偏差判别——当前点相对于理想直线,是偏上还是偏下?
  • 坐标进给——根据偏差,决定往X方向走还是往Y方向走
  • 偏差计算——走完一步后,重新计算新的偏差值
  • 终点判别——看看走完了没有,没走完就继续

这四步循环往复,直到到达终点。听起来简单吧?但实际做起来,里面有不少门道。

直线插补的数学推导

假设我们要从原点(0,0)走到终点(Xe, Ye),走一条直线。这条直线的方程是:

Y = (Ye / Xe) * X

但FPGA不喜欢除法,所以我们换个思路。定义偏差函数:

F = Xe * Y - Ye * X

为什么这么定义?你想想看,如果当前点正好在直线上,那么F=0。如果点在直线上方,F>0。点在直线下方,F<0。这个偏差函数,就是我们判断方向的依据。

关键点:偏差函数F的符号决定了进给方向。F≥0时走+X,F<0时走+Y。这是逐点比较法的核心规则。

偏差计算的递推公式

每次走完一步,都要重新算F值。但每次都重新算乘法太慢了,我习惯用递推公式。这样在FPGA里只需要做加减法,快得很。

情况一:当前F≥0,走+X一步

走完这一步,新坐标是(X+1, Y)。新偏差:

F_new = Xe * Y - Ye * (X + 1)
      = Xe * Y - Ye * X - Ye
      = F_old - Ye

情况二:当前F<0,走+Y一步

走完这一步,新坐标是(X, Y+1)。新偏差:

F_new = Xe * (Y + 1) - Ye * X
      = Xe * Y + Xe - Ye * X
      = F_old + Xe

看到了吗?每次只需要加或减一个常数。这个特性在FPGA里简直是天赐良机。

我的经验:在FPGA实现时,把Xe和Ye提前存好。每次迭代只需要一个加法器和一个比较器,资源消耗极低。我曾经在一个小规模的FPGA里同时跑了8轴插补,靠的就是这个递推公式。

终点判别的两种方式

终点判别,说白了就是看看走完了没有。我见过两种做法:

方法 原理 优缺点
总步数法 总步数 = Xe + Ye,每走一步减1 简单,但需要提前算好总步数
坐标比较法 比较当前坐标是否等于终点坐标 直观,但比较逻辑稍复杂

我个人更推荐总步数法。为什么?因为只需要一个减法器和一个零比较器,在FPGA里实现起来特别干净。我曾经踩过一个坑:用坐标比较法时,如果终点坐标不是整数步长,可能会永远到不了终点。用总步数法就没这个问题。

注意:总步数法要求Xe和Ye都是非负整数。如果直线在其它象限,需要先做象限变换。这个我们后面会详细讲。

完整的插补流程

把上面这些串起来,一个完整的直线插补流程就是:

  1. 初始化:设置终点(Xe, Ye),总步数N = Xe + Ye,偏差F = 0
  2. 判断F的符号:F≥0走+X,F<0走+Y
  3. 更新偏差:走+X时F = F - Ye,走+Y时F = F + Xe
  4. 总步数减1:N = N - 1
  5. 判断N是否为0:不为0则回到步骤2,为0则结束

这个流程,在FPGA里可以用一个状态机来实现。每个时钟周期走一步,非常规整。

知识体系结构图

下面这张图,把逐点比较法直线插补的整个知识体系串起来了。你可以看到,从偏差函数出发,衍生出四个核心环节,每个环节又有具体的实现方法。

逐点比较法直线插补知识体系 逐点比较法 偏差判别 坐标进给 偏差计算 终点判别 偏差函数 F = Xe·Y - Ye·X F=0在线上,F>0在上方 进给规则 F≥0 → 走+X F<0 → 走+Y 递推公式 走+X: F = F - Ye 走+Y: F = F + Xe 判别方法 总步数法: N=Xe+Ye 坐标比较法 循环迭代 四步循环 → FPGA状态机实现

一个简单的例子

假设我们要从(0,0)走到(5,3)。总步数N=8。我们手动走一遍:

初始:F=0, N=8

第1步:F=0 ≥ 0,走+X → F=0-3=-3, N=7
第2步:F=-3 < 0,走+Y → F=-3+5=2, N=6
第3步:F=2 ≥ 0,走+X → F=2-3=-1, N=5
第4步:F=-1 < 0,走+Y → F=-1+5=4, N=4
第5步:F=4 ≥ 0,走+X → F=4-3=1, N=3
第6步:F=1 ≥ 0,走+X → F=1-3=-2, N=2
第7步:F=-2 < 0,走+Y → F=-2+5=3, N=1
第8步:F=3 ≥ 0,走+X → F=3-3=0, N=0 → 结束

走出来的轨迹是:X方向走了5步,Y方向走了3步,正好到达(5,3)。而且每一步的决策都是基于当前偏差,没有用到任何除法或乘法。

避坑指南:我曾经在调试时发现,如果Xe或Ye为0,也就是走水平线或垂直线,递推公式依然有效。但要注意,如果Xe=0,那么走+Y时F=F+0,偏差不变,这时候需要特殊处理。我的做法是:如果Xe=0,直接走Y方向直到终点;如果Ye=0,直接走X方向。

好了,逐点比较法直线插补的原理就讲到这里。这个算法虽然简单,但在FPGA里实现时,你会发现它的硬件友好性极好——没有乘法、没有除法、只有加减法和比较器。下一节我们会深入FPGA的具体实现,包括状态机设计、流水线优化,以及多轴联动的同步问题。


专注资料整理