3、数字积分法(DDA):DDA直线插补、DDA圆弧插补、DDA的终点判断与进给速度控制
数字积分法,圈内人习惯叫它 DDA(Digital Differential Analyzer)。
说实话,这是我个人非常偏爱的一种插补算法。为什么?因为它思路极其简洁——用积分的思想,把连续的轨迹离散成微小的步进。你想想看,我们做运动控制,本质上不就是把一条连续的曲线,拆成无数个微小的直线段去逼近吗?DDA 正好完美契合了这个逻辑。
3.1 DDA 直线插补
先聊直线插补。DDA 做直线,核心就一句话:对速度分量进行累加积分。
假设我们要从起点 (0,0) 走到终点 (Xe, Ye)。X 方向的速度设为 Vx,Y 方向的速度设为 Vy。那么经过时间 t,位置就是:
X = Vx * t
Y = Vy * t
但在数控系统里,时间 t 是离散的。我们用一个累加器来模拟积分过程。每次累加一个增量,当累加器溢出时,就发一个脉冲,驱动电机走一步。
具体实现时,我习惯这样处理:
- 设累加器位数为 N(比如 8 位、16 位)
- 累加器最大值 M = 2^N
- X 方向每次累加 K*Xe,Y 方向每次累加 K*Ye
- K 通常取 1/M,这样累加 N 次后刚好走完全程
看个简单的例子。假设 N=4,M=16,终点 (5, 3):
X 累加器初值 = 0,每次加 5
Y 累加器初值 = 0,每次加 3
第1次:X累加器=5,未溢出;Y累加器=3,未溢出
第2次:X累加器=10,未溢出;Y累加器=6,未溢出
第3次:X累加器=15,未溢出;Y累加器=9,未溢出
第4次:X累加器=20,溢出(20-16=4),X走一步;Y累加器=12,未溢出
第5次:X累加器=9,未溢出;Y累加器=15,未溢出
...
核心要点:溢出即走步。谁溢出,谁就动一下。这就是 DDA 最朴素的逻辑。
我的经验:我在调试一台三轴雕刻机时,发现直线插补出来的轨迹总有点歪。查了半天,原来是累加器位数选得太小(8位),导致量化误差太大。后来换成16位,精度立马就上去了。所以,累加器位数直接决定了插补精度,别省这点资源。
3.2 DDA 圆弧插补
圆弧插补比直线复杂一点。为什么?因为速度方向一直在变。
DDA 处理圆弧的思路很巧妙——它把圆弧运动分解成两个互相垂直的速度分量。你想想看,一个点做圆周运动时,X 方向的速度正比于 Y 坐标,Y 方向的速度正比于 X 坐标(带符号)。
具体来说:
- 第一象限逆圆:Vx = -Y,Vy = X
- 第一象限顺圆:Vx = Y,Vy = -X
所以 DDA 圆弧插补的累加公式是:
X 累加器每次加 Y 的当前值(或负值)
Y 累加器每次加 X 的当前值(或负值)
注意,这里的 X 和 Y 是动点的实时坐标,不是终点坐标。每次走步后,坐标要更新。
我举个例子,第一象限逆圆,半径 R=5,从 (5,0) 走到 (0,5):
初始:X=5, Y=0
X累加器=0,每次加 -Y(即0)
Y累加器=0,每次加 X(即5)
第1次:X累加器=0,无溢出;Y累加器=5,未溢出
第2次:X累加器=0,无溢出;Y累加器=10,溢出,Y走一步,Y=1
第3次:X累加器=0,无溢出;Y累加器=15,溢出,Y走一步,Y=2
...
注意:圆弧插补时,累加器的值会随着坐标变化而变化。这跟直线插补完全不同。直线插补的累加值是固定的(终点坐标),而圆弧插补的累加值是动态的(实时坐标)。
我曾经在做一个圆插补测试时,发现走出来的圆总是扁的。排查了很久,发现是坐标更新时机出了问题——我是在累加之前更新坐标的,导致累加值用错了。正确的做法是:先累加,判断溢出,再更新坐标。顺序搞反了,圆就变椭圆了。
3.3 DDA 的终点判断
终点判断是个老生常谈的问题。DDA 怎么做终点判断?
常用的方法有两种:
- 总步数法:事先算好总共要走多少步,走完就停。直线插补时,总步数 = max(|Xe|, |Ye|) 或者 |Xe| + |Ye|。圆弧插补时,总步数根据弧长和步长计算。
- 坐标比较法:每次走步后,比较当前坐标是否到达终点。到了就停。
我个人更推荐总步数法。为什么?因为坐标比较法在圆弧插补时容易出问题——由于量化误差,当前坐标可能永远无法精确等于终点坐标,导致停不下来或者提前停。
避坑指南:我曾经用坐标比较法做圆弧插补,终点是 (0,5),结果走到 (0.02, 4.98) 就停了,因为判断条件写的是 "坐标相等"。后来改成 "坐标差值小于半个脉冲当量",问题就解决了。
3.4 进给速度控制
进给速度控制,说白了就是控制插补的快慢。
DDA 的进给速度由累加时钟频率决定。时钟频率越高,累加越快,溢出越快,走步越快,进给速度就越大。
但这里有个坑:直线插补和圆弧插补的进给速度含义不同。
直线插补时,累加一次对应一个时间片,走一步对应的位移是固定的(一个脉冲当量),所以速度 = 步长 × 时钟频率。
圆弧插补时,情况复杂一些。因为圆弧上每走一步,对应的弧长并不完全相等(尤其在曲率变化大的地方)。所以同样的时钟频率下,圆弧插补的实际进给速度可能会有波动。
我一般这样处理:
- 设定一个基准时钟频率 F0
- 根据目标进给速度 F,计算分频系数 K = F0 / F
- 用分频后的时钟驱动累加器
看个表格,更清楚:
| 目标速度 (mm/min) | 基准频率 (Hz) | 分频系数 | 实际驱动频率 (Hz) |
|---|---|---|---|
| 100 | 10000 | 100 | 100 |
| 500 | 10000 | 20 | 500 |
| 1000 | 10000 | 10 | 1000 |
小技巧:实际项目中,我通常不会直接用分频器,而是用定时器中断来产生累加时钟。这样频率可以精确控制,而且方便动态调整。比如在加减速阶段,只需要修改定时器的重装值就行。
嗯,DDA 的内容差不多就这些。它的优点是算法简单、易于硬件实现,缺点是精度受限于累加器位数,而且圆弧插补时速度均匀性不如逐点比较法。但瑕不掩瑜,DDA 至今仍是很多数控系统的首选插补方案。