# 3018 PCB 雕刻实践：MKS DLC32、FlatCAM、Candle、对刀与高度图

记录日期：2026-09-19。设备为 3018 雕刻机、MKS DLC32 V2.2；文件来自 FlatCAM v2024.4，使用 Candle 发送。Candle 安装版本未确认。本文记录本次实际经验，不把当前进给和切深当作所有机器通用参数。

## 1. 工作流程

```tikz
\begin{tikzpicture}[x=1cm,y=1cm]
\path[fill={rgb,255:red,16;green,24;blue,34}] (0,0) rectangle (16,7);
\node[text=white,font=\large] at (8,6.5) {PCB 雕刻：从铜层文件到实物验证};
\draw[cyan!70!white,rounded corners] (0.7999999999999998,4.45) rectangle (5.2,5.55);
\node[text=white,align=center] at (3,5) {Gerber / Excellon};
\draw[cyan!70!white,rounded corners] (5.8,4.45) rectangle (10.2,5.55);
\node[text=white,align=center] at (8,5) {FlatCAM 生成刀路};
\draw[cyan!70!white,rounded corners] (10.8,4.45) rectangle (15.2,5.55);
\node[text=white,align=center] at (13,5) {检查 NC 与范围};
\draw[cyan!70!white,rounded corners] (10.8,2.45) rectangle (15.2,3.55);
\node[text=white,align=center] at (13,3) {装夹 / 对刀 / 扫描};
\draw[cyan!70!white,rounded corners] (5.8,2.45) rectangle (10.2,3.55);
\node[text=white,align=center] at (8,3) {应用高度图};
\draw[cyan!70!white,rounded corners] (0.7999999999999998,2.45) rectangle (5.2,3.55);
\node[text=white,align=center] at (3,3) {参考点确认 Z};
\draw[cyan!70!white,rounded corners] (0.7999999999999998,0.44999999999999996) rectangle (5.2,1.55);
\node[text=white,align=center] at (3,1) {移除夹线 / 试切};
\draw[cyan!70!white,rounded corners] (5.8,0.44999999999999996) rectangle (10.2,1.55);
\node[text=white,align=center] at (8,1) {正式加工};
\draw[cyan!70!white,rounded corners] (10.8,0.44999999999999996) rectangle (15.2,1.55);
\node[text=white,align=center] at (13,1) {去毛刺 / 电气检查};
\draw[->,orange!80!white,line width=1pt] (5.2,5)--(5.8,5);
\draw[->,orange!80!white,line width=1pt] (10.2,5)--(10.8,5);
\draw[->,orange!80!white,line width=1pt] (13,4.45)--(13,3.55);
\draw[->,orange!80!white,line width=1pt] (10.8,3)--(10.2,3);
\draw[->,orange!80!white,line width=1pt] (5.8,3)--(5.2,3);
\draw[->,orange!80!white,line width=1pt] (3,2.45)--(3,1.55);
\draw[->,orange!80!white,line width=1pt] (5.2,1)--(5.8,1);
\draw[->,orange!80!white,line width=1pt] (10.2,1)--(10.8,1);
\end{tikzpicture}
```

1. **准备文件**：KiCad 导出待加工面的 Gerber 铜层；钻孔使用 Excellon。隔离铣铜、钻孔、外形切割是不同工序，分别配置刀具和深度。背面加工的翻转轴、定位孔和坐标必须统一；菲林打印的纵向 100.17% 补偿不用于 CNC 坐标。
2. **固定板材**：清理垫板和 PCB 背面，均匀支撑并牢固固定。探针压力导致板材下陷，测得的就不是自然表面；高度图不能修复松动夹持。
3. **FlatCAM**：导入 Gerber → 生成隔离路径 → 检查窄缝和孤岛 → 生成 CNC Job → 导出适合 GRBL 的 NC。
4. **Candle**：加载原始 NC，核对毫米单位、范围、坐标系、刀具、安全高度。建立板面 Z 零点，再扫描高度图。
5. **应用补偿**：保存高度图，退出编辑并勾选 Use heightmap，在同一参考 XY 点确认 Z 零点。检查补偿后的刀路。
6. **加工验证**：先用废板小区域验证，再加工整板。完成后去毛刺，检查隔离缝、短路和断路；钻孔及外形加工另行核对刀具与装夹。

## 2. FlatCAM：不是填一个切深就能直接加工

| 项目 | 设置和检查原则 |
|---|---|
| 刀具直径 | 使用实际有效切宽。V 刀随切入深度增加而变宽；CAM 的 0.1 mm 不代表实物一定切出 0.1 mm |
| 切深 Z Cut | 相对当地铜面的切入量。先确认对刀与补偿，再在废板上找能完整隔离铜的最小可靠切深 |
| XY / Z 进给 | 分别设置。依据刀具、主轴、刚度和试切结果调整，不能只依据控制器支持的速度 |
| 安全高度 | 必须越过板面起伏与途经障碍，同时不能超过 Z 行程；结束高度也要检查 |
| 后处理器 | 选择当前版本提供的 GRBL 兼容后处理器，检查换刀、暂停、主轴命令是否适用 |
| 输出检查 | 看文件内容和刀路范围，不依赖文件名；检查 G21、G90、进给、主轴及首尾运动 |

当前 NC 标记为 **default / MACH3 compatible**，含 `T1`、`M6`、`M0`，这是需要检查的兼容性风险，**尚不能据此认定它造成了此前报警**。文件还记录主轴转速 0，随后为没有 S 值的 `M03`；加工前要确认实际主轴控制方式与转速。

## 3. 对刀接线：使用 DLC32 的 PROBE 接口

```tikz
\begin{tikzpicture}[x=1cm,y=1cm]
\path[fill={rgb,255:red,16;green,24;blue,34}] (0,0) rectangle (16,7);
\node[text=white,font=\large] at (8,6.5) {无源接触探针：按接口丝印接线};
\draw[cyan!70!white] (1,1.4) rectangle (5,5.7);
\node[text=white,align=center] at (3,5.2) {MKS DLC32 / PROBE};
\node[text=white,align=center] at (3,4) {S};
\node[text=white,align=center] at (3,3) {GND};
\node[text=white,align=center] at (3,2) {5V 不接};
\draw[orange!80!white,line width=1.3pt] (5,4)--(7,4)--(7,1.8)--(10,1.8);
\draw[cyan!70!white,line width=1.3pt] (5,3)--(6,3)--(6,5.5)--(12,5.5)--(12,4.8);
\draw[white,line width=1.2pt] (11.6,4.8)--(12.4,4.8)--(12.4,3.4)--(12,2.9)--(11.6,3.4)--cycle;
\draw[orange!80!white,line width=2pt] (9,1.8)--(15,1.8);
\draw[white!60] (9,1.6) rectangle (15,1.2);
\draw[->,white,dashed] (12,2.8)--(12,1.9);
\node[text=white,align=center] at (13.9,4.2) {导电刀具};
\node[text=white,align=center] at (12,0.95) {裸铜板 / 导电对刀块};
\node[text=white,align=center] at (8,5.9) {主轴停止};
\node[text=white,align=center] at (7.7,0.2) {先验证分离无 P、接触有 P；旋转前拆掉夹线};
\end{tikzpicture}
```

无源接触探针只用 **S 和 GND**：S 接裸铜面或导电对刀块，GND 接导电刀具；接口的 5V 不接。按板上丝印辨认，不凭插座左右方向猜针脚。MKS DLC32 不是 Uno，不套用 Uno 的 A5 接法。

- 对刀时主轴停止，铜面清洁、导电；绿油和氧化层会影响接触。
- 检查夹具是否已经把刀具与铜板短接。可用万用表确认断开与接触状态。
- **先手动接触验证输入，再允许向下探测；开主轴前拆掉刀具夹线。**
- 直接接触 PCB 裸铜：没有额外对刀块厚度。使用对刀块：接触位置高于板面，需按实测块厚设置，不能把块顶当成板面零点。

官方接线手册第 12 页说明：该接口在 CNC 固件中用于 Probe，在激光固件中用于火焰检测。应确认使用对应的 CNC 固件。[Makerbase 接线手册 PDF](https://github.com/makerbase-mks/MKS-DLC32/blob/main/MKS-DLC32-main/doc/DLC32%20wiring%20manual.pdf)

## 4. 控制器与探针状态：本次容易混淆的地方

| 命令或显示 | 含义 / 本次记录 |
|---|---|
| `$I` | 大写字母 I，查询固件信息；本机返回 MKS_DLC32、`VER:1.1h.20251204:` |
| `$1=25` | 数字 1，步进电机空闲保持延时 25 ms，不是探针设置 |
| `$6` | 探针输入反相。原先为 0，用户反馈接触时 P 消失，反相后反馈已改变 |
| `?` | 实时状态查询；Candle 可能自行解析，控制台没有原始状态文本不代表探针坏了 |
| `PS: P` | 本界面显示探针触发；目标是分离无 P、接触有 P |
| `PS: XYZ` | 限位输入状态，不能用来判断探针；实际限位接线是否正常还需单独验证 |

本次根据输入状态尝试了 `$6=1`，**不要将它作为所有 DLC32 的固定值**。以实际接触测试为准。输入状态不能正确改变时，不继续自动扫描。[GRBL 配置说明](https://github.com/gnea/grbl/wiki/Grbl-v1.1-Configuration)

## 5. 对刀与高度图使用同一个基准

先建立并记录工件 XY 原点、当前工作坐标系（例如 G54）、高度图参考 XY。参考点应在后续加工中仍可接触到裸铜的位置。

初次验证只做短距离、低速探测，行程必须结合刀尖实际离板距离。`G38.2` 是朝目标方向探测；失败后应先处理报警。注意 `G90/G91` 为持续有效的绝对/相对模式，不能在失败后盲目执行原来的后续运动。

**不要扫描后在另一个任意 XY 点重新按 Z0。** 那里的铜面高度可能不同，会改变整张图使用的 Z 基准。换刀、改变刀具伸出量后必须重新对刀；板材、夹具或 XY 位置改变后，应重新评估并通常重测高度图。

使用高度图 Origin 按钮前先将刀具升到安全高度；它会移动到参考 XY，**不是只修改一个标签**。按 Candle 官方流程，在该参考点建立对应的 Z 零点，然后检查补偿程序。[Candle 高度图流程](https://github.com/Denvi/Candle/blob/master/help/en/process/creatingheightmap.md)

## 6. 高度图：测量点、插值点、应用开关是三回事

- **Probe grid**：真实接触测量。本次 4×4 为 16 点，X 间隔 20 mm、Y 间隔 30 mm；对于局部翘曲仍可能过稀。
- **Interpolation grid**：把测量结果插值得更密。本次 61×81 并不是测了 4941 个点，无法补回未测得的局部凹凸。
- **Use heightmap**：是否实际应用到程序。有彩色网格不等于已启用；本次早期截图没有勾选，后期截图已经勾选。
- **覆盖范围**：所有加工路径都应在测量范围内。超出部分没有测量保证，不能通过拉伸旧图边界代替重测。
- **插值方式**：Bicubic 可能在点间产生过冲；应结合真实板面检查，不能把漂亮平滑的曲面当成测量证据。

保存地图时确认处在高度图编辑状态并保存正确对象。保留原始 NC、地图、装夹照片、参考点和对刀记录；不要把已经补偿的程序再套一次高度图。

## 7. 补偿 Z 坐标不是实际切深

```tikz
\begin{tikzpicture}[x=1cm,y=1cm]
\path[fill={rgb,255:red,16;green,24;blue,34}] (0,0) rectangle (16,7);
\node[text=white,font=\large] at (8,6.5) {高度图改变执行 Z，目标切深保持一致};
\draw[white!40,dashed] (1,5)--(15,5);
\draw[cyan!70!white,line width=1.4pt] (1,4.5)..controls(5,4.5)and(6,2.5)..(9,2.5)..controls(12,2.5)and(13,4)..(15,4);
\draw[orange!85!white,line width=1.4pt] (1,4.05)..controls(5,4.05)and(6,2.05)..(9,2.05)..controls(12,2.05)and(13,3.55)..(15,3.55);
\draw[<->,white] (9,2.05)--(9,2.5);
\node[text=white,align=center] at (3,5.5) {坐标零平面};
\node[text=white,align=center] at (12.5,4.8) {青色：铜面};
\node[text=white,align=center] at (12.5,1.8) {橙色：刀尖路径};
\node[text=white,align=center] at (6,3.1) {表面低，刀尖也随之降低};
\node[text=white,align=center] at (8,1) {示例：铜面 Z = -0.237，刀尖 Z = -0.257};
\node[text=white,align=center] at (8,0.45) {实际切深 = 0.020 mm（纵向夸张示意）};
\end{tikzpicture}
```

在地图与工件使用同一个 Z 基准时：

```text
执行 Z(x,y) = 原程序 Z + 地图表面高度 h(x,y)
实际切入深度 = 真实表面高度 − 执行 Z
```

例如切深设为 0.02 mm：某处表面为 −0.237，执行 Z 为 −0.257，实际仍只切入 **0.020 mm**。因此预览显示最低 Z 为 −0.562，不能直接理解成处处切深 0.562。

Candle 按 XY 位置插值修改 Z，并细分路径；属于加工前生成空间变化的补偿，**不是加工时实时测量，也不是只给整板加一个固定数**。查看补偿后多个位置的实际指令，而不是只看左下角 Z 最小值；原始磁盘 NC 仍为固定 Z 也不代表内存中的程序没有补偿。[Candle 实现源码](https://github.com/Denvi/Candle/blob/master/src/candle/frmmain.cpp)

## 8. 本次文件核对结果

路径：`D:\desk\gerber`。地图 `cc.map`；原始程序 `stm32-minimal-F_Cu.gbr_iso_combined_cnc.nc`。

| 项目 | 已读取的数据 |
|---|---|
| 当前 NC 切深 | **−0.0200 mm**，不是此前口述的 −0.05 |
| CAM 刀具直径 | 0.1 mm |
| XY / Z 进给 | 120 / 60 mm/min，属于本次设置记录 |
| 移动 / 结束 Z | 2 / 15 mm |
| 刀路范围 | X 0.95～49.05；Y −99.05～−0.95 mm |
| 地图范围 | X 0～60；Y −90～0 mm |
| 明确的覆盖缺口 | Y 负方向缺 **9.05 mm**，需扩大实际扫描范围 |
| 地图探测设置 | 4×4；Zb −1、Zt 3、F 10 mm/min |
| 16 点读数范围 | −0.671～+0.005 mm，跨度 0.676 mm |

地图读数（mm）：

| Y / X | 0 | 20 | 40 | 60 |
|---|---:|---:|---:|---:|
| −90 | −0.022 | −0.057 | −0.093 | −0.141 |
| −60 | −0.226 | −0.237 | −0.326 | −0.671 |
| −30 | −0.146 | −0.224 | −0.306 | −0.604 |
| 0 | −0.009 | +0.005 | −0.034 | −0.150 |

这些是保存的测量读数；有 16 个数字并不能独立证明每次接触都可靠。最低点位于 X60，在当前刀路最大 X49.05 之外，但会影响附近插值。

## 9. 故障记录与排查顺序

| 现象 | 判断与处理 |
|---|---|
| 连续 `error:9` | 表示报警或点动状态下 G-code 被锁定；先 Abort，查最早的报警，不能一直 Ignore 或盲目解锁 |
| `ALARM:4` | 探测起始状态不符合要求，例如 G38.2 开始前已经触发 |
| `ALARM:5` | 在给定行程内未触发；查接触、电路、方向、距离，不直接加大行程撞下去 |
| 有高度图但中间切不到 | 查是否勾选、范围覆盖、实际测点密度、板材是否受力变形以及 Z 基准 |
| 整块切得过深 | 优先查共同 Z 偏差、坐标系、对刀块厚度、换刀、重复补偿；空间补偿存在也可能整体偏深 |
| 少数区域异常深浅 | 查装夹、假触发、稀疏采样、插值过冲、范围外路径及主轴/刀具状态 |

`error:9` 与 `ALARM:9` 不是同一含义。此前没有取得第一条报警，不能确认其根因。[GRBL 错误表](https://github.com/gnea/grbl/blob/master/doc/csv/error_codes_en_US.csv) · [报警表](https://github.com/gnea/grbl/blob/master/doc/csv/alarm_codes_en_US.csv)

### 整板过深：待完成的验证

用户反馈即使设置 0.02 mm 也整板很深，**目前未查明，也未完成修复验证**。

可以在主轴停止、确认安全移动后，到地图中一个已知点，例如工件 X20、Y0，缓慢接触裸铜，**不要先按 Z0**，记录第一次触发时的 Work Z。地图该点为 +0.005 mm。若实际读到 +0.200 mm，则该点基准差为 +0.195 mm，理论上 0.020 的切深会变成约 0.215 mm；这只是计算示例，不是本机实测结论。比较多个点才能区分共同偏移和局部误差。

## 10. 下次加工前的简表

- [ ] 导入正确铜层；毫米、原点、翻转方向和实物装夹一致。
- [ ] 使用兼容后处理；核对刀具、转速、进给、切深、首尾运动与安全高度。
- [ ] 探针分离无 P、接触有 P；主轴停止时完成测试。
- [ ] 地图覆盖整个刀路；真实测点密度能反映板面，所有探测完成且无报警。
- [ ] 原始 NC 只补偿一次；Use heightmap 已启用；参考 XY 与 Z 基准一致。
- [ ] 已检查补偿后的 Z 变化；换刀或板材移动后重新确认测量有效性。
- [ ] 开主轴前移除夹线；废板试切通过后再做整板。

高度图负责补偿已测得的表面形状；对刀负责建立深度基准；装夹负责让加工时的表面保持不变。三者必须同时可靠。
