逐点比较法直线插补:从原理到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都是非负整数。如果直线在其它象限,需要先做象限变换。这个我们后面会详细讲。
完整的插补流程
把上面这些串起来,一个完整的直线插补流程就是:
- 初始化:设置终点(Xe, Ye),总步数N = Xe + Ye,偏差F = 0
- 判断F的符号:F≥0走+X,F<0走+Y
- 更新偏差:走+X时F = F - Ye,走+Y时F = F + Xe
- 总步数减1:N = N - 1
- 判断N是否为0:不为0则回到步骤2,为0则结束
这个流程,在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的具体实现,包括状态机设计、流水线优化,以及多轴联动的同步问题。