自制工业控制系统:插补实战——逐点比较法、偏差递推与脉冲节拍
Contents
起因
三线合拢了:几何侧的逐点比较法在详解篇讲过来历,执行侧的脉冲和电机在电机篇备好了合同,速度侧的变频入口在放电篇通了——这篇写插补本体,把段表变成脉冲。插补这个词本身是什么、为什么非有它不可,前置的插补基础一篇已从零垫平(问题、三笔账、记分牌直觉),这里不再重复铺概念,直接进算法。
插补是个带着年代味的问题:数字计算机还没便宜下来的时候,怎么让一台机床走出不是直角折线的轨迹?五十年代的硬接线数控柜给出的答案是把轨迹问题化成"每步走一个脉冲当量、每步判一次方向"——逐点比较法。七十年代国产线切割的数控柜用分立元件实现了它,3B 纸带上的五个字段(X、Y、J、G、Z)就是这套硬件逻辑的寄存器投影:J 是计数器、G 是判终轴、Z 是象限查表的索引。同一时期,IBM 的 Bresenham 为绘图仪独立推导出同一套数学——两个世界互不知晓,得到同一条偏差递推。HF 时代用 x86 汇编把同一算法第三次写进软件;我们用 Rust 加 ISR 加 FPGA 第四次重写,每次重写,时代给的条件都在变:硬件时代的门电路按个数算,今天的乘法器在 GHz 面前近乎免费——这次的改法就藏在这个变化里,第二节见。

插画:插补实战的全景图解,五个区块正好是这篇的五段路。①是起因的三线汇合——几何侧逐点比较法、执行侧脉冲合同、速度侧变频入口三股线拧成插补本体,左边那截阶梯轨迹贴着理想斜线的样子,就是"每步走一个脉冲当量、每步判一次方向"的直观像。②是第二节的直线账——偏差函数 F = Xe·Y−Ye·X、两个前向候选挑 |F| 小的那条带符号规则(四张象限表塌缩成一行就是它)、dF 递推只剩加减、总步数 |ΔX|+|ΔY| 对账。③是第三节的圆弧账——F = x²+y²−R²、切向定前向候选、sgn 过象限自然翻符号、F 每拍重算换断电续切的幂等恢复。④是第四节的节拍分离——0xD0 一批算 256 个 tick 的步进位图进模式环,FPGA 拿变频频率当播放钟逐 tick 驱 PUL/DIR,83kHz 的重活全在硬件侧,变速只改频率不动几何。⑤是第五到七节的收尾账——段流转与短路回退(换目标不问方向)、四轴 DDA 均匀分配、给硬件篇的七项寄存器表合同。
一、两类插补与我们的选择
先把插补的两大门派认全。脉冲增量式:每输出一个脉冲,工作台走一个脉冲当量,插补器逐个脉冲地决定"哪个轴、朝哪边"——逐点比较法、数字积分法(DDA)、最小偏差法全属此门。数据采样式:插补器每毫秒级算一次"下一时刻各轴应该到哪"的位置设定值,由闭环伺服去跟——现代伺服 CNC 的主流。
我们没得选也不需要选:开环步进加脉冲方向接口(电机篇),只能吃脉冲增量式——接口决定算法。这不是将就:脉冲增量式的每一步都由几何递推决定、位置天然量化到脉冲当量,和开环步进"一个脉冲一个位置"的世界观严丝合缝;伺服闭环反而是采样式的地盘。
二、直线:偏差函数与增量递推
教科书讲直线插补,先在四个象限列四张进给方向表(L1–L4),因为逐点比较法的正统形态靠 F 的符号查表定方向——硬件时代省一次比较就是省几个门。软件时代不需要省这一下,四张表可以塌缩成一条带符号的规则。
偏差函数取 F = Xe·Y − Ye·X(Xe、Ye 是全段增量,X、Y 是当前点,都相对段起点、单位 µm):F = 0 在线上,F > 0 在线一方,F < 0 在另一方。每步朝终点方向走一个轴,两个前向候选里挑让 |F| 变小的那个——就这一条,象限没了:
|
|
几个性质一眼可验:dF 递推只有加减(dfx、dfy 在段内是常数);终点判别是双轴剩余量归零,总步数恰为 |ΔX|+|ΔY|——这个数可以和解析器那边对账,多一步少一步都说明有 bug;轨迹对理想直线的偏差不超过一个脉冲当量,1µm 当量下几何误差小于机械误差一个数量级,驱动不是精度的短板(电机篇的结论在这里兑现)。教科书把一次循环分成四拍——偏差判别、进给、偏差计算、终点判别——tick() 里三行就是这四拍,判别和计算在"比较两个候选"里合了。
三、圆弧:F = x²+y²−R²,两个前向候选挑小的
圆弧的偏差函数换成到圆心的距离差:F = x²+y²−R²(x、y 是当前点相对圆心)。前向候选由切向的轴向分量给出——逆圆(CCW)时切向是 (−y, x),所以 X 的前向步是 −sgn(y)、Y 的前向步是 +sgn(x);顺圆反号。两个候选里还是挑 |F| 小的:
|
|
三条要说的。过象限不用特判:教科书逆圆顺圆乘四象限列十六张表,是因为方向靠查表;这里 sgn(x)、sgn(y) 过轴时自然翻符号,表就没了。收敛性有保票:两个前向候选的角进度分别是 s·|y| 和 s·|x|(叉积一步就能算),都非负——扫角单调,算法只会绕着走不会兜圈,双轴剩余量(初始化为 |ex−x|、|ey−y|)必然归零。F 每拍直接重算:两次乘法在现代 CPU 上近乎免费,换来的是 tick() 不依赖历史状态——断电续切时快照只需要段号加绝对位置,F 从几何重算(参数篇 500ms 快照的"幂等恢复",在这里兑现成代码)。
3B 的 J 判终是单轴计数(G 方向那只轴),我们两个轴都数,更严;J 的校验职责留在解析器导入时(详解篇的口径),运行时各干各的。容量账:行程 ±2m 折 ±2×10⁶ µm,x² 上限 4×10¹²,加上 R² 的加减,离 i64 的 9.2×10¹⁸ 还有九个数量级余量——放心用。
四、节拍与批量:几何与节奏分离
tick() 只回答"下一步走哪",没回答"什么时候走"。节拍是速度的事:步频 = 进给速度 ÷ 脉冲当量,1µm 当量下 5m/min 空走就是 83kHz(电机篇算过)。83kHz 的中断每秒打断 CPU 八万次,每次进出栈加分发就是一两微秒,CPU 花掉一成还带抖动——软件节拍伺候不了这个频率,这是脉冲必须 FPGA 发的根本原因。
但不能让 FPGA 也算几何——几何是递推状态机,硬件实现是七十年代的老路(要走好多门)。解法是把模式和节拍拆开:
- 模式(几何):0xD0 的 ISR 一次算一批——比如 256 个 tick 的步进位图(一个 u8 一个 tick,四轴正负各一位),写进卡上的模式环
- 节拍(变频):FPGA 拿当前频率当播放时钟,逐 tick 从环里弹出字节、驱 PUL/DIR;水位低于一半,卡发"补货"中断,0xD0 再算一批
批量的账:256 步每步十几个周期(递推全是加减和比较),一批几微秒;83kHz 下 256 tick 撑 3.1ms,补货周期毫秒级——CPU 占用千分之一量级。更值钱的是解耦本身:0xE0 的变频修正只改播放频率,不动模式——放电反馈调快调慢,几何纹丝不动;操作工拨倍率同理。切到一半想快想慢是这台机器的常态,轨迹不能因为变速重算,这个分离是插补器抗压的根。
五、段的流转:从段表到脉冲,和回退
段的供给链:Core1 协作层把段表按序喂进 SPSC 环,0xD0 消费。段边界的处置在这一拍完成:下一段是 Comp/Taper 记录就转给补偿层挂账(解析器定的"只记录不展开"在这里兑现),Stop/OptStop 就通报 planner 暂停,规准组号变化的段边界通知 0xE0 转写放电模块寄存器(放电篇的段边界自动换组)。
短路回退是插补器必须直着腰接下的需求(放电篇:短路持续几十 ms 沿轨迹反向退)。位置基的生成让回退退化了:把当前段的目标从段终点换成段起点,重新初始化 rem_x/rem_y——生成器不问方向,只问"从现在这点到目标怎么走"。回退用固定慢速(播放频率压到切割速度的零头),解除后目标再换回终点。往返一回事,位置归零可验。
还有个白捡的遗产:插补生成器是纯函数(进状态出脉冲位),跟解析器一样能在开发机上 cargo test——全系统第二个 host 可测模块。测试断言三件套:终点精确命中、总步数对账(直线 |ΔX|+|ΔY|、圆弧双轴剩余量)、步进序列重构出的轨迹包络在 1 个脉冲当量内贴住理论线。golden 文件攒起来,改递推先跑测试再上机。
六、四轴与锥度:主从联动
XYUV 四轴直线不能拿偏差法硬扩(它生在二维)。用 DDA 的思路:每轴一个累加器,同一节拍钟下把各轴的步数均匀摊到总 tick 里——acc_u += ΔU; 若 acc_u 超过总步数就出一步并回减。两轴情形这个分配和偏差法等价(同一条阶梯),四轴直接扩展,锥度直线的 UV 随动就是 XY 的从动分配器。圆弧带锥度时上轨迹也是圆弧(同圆心异半径),ArcGen 各跑一份、共用节拍。上下异形那类真三维的活,留给锥形切割篇——插补器这层只需保证:任意 tick,四根轴谁出步都由同一个几何决定。
七、卡的寄存器表:给硬件篇的合同
运动控制卡是自研的,寄存器表就是我们自己定的规格——软件先立合同,硬件篇照着实现,跟 PCIe 篇"设备框架不写死卡"是同一套哲学的两端。先把这份合同的边界注明:它只管脉冲卡这一种形态(自研 GD32F4+FPGA,PUL/DIR 脉冲输出一族)。更高端的 PCIe EtherCAT 主站卡(一卡几十上百轴)、机柜外的独立控制器,吐的是总线报文不是脉冲,接不进这张表,但接得进卡适配层——对上暴露同一组运动命令,对下按卡的形态翻译。系统不会只支持一种卡,这张表是第一份合同,不是唯一一份;EtherCAT 那份的报文侧,硬件篇展开。
| 偏移 | 名称 | 方向 | 含义 |
|---|---|---|---|
| 0x00 | ID/VER | R | 卡标识与版本(对齐设备框架的枚举注册) |
| 0x08 | CTRL | W | 启动/停止/急停/回退模式 |
| 0x10 | PACE | W | 播放频率 Hz(变频修正经 0xD0 落到这里,0xE0 不直接摸卡) |
| 0x18 | PAT_WPTR | W | 模式环写指针(批量步进位图的落点) |
| 0x20 | PAT_CNT | R | 环内剩余 tick 数(补货水位) |
| 0x28 | STAT | R | 段完成/断丝输入/限位输入/故障位 |
| 0x30+ | POS_X/Y/U/V | R | 卡内脉冲计数器(命令侧位置,回读对账用) |
POS 计数器值得一句:开环系统的命令侧也能对账——卡数自己发出去的脉冲,主机比对命令意图与发出数,命令通路上的丢失当场现形(机床侧的丢步是另一回事,靠电机篇的回零流程兜)。断丝、限位输入落在卡上,直接进 0xF0 安全链——硬件信号走硬件的路,不绕软件。
总结
实战清单:门派选型(脉冲增量式配开环步进,接口决定算法)+ 三个时代四次重写的来历;直线偏差 F = Xe·Y−Ye·X、双前向候选挑 |F| 小、四张象限表塌缩成带符号一行、终点双轴剩余量+总步数对账;圆弧 F = x²+y²−R²、切向定前向候选、十六张表消融、扫角单调保收敛、F 每拍重算换幂等恢复(断电续切只需段号+位置)、i64 容量账;模式与节拍分离(0xD0 批量 256 tick 进模式环、FPGA 按变频频率播放、CPU 千分之一、变速不动几何);段流转(SPSC 供段、边界处置 Comp/Taper/规准换组)+ 位置基生成让回退=换目标 + host 可测第二模块(终点/步数/包络三断言);四轴 DDA 均匀分配与锥度随动框架;自研卡寄存器表七项当硬件篇的合同。跑通标志:矩形件每段脉冲账 |ΔX|+|ΔY| 核对全过、圆弧双轴剩余量归零且终点命中;切到一半拨倍率 80%↔120%,轨迹无缝不变形;断电重启续切,回位精度在脉冲当量级;强制短路触发回退,解除后往返位置归零;卡上 POS 计数器与命令意图全程一致;UV 联动比例在仿真屏可验。
下一篇顺藤摸瓜:四轴联动长出来的第一颗瓜是锥形切割——G51/G52 的角度怎么变成上下导轮的轨迹差,锥度件的工艺口径和 U/V 轴的边界条件,都在那篇展开。
参考链接
- Wikipedia: Bresenham’s line algorithm——同一数学在绘图仪世界的独立推导,1962
- Wikipedia: Digital differential analyzer——DDA 门派的家谱,四轴均匀分配的思路来源
- 本系列:G代码与3B代码详解(逐点比较法与 J/G/Z 的硬件来路)、G代码与3B解析实战(段表契约)、电机驱动基础(脉冲当量与 83kHz 的账)、放电加工与高频电源(变频与短路回退的需求源)、中断驱动的硬实时层与协作式主循环(0xD0 节拍与两级调度)、参数系统与断电恢复实战(快照幂等恢复)、PCIe 枚举实战(设备框架与自研卡的挂接点)
Author 软件开发大郭
LastMod 2026-09-11