4. 校准XYZ轴步进值

任务说明

Klipper固件通过rotation_distance参数将步进电机步数映射为实际运动距离。当该值不准确时,打印件尺寸会系统性偏差(例如模型设计为20mm,实际打印为19.6mm)。本案例目标:使用卡尺测量各轴实际运动距离,反向计算并更新rotation_distance,使运动误差控制在0.1mm以内。

校准原理与计算

Klipper官方推荐方法:先临时设置一个已知的rotation_distance(如初始值40),发送移动命令让轴运动理论距离D_target,用卡尺测量实际运动距离D_actual,则修正后的值为:

rotation_distance_new = rotation_distance_old × (D_actual / D_target)

本案例提供Python脚本自动完成测量数据录入、计算与配置更新,并给出验证流程。

实现代码

#!/usr/bin/env python3
"""
calibrate_rotation_distance.py
用法: python3 calibrate_rotation_distance.py [配置文件路径]
默认读取 ./printer.cfg
"""
import sys
import re
from pathlib import Path

CONFIG_PATH = Path(sys.argv[1]) if len(sys.argv) > 1 else Path("./printer.cfg")

def get_current_rd(axis: str) -> float:
    """从printer.cfg中读取当前轴的rotation_distance"""
    pattern = re.compile(
        rf"^\[({axis}_axis|stepper_{axis})\]\s*$",
        re.MULTILINE
    )
    content = CONFIG_PATH.read_text()
    match = pattern.search(content)
    if not match:
        raise ValueError(f"未找到 [{axis}_axis] 或 [stepper_{axis}] 配置段")
    # 从该段开始查找第一个 rotation_distance
    section_start = match.end()
    next_section = re.search(r"^\[", content[section_start:], re.MULTILINE)
    section_body = content[section_start:] if not next_section else content[section_start:section_start + next_section.start()]
    rd_match = re.search(r"^\s*rotation_distance\s*:\s*([0-9.]+)", section_body, re.MULTILINE)
    if not rd_match:
        raise ValueError(f"{axis}轴配置段中未找到 rotation_distance")
    return float(rd_match.group(1))

def update_rd(axis: str, new_rd: float) -> None:
    """更新配置文件中的rotation_distance值"""
    content = CONFIG_PATH.read_text()
    pattern = re.compile(
        rf"^(\[{axis}_axis|stepper_{axis}\]\s*$.*?rotation_distance\s*:\s*)([0-9.]+)",
        re.MULTILINE | re.DOTALL
    )
    if not pattern.search(content):
        raise ValueError(f"无法定位 {axis} 轴的 rotation_distance 配置")
    updated = pattern.sub(lambda m: m.group(1) + f"{new_rd:.4f}", content, count=1)
    CONFIG_PATH.write_text(updated)
    print(f"已更新 {axis} 轴 rotation_distance: {new_rd:.4f}")

def calibrate_axis(axis: str) -> None:
    """执行单轴校准流程"""
    print(f"\n=== 校准 {axis.upper()} 轴 ===")
    old_rd = get_current_rd(axis)
    print(f"当前 rotation_distance: {old_rd}")
    try:
        d_target = float(input(f"输入理论运动距离(mm,建议50): "))
        d_actual = float(input(f"输入卡尺实测距离(mm): "))
    except ValueError:
        print("输入无效,请输入数字")
        return
    if d_target <= 0 or d_actual <= 0:
        print("距离必须为正数")
        return
    new_rd = old_rd * (d_actual / d_target)
    print(f"计算新 rotation_distance: {new_rd:.4f}")
    confirm = input("写入配置文件? (y/N): ").strip().lower()
    if confirm == 'y':
        update_rd(axis, new_rd)
    else:
        print("已取消写入")

def main():
    if not CONFIG_PATH.exists():
        print(f"错误: 找不到配置文件 {CONFIG_PATH}")
        sys.exit(1)
    print(f"使用配置文件: {CONFIG_PATH}")
    for axis in ['x', 'y', 'z']:
        calibrate_axis(axis)
    print("\n校准完成。请重启Klipper服务使配置生效:")
    print("  sudo systemctl restart klipper")

if __name__ == "__main__":
    main()

落地步骤

  1. 将上述脚本保存为calibrate_rotation_distance.py,与printer.cfg置于同一目录。
  2. 确保打印机处于待机状态,通过Klipper终端或控制台发送命令移动X轴至行程中点。
  3. 运行python3 calibrate_rotation_distance.py,按提示依次输入理论距离(建议50mm)和卡尺实测距离。
  4. 对Y、Z轴重复相同操作。Z轴测量时需安装千分表或使用已知高度块规。
  5. 脚本自动更新配置文件后,重启Klipper:sudo systemctl restart klipper。

验证方法

重启后发送移动命令使各轴运动50mm(如G91后G1 X50 F600),用卡尺测量实际位移。判定标准:实测值与目标值偏差≤0.1mm即校准通过。若偏差仍超限,重复上述校准流程一次(通常一次迭代即可收敛)。

XYZ轴步进值校准流程 1. 读取printer.cfg 获取当前rotation_distance 2. 移动D_target并测量 卡尺读取D_actual 3. 计算新值 new = old × (D_actual/D_target) 4. 写入配置文件 更新rotation_distance 5. 重启Klipper服务 sudo systemctl restart klipper 6. 验证测量 移动50mm,实测偏差≤0.1mm 偏差≤0.1mm? 是 校准完成 否:重复步骤2-6(通常一次收敛)

注意事项

  • 测量时确保运动方向无背隙影响,建议同方向多次运动后取平均值。
  • Z轴校准建议使用块规或千分表,卡尺测量Z轴行程误差较大。
  • 修改配置前备份原文件:cp printer.cfg printer.cfg.bak。
  • 若打印机使用微步进或不同驱动模式,rotation_distance与步数关系不变,本方法依然适用。