跳转至

调平与探针

调平不是一个动作,是三层:先让龙门/机架自身水平(多 Z 找平),再测床面形状(网格), 最后定义 Z 零点(探针偏移)。顺序不能反 —— 上一层变了,下一层的测量全部作废。

大幅面机(1 m 以上 / 大喷嘴 / 混凝土)和桌面机是两套完全不同的方案,混用必踩坑。

一、先分层,再选方案

层 解决什么 手段 失效后果
L1 机架找平 龙门/横梁自身歪斜、四立柱不等高 Z_TILT_ADJUST(2 个 Z)/ QUAD_GANTRY_LEVEL(4 个 Z) 首层一边厚一边薄,网格怎么测都补不平
L2 床面形状 床板本身的凹凸、热变形 BED_MESH_CALIBRATE(网格补偿) 首层局部过高刮床 / 过低不粘
L3 Z 零点 喷嘴到床的实际间隙 PROBE_CALIBRATE → z_offset 整体首层偏高或偏低,靠手调救

关键关系:L2 的网格是「相对高度表」,它的基准面就是 L3 定义的 Z 零点。 所以 z_offset 一变,之前测的网格整体平移、直接作废。官方文档写得很直白: Prior to Mesh Calibration you will need to be sure that your Probe's Z-Offset is calibrated.

G28 → PROBE_CALIBRATE / TESTZ 逼近 → ACCEPT → SAVE_CONFIG
G28 → BED_MESH_CALIBRATE → BED_MESH_PROFILE SAVE=default

L1 又在 L2 之上:龙门没找平就去测网格,等于用一个歪的尺子量床面, 补偿量会被机架误差污染,越补越乱。

二、大幅面机的方案选型

1 m 以上的床,热变形量级是零点几毫米(实测:同一点冷床 +0.55 mm, 加热到 80 °C 变成 +0.94 mm,热变形约 0.4 mm)。这个尺度上「手动调平」和「单 Z 电机」都不成立。

方案 硬件成本量级 精度 扫描 1 m 床耗时 适用
多 Z(2–4)+ 电涡流探头 ⭐ 探头 300–500 元 + 每多一根 Z 电机约 200 元 ±20 μm ~30 s 大幅面首选;非接触、无磨损
多 Z + BLTouch 克隆 探头 ~40 元 + 电机 ~80 元 ±50 μm 级 3–5 min 预算卡死、不常换床
纯电感接近开关(PL-08N) 几十元 温漂 0.1 mm+ — 不推荐:冷热态偏差吃掉全部精度
单 Z + 手动 0 — — 不成立:龙门必然一头高一头低

混凝土 / 颗粒料打印的特殊约束

大喷嘴会粘料,常规接触式探针没法戳(戳一下带一坨料走)。三条路:

  1. 激光测距(如 Panasonic HG-C1030 一类,约 800 元)—— 非接触,粘料无所谓
  2. 首层视觉补偿 —— 摄像头拍首层,偏差反馈回 G-code
  3. 龙门找平必须做 —— 用机械限位块 + 编码器绝对定位

三、四 Z 调平的四个硬规则(quad_gantry_level)

这四条都是「不知道就一定会把机器拧坏」的级别。

规则 1:gantry_corners 的顺序 = 电机顺序

[quad_gantry_level]
gantry_corners:      # 顺序 ↔ 电机,绝不能错
   1100,800          #   → stepper_z    (DRIVER0)
   1100,100          #   → stepper_z1   (DRIVER1)
   -100,100          #   → stepper_z2   (DRIVER2)
   -100,800          #   → stepper_z3   (DRIVER3)
points: 950,750 / 950,150 / 50,150 / 50,750
speed: 100
horizontal_move_z: 20

角位与 stepper_z / z1 / z2 / z3 的对应关系必须现场逐根核对。 反了的后果不是报错,是四根立柱朝互相相反的方向扭转,把龙门拧变形。

同理,给 gear_ratio / rotation_distance 时四个 Z 必须一起改, 漏一个 ⇒ 同一段 G28 Z 里四电机按不同比例走。

规则 2:points 必须落在四角围成的矩形内

Klipper 要求探测点在 gantry_corners 围成的矩形内。出界不报错,而是外推, 误差被放大。报错信息是 Probe points outside gantry corners。

立柱常装在行程之外(比如 X −100 / 1100 而行程是 0–1000),所以取点要往里收:

项 立柱位置 取点
X −100 / 1100 50 / 950(各收 50 避开软限位)
Y 100 / 800 150 / 750

[bed_mesh] 的 mesh_min/mesh_max 应与 QGL 的 points 对齐, 否则网床测量范围出界,边缘照样外推。

⚠️ 结构性限制:立柱 Y 只跨 100–800 而机床 Y 行程 1000 ⇒ Y < 100 / Y > 800 的台面 本身调平覆盖不到,这是机械决定的,靠改配置解决不了。

规则 3:只有 1 个 Z 端停时,「端停当探针」要三处联动

四 Z 机常常只装一个 Z 限位开关。要把它当床探针用,必须同时改三处:

[stepper_z]
endstop_pin: probe:z_virtual_endstop   ; 原 ^PD11 —— 引脚交给 probe 管
# position_endstop: -13                  ; 注释掉,改由 probe 的 z_offset 决定

[probe]
pin: ^PD11        ; 就是原来 Z 端停那个脚
z_offset: -13     ; 与旧 position_endstop 对齐 ⇒ 归零后坐标不变
  • 只把 [probe] pin 写成 PD11 而不改 [stepper_z] endstop_pin ⇒ 启动报 pin PD11 used multiple times
  • z_offset 取旧 position_endstop 的值,是为了让 G28 Z 之后坐标仍显示 0(不改变已有坐标系)
  • 常闭探针保留 ^!,常开去掉 !;x_offset / y_offset 按探针相对喷嘴的实际位置填

规则 4:Mainsail 里看不到按钮 = 配置没加载,不是配置错

症状:printer.cfg 里已经写了 [quad_gantry_level],Mainsail 左侧 MACHINE → Tools 里却没有按钮。

原因:Klipper 没重启。Mainsail 的按钮是从 Klipper 内存里的对象列表生成的。 核对方法:printer.cfg 的 mtime 晚于 Klipper 进程启动时间 ⇒ 就是没加载。

处理:FIRMWARE_RESTART。重启后起不来,优先看两类错误:

  • pin ... used multiple times(规则 3)
  • Probe points outside gantry corners(规则 2)

四、最隐蔽的失效:探针下探余量 = 0

这是「探针没坏、点位也测得到,但第二点就报 No trigger on probe after full movement」 的真根因,非常容易被误判成硬件故障。

机理

下探目标高度 = [stepper_z] position_min           (probe.py: descend_until_trigger → lookup_minimum_z)
探针归零后触发瞬间的喷嘴坐标 = [probe] z_offset
⇒ 可探条件:bed_z ≥ position_min − z_offset

两个值重合(余量 0)时,只有比归零中心高的点能探到,低 0.05 mm 就报 No trigger。

现场特征(可用来识别这个坑)

probe: at 50.000,50.000 bed will contact at z=0.940625   ← 第1点(中心)正常触发
probe: at 50.000,50.000 bed will contact at z=0.931250   ← samples=2 也正常
!! No trigger on probe after full movement               ← 第2点(远端)挂
// Klipper state: Shutdown

判据:中心点每次成功、远端点每次失败,且远端床面比中心低 → 就是余量问题,不是探针坏。

另一个旁证:z_offset = 0 期间同样的 Z_TILT_ADJUST 连续 8 次全部成功; 改成负值之后一次都没成功过。

修法

[stepper_z]
position_min: -15     # 原 -5;与 z_offset=-5 配合得到 10 mm 余量

更干净的路子是重标 z_offset:正常应为正值;出现负值本身说明喷嘴零位关系不对 (首层高度会整体偏),重标后设 position_min = z_offset − 8。

余量留多少?按热变形量级算:冷床 +0.55 → 热床 80 °C +0.94,约 0.4 mm 变形, 再给装配误差和探测重复性留量 —— 5 mm 是下限不是目标。

五、涡流位移传感:为什么能在冷端测喷嘴

消费级标杆(Bambu Lab A1 系列)被普遍误称为「load cell / 应变片」, 实际是涡流位移传感器 + 弹簧浮动热端:

喷嘴触床 → 热端被床面顶起(轴向浮动)→ 散热鳍与涡流线圈间隙变小
→ 线圈阻抗/谐振频率变化 → 触发「已接触」→ 记录 Z 零点
  • 热端(喷嘴 + 加热块 + 散热鳍 + 热断一体)由卡扣 + 防转盘固定, 允许轴向滑动但不旋转
  • 涡流线圈装在挤出机与热端之间、热端正上方(冷区),测散热鳍顶面的位移
  • 一感多用:Z 归零、床面网格(最高 21×21)、熔体背压 → 自动压力提前(PA)

三代产品的技术路线对照

机型 调平传感器 探测方式 首层/流量检测
A1 / A1 mini 工具头涡流线圈(测散热鳍位移) 喷嘴触床 + 浮动热端 同传感器测熔体背压 → 自动 PA
X1 / X1C 热床下 3 个压电陶瓷力传感器 + 预紧弹簧 喷嘴按压热床 力传感器网格 + 微 LiDAR 复核
P1 / P1S 同 X1 床下力传感器 同 X1 无 LiDAR

四条核心优势

  1. 零探针偏置 —— 测的就是喷嘴触床,无 z_offset 标定,换板不用重调
  2. 传感器在冷端 —— 测散热鳍顶面(风扇强制冷却),避开 250 °C 高温区
  3. 无机械探针 —— 没有伸缩针,可靠、快(所以敢做 21×21 密集网格)
  4. 一感多用 —— 归零 + 网格 + 熔体压力自动 PA + 打印中实时监测

代价:热端必须轴向浮动(降低刚性,装配纪律要求高);传感器靠近热源有温漂。

温度补偿的四条做法

  • 归零时喷嘴须 ≤ 140 °C —— 保证热膨胀状态一致
  • 传感器冷区化 —— 测散热鳍而非加热块
  • 判定用信号突变(微分判据)而非绝对值 —— 抗基线漂移
  • 每次归零/调平重新建立基线(tare)

移植到 1.5 mm 颗粒热端:力程放大 10 倍

这是不能直接抄的关键差异:

喷嘴 熔体背压
0.4 mm 2.5–3.8 N
1.5 mm 35–53 N(F = P × A,约 10 倍)
  • 探测小力(几 N)+ 挤出大力(几十 N)方向相反,量程跨度大,弹簧刚度要重新设计
  • 浮动系统对重热端(马达 + 减速 + 料筒)固有频率低,要加阻尼
  • 压力—位移传递函数必须随整机标定 —— 不能抄原厂 K 值

最值得抄的是架构:浮动热端 + 冷端位移传感 + 微分触发。开源可参照 Prusa MK4/XL 的 loadcell、Voron TAP(磁力耦合位移)、BDPressure(350 Ω 应变片 + 惠斯通电桥)。

面包板原型的低成本验证路线

方案 元件 成本
LDC1612/LDC1614 模块(推荐) TI 电感数字转换器,免自搭振荡电路;自绕 Φ10 mm 空心线圈(0.2 mm 漆包线 15–20 圈),ESP32/Arduino SPI 读 ~20 元
74HC14 施密特触发器 线圈 L + 100 pF 电容并联成 LC 谐振,74HC14 维持自激;金属靠近 → 涡流损耗 → 等效电感减小 → 频率升高;单片机定时器输入捕获测频 ~2 元

测试顺序(顺序很重要):频率—距离标定曲线(3/2/1.5/1/0.5/0.2/0 mm 逐档,确认单调) → 温漂测试 → 触发阈值与滞回标定。

⚠️ 涡流方案对非金属床无效(玻璃台面等),上方案前先确认床材质。

六、压力称重调平:Creality 路线的两个坑

桌面机另一条主流路线是床下 4 路 HX711 称重,喷嘴触床产生力信号触发 Z。 好处是无需探针、探测点就是喷嘴;坏处是软件闭源、易出「保存了不生效」的问题。

坑 1:模块压根不读 z_offset

实测取证链(这是典型形态,值得记住怎么查):

步骤 结果
① 屏上点「保存 Z offset」 ✅
② 发出 Z_OFFSET_APPLY_PROBE ✅ 日志有
③ probe.py 写进 [prtouch_v2] z_offset ✅ save_config: set ... z_offset = -1.100
④ SAVE_CONFIG 写进 printer.cfg #*# 段 ✅
⑤ 下次 G28,模块读这个值 ❌ 它压根不读

模块内硬编码 def get_position_endstop(self): return 0;它真正读的参数列表里没有 z_offset。 而「保存」之所以看起来成功,是因为该机的 probe 对象挂在这个 section 名下, Klipper 的通用保存机制认得这个名字 —— 名字对了,对面没人接。

旁证:历史值 -0.350 → -0.800 → -1.700 → -1.100 乱跳 = 每次都在重新猜, 没有任何反馈闭环。

真正决定 Z 基准的杠杆是模块自己的补偿参数(如喷嘴热膨胀补偿 noz_ex_com)+ 网床。

三条出路:

方案 做法 评价
A 通用 Z 偏移持久化 [save_variables] + 自定义 ZCOMP_SAVE/ZCOMP_APPLY,PRINT_START 里 G28 后套用 最稳、不碰第三方模块;换机要重配
B 改模块自己认的参数 改补偿系数 = 整体平移 Z 基准 要手算差值,SAVE_CONFIG 才生效
C 给模块打补丁 让它认 z_offset 最「正确」,但要改第三方模块归零逻辑

坑 2:打补丁时的四个陷阱

  1. 必须完整重启 Klipper 进程 —— Python 模块缓存,RESTART 不够。 验证:看 .pyc 的重新编译时间。
  2. 补丁生效前先清垃圾值 —— 把 #*# 段里累积的旧 offset 归零。 否则补丁一生效,那个「不生效时期」攒下的 -1.100 会真的生效,首层直接悬空 1.1 mm。
  3. 符号约定 —— 负值 = 喷嘴抬高(与标准 [probe] 语义一致)。
  4. 旧暂存会覆盖现场改动 —— 下载过的 /tmp/printer.cfg 里还带旧值, 直接套用会把归零又写回旧数。

七、BLTouch:引脚复用与混用限位

引脚复用规则(源码级)

Klipper 的 pins.py:同一引脚只有「用法类型 + 极性都相同」才允许复用。

场景 结果
[stepper_x]/[stepper_y] 共用 enable_pin: !PC15 ✅
[stepper_z]/[stepper_z1] 共用 endstop_pin: !PB13 ✅
BLTouch 的 control_pin 撞上 enable_pin: !PB6 ❌ pin PB6 used multiple times
断料检测的 switch_pin 撞上风扇 pin: PA1 ❌

另一个机制:重复 section 不报错,后面的覆盖前面的 (RawConfigParser(strict=False),注释写 overrides apply linearly)。 ⇒ 不要靠「重复段」兜底,stepper_z 应在原地改,而不是新增第二个 [stepper_z]。

★ Can't add signal that is already active 的真根因

这个报错看着像信号/中断问题,实际是一轴上混用了两种限位:

  1. 出处 src/trsync.c:同一路 trigger-sync 只能挂一个信号
  2. 全固件只有 stepper_stop_on_trigger 会挂信号 —— 挂的是步进电机 ⇒ 问题在「电机 ↔ 限位/归零」的装配,与引脚、PWM 无关
  3. 官方明确禁止一轴混用(homing.py): Can't home to mix of probe:z_virtual_endstop rails
  4. 典型触发:把 [stepper_z] 改成 probe:z_virtual_endstop 后, [stepper_z1] 还留着机械 endstop_pin: !PB13 ⇒ 轴上变成「探针 + 机械」两个不同限位

改之前不报错,是因为两个 Z 电机共用同一个引脚,Klipper 按引脚名把它合并成一个限位。

修法(一处):[stepper_z1] 里注释掉 endstop_pin —— 双 Z 的第二个电机不参与归零。 改完执行 FIRMWARE_RESTART(不是 RESTART)。

BLTouch 分步验证流程

顺序:先控制脚、再信号脚、再精度、最后标定。

FIRMWARE_RESTART                        # 先从 shutdown 恢复
BLTOUCH_DEBUG COMMAND=pin_down          # 针伸出 + 红灯灭
BLTOUCH_DEBUG COMMAND=pin_up            # 针收回 + 红灯亮
BLTOUCH_DEBUG COMMAND=self_test         # 完整自检
# 信号脚:pin_down → 指甲轻顶上顶 → QUERY_PROBE 应 TRIGGERED
PROBE_ACCURACY SAMPLES=20 PROBE_SPEED=2 # 标准差 < 0.01 mm 算好;range > 0.05 mm 说明干扰大
G28                                     # 探针下降时用指甲顶住,机器应立刻停
PROBE_CALIBRATE → TESTZ Z=-0.1 → … → ACCEPT → SAVE_CONFIG

判据:两次 QUERY_PROBE 都 open 或都 TRIGGERED ⇒ 信号线 / 上拉 / 配置问题, 不是机械问题。

校准宏(最小可用版)

[gcode_macro Z_OFFSET_CALIBRATE]
description: Z偏移校准:归零 → 移到床中心 → 进入 PROBE_CALIBRATE
variable_center_x: None          # None = 自动取行程中心
variable_center_y: None
variable_travel_z: 20            # 安全高度,跑之前确认平台上没有超过 20 mm 的夹具
gcode:
    {% set amin = printer.toolhead.axis_minimum %}
    {% set amax = printer.toolhead.axis_maximum %}
    {% set cx = center_x if center_x is not none else (amin.x|float + amax.x|float) / 2.0 %}
    {% set cy = center_y if center_y is not none else (amin.y|float + amax.y|float) / 2.0 %}
    M117 Z校准:归零中...
    G28
    G1 Z{travel_z} F600
    G1 X{cx} Y{cy} F6000
    M117 Z校准:TESTZ 微调
    PROBE_CALIBRATE

八、什么时候两者同时失效

这些操作会让 z_offset 和 bed mesh 同时作废,做完必须重跑全流程:

  • 拆装 / 挪动探针
  • 换喷嘴
  • 动床螺丝
  • 跑 Z_TILT_ADJUST / QUAD_GANTRY_LEVEL / DELTA_CALIBRATE(探针有 X/Y 偏移时)

还有一个最容易被忽略的:温度必须一致。探针触发高度随温度漂移, 要么都在室温下做、要么都在打印温度下且等热稳定 —— 混着做等于白做。

相关阅读