脉冲型伺服:电子齿轮、接线与多轴
四条结论
- 脉冲型伺服接 Klipper 的第一道坎不是接线,是算出"发多少脉冲 = 走多少"。通式只有一条:
一圈指令脉冲数 = 编码器 P/R × 4 × 分母 ÷ 分子,但×4和"分子/分母"在不同驱动器上的参数号完全不同,抄错一组就整体差 2 倍或 8 倍。- 把一圈做成 3200 脉冲(= 200 × 16)是为了跟 Klipper 的
microsteps: 16对齐;出厂值 16384 除 200 得 81.92,填不出整数。- NPN/PNP 接反不烧机,只是光耦方向不对——现象从"完全不动"到"偶尔动一下"都有可能,后者最坑。
- 总线伺服回零的坑与脉冲伺服完全不同:Klipper 和伺服各有一套原点,回零后不同步零点,第一条绝对位置指令就会跳位。多轴扩轴则不需要改固件,
manual_stepper+GCODE_AXIS加一层宏就够。
电子齿轮:把脉冲换算成位移
通式(两家原厂手册一致):
电机转 1 圈所需指令脉冲数 = 编码器脉冲数(P/R) × 4 × 分母 ÷ 分子
- 安川 Σ-II:分子 =
Pn202、分母 =Pn203(手册 8.6.2)。 - XDS1:
Pn20E(分子)/Pn210(分母);Pn210 = 0时Pn20E直接就是"一圈的指令脉冲数",驱动器按编码器类型自己反算——免算分式,最省事。 ×4不能漏:编码器计数是 A/B 相四倍频,把 P/R 直接当一圈脉冲数会差 4 倍。
编码器位数决定分子
| 编码器位数 | P/R | ×4 后 |
|---|---|---|
| 13 位 | 2048 | 8192 |
| 16 位(最常见) | 16384 | 65536 |
| 17 位 | 32768 | 131072 |
怎么确认自己是几位:手转电机一圈看监视参数——安川 Un00D;XDS1 Un060(17 位 = 131072、20 位 = 1048576、23 位 = 8388608)。别猜铭牌,铭牌常有多个可选配置。
算例一:安川 Σ-II 16 位,要 3200 脉冲/圈
65536 × 分母 ÷ 分子 = 3200
取 分子 = 2048,分母 = 100 → 65536 × 100 / 2048 = 3200 ✓
所以 Pn202 = 2048、Pn203 = 100。等值写法 16384 / 800 也对(65536 × 800 / 16384 = 3200),差别只在参数可读性。
算例二:17 位编码器,同样要 3200
131072 × 分母 ÷ 分子 = 3200
取 分子 = 4096,分母 = 100 → 131072 × 100 / 4096 = 3200 ✓
| 驱动器 | 编码器 | 参数 |
|---|---|---|
| 安川 Σ-II | 16 位 | Pn202 = 2048,Pn203 = 100 |
| 安川 Σ-II | 17 位 | Pn202 = 4096,Pn203 = 100 |
| XDS1 | 任意 | Pn20E = 1600,Pn210 = 0 |
为什么盯 3200:3200 = 200 × 16,Klipper 里直接 microsteps: 16 就对齐;出厂 16384 除 200 得 81.92,microsteps 填不出整数。
⚠ 安川出厂是 4/1,即每圈 16384 脉冲(16 位)——设计意图是"1 指令脉冲 = 1 编码器脉冲",配 Klipper 反而不合适:不仅 microsteps 凑不出整数,在集电极开路 200 kpps 上限下只能跑 732 rpm。
XDS1 的"1600 一圈"与精度取舍
Pn20E = 1600 / Pn210 = 0 能跑,但 1600 的分辨率很粗:23 位编码器下折算出的电子齿数比 ≈ 8388608 / 1600 = 5243,远超手册建议范围 0.01~200。报警上限是 < 64000,所以能跑,但已经在边界外工作。
代价是低速易爬行/抖动、定位精度只到 1/1600 圈。对低速平稳性敏感的机器,保留出厂 10000 更好。
两个坑:
Pn20E是 32 位参数:走 RS485 Modbus 写不能用0x06(16 位写会报错),要用0x10;面板改则正常。- "一圈"若指负载轴一圈(带减速机/丝杠),不能这样设,要按
B/A = 编码器分辨率 ÷ 负载轴一圈指令量重算。
脉冲宽度:别照抄 5 µs
手册(符号 + 脉冲列)的硬约束:脉宽 τ ≥ 1.0 µs、占空比 ≤ 50%、间隔时序 > 3 µs。
| 脉宽 τ | 占空比 | 低电平 | 判定 |
|---|---|---|---|
| 1.0 µs | 20% | 4.0 µs | 合规 |
| 2.0 µs | 40% | 3.0 µs | ✅ 推荐(Klipper 对步进驱动的默认值正是 0.000002) |
| 2.5 µs | 50% | 2.5 µs | 顶格,别用 |
| 5.0 µs | 100% | 0 | ❌ 光耦来不及关断,必丢脉冲 |
⇒ 配置写 step_pulse_duration: 0.000002,全速段都安全。通用教程里的 5 µs 是从老式步进驱动器抄来的,对光耦输入的伺服是错的。
速度余量:3200 脉冲/圈时 200 kpps 对应 3750 rpm;跑 3000 rpm 只需要 160 kpps,还有余量。
[stepper_x]
step_pulse_duration: 0.000002
microsteps: 16
rotation_distance: 40 # 同步带轮/丝杠的实际导程
rotation_distance 与 microsteps 一起决定 mm/step:rotation_distance / (200 × microsteps)。3200 脉冲/圈 + 40 mm 导程 → 每脉冲 0.0125 mm。
实机体检:先看"前手值"
接一台二手/改装的伺服,先读参数再动手。一组真实的 Σ-II 前手值:
| 参数 | 前手值 | 含义 | 结论 |
|---|---|---|---|
Pn201 |
1250 | PG 分频比(反馈给上位机的 A/B 相每圈脉冲数) | 跟前手 PLC 的计数习惯有关,与指令脉冲无关,别动 |
Pn202 |
16384 | 分子(= 16 位 P/R) | 可保留 |
Pn203 |
625 | 分母 → 65536 × 625 / 16384 = 2500 脉冲/转 |
不是 200 的整数倍 ⇒ microsteps 别扭,宜改 800(→ 3200) |
Pn201 是最容易被误改的一个:它只影响反馈输出,不影响指令脉冲;改了它,上位机看到的"位置"整体缩放,而电机实际走的一圈没变。
改完怎么验
| 检查 | 期望 |
|---|---|
| 发 N 个脉冲(N = 一圈脉冲数) | 电机正好转 1 圈 |
安川 Un003 |
+65536(16 位)= 1 圈;且 Un003 = Un00C × (Pn202/Pn203) |
| 手转一圈 | Un003 变化 +65536(16 位)/ +131072(17 位) |
⚠ 含电子齿轮的参数(安川 Pn202/Pn203、XDS1 Pn20E/Pn210)手册都标"电源重起动:需要"——改完必须断电重上电,否则新值不生效,会让人误以为算错了。
NPN 与 PNP:接反了什么后果
| 项目 | NPN(共阳/源型) | PNP(共阴/漏型) |
|---|---|---|
| 公共端接法 | COM 接 +24V | COM 接 0V |
| 导通电平 | 低电平有效(拉低) | 高电平有效(拉高) |
| 常见品牌 | 松下、三菱(默认)、台达(部分) | 西门子、欧系、三菱(PNP 档) |
| 驱动器内部 | 光耦阴极接信号端 | 光耦阳极接信号端 |
接反的三个后果,按严重程度倒序:
- 不烧机——输入端是光耦隔离,只是电流方向和电平逻辑对不上,硬件不会坏。
- 信号无效——NPN 导通是把线拉低,而 PNP 输入要高电平才导通,于是收不到脉冲:电机不动,或方向反了。
- 半死不活——光耦触发阈值临界时出现"偶尔动一下/抖动/丢脉冲"。这是最坑的一种,因为现象像机械问题或参数问题,实际是电平不匹配。
两种标准接法
共阳(配 NPN 输出,低有效):
PUL+ ─┐
DIR+ ─┴── 并一起接 +24V(或 +5V)
PUL- ────── 接控制器 NPN 输出端(导通拉低)
DIR- ────── 接控制器 NPN 输出端
共阴(配 PNP 输出,高有效):
PUL- ─┐
DIR- ─┴── 并一起接 0V(GND)
PUL+ ────── 接控制器 PNP 输出端(导通拉高)
DIR+ ────── 接控制器 PNP 输出端
判断方法:看驱动器手册的输入电路图。光耦阳极引到端子(PUL+)就是共阳接法,只能配 NPN;阴极引出来就是共阴,配 PNP。老款驱动器内部只接一种方向,必须与控制器输出类型一致。
三种修法
- 改控制器侧:PLC/控制卡 NPN 输出改 PNP(或换输出模块),COM 从 +24V 改接 0V。
- 看驱动器能否切换:很多国产伺服/步进(台达、雷赛、微秒、研控)输入端子留了两种接法,或有跳线/参数("脉冲输入方式")切换。
- 加转换:中间串光耦或继电器模块,NPN 转 PNP。
一句话:让两边的"有效电平"对齐,要么改接法,要么改设置。
上电使能:三种驱动器三种做法
场景:挤出机/输送机/圆台这类旋转型负载(不定位、不停机换向),希望驱动器上电即使能、一直转,而不是每次由上位机发 S-ON。
| 驱动器 | 官方"上电恒使能" | 推荐做法 |
|---|---|---|
| XDS1(脉冲篇,仿安川系) | ✅ 有(Pn500 千位 = 1 → 常时有效) |
参数法 Pn500 = h.1000 优先 |
| 安川 Σ-II SGDM | ✅ 有(Pn50A.1 = 7 常时有效) |
Pn50A = 8170 + Pn50B = 6548 |
| FV3(旋转脉冲型) | ✅ 有 VDI + 上电默认电平 | 虚拟 DI 恒使能(免接线,最正规) |
FV3:虚拟 DI 恒使能
前提:MCU 软件版本 ≥ 8.0(查 U01.00 bit0 ≥ 8、U01.04 ≥ 0)。
① P04.50 = 1 // 开启通信 VDI 功能
② P04.54 = 1 // VDI1 端子功能 = 1(使能 SRV_ON)
③ P04.51 = 1 // 上电 VDI 默认电平:bit0 = 1 → VDI1 上电即有效
上电后 VDI1 恒有效,驱动器自动被使能,不需要外部接线,走 RS485 通讯时仍可用 F34 控制。
- 用 VDI2 则
P04.56 = 1(VDI2 功能 = 使能)、P04.51 = 2(bit1 = 1)。 P04.51是 16 位开关矩阵:bit n 对应 VDI(n+1),设哪位哪个 VDI 上电即有效。
传统做法是外部 DI 接死:DI1 出厂默认功能就是使能(P04.04 = 1,功能序号 1 = SRV_ON),P04.05 默认正逻辑;把 DI1 接到有效电平即恒使能。
XDS1:参数法优先,接线留作应急
Pn500~Pn503 的千位就是"常有效/常无效"选择:
| 千位 | 含义 |
|---|---|
h.1000 |
常时有效(内部强制 ON,不看外部) |
h.2000 |
常时无效 |
h.0000 |
由外部 IO 控制(出厂) |
出厂 Pn502 = h.2002、Pn503 = h.2003 正是拿这一位把 P-OT/N-OT 置成常无效——同一个机制。所以 Pn500 = h.1000 就能免接线恒使能。
接线做法(CN1 信号表为准):
/S-ON(伺服使能)= DI1 = CN1-9(负逻辑,ON 时电机通电)DICOM= CN1-11(I/O 信号供电,需外接 24 VDC)- 输入为双向光耦,默认 ON = 低电平 L
三种上电使能:硬件短接(DICOM 接 +24V、/S-ON 接 0V,光耦恒导通);改极性后接死(Pn500 = h.□1□□ 高电平有效,/S-ON 接 +24V);由 PLC 给使能(最安全,可控通断)。
安川 Σ-II:改两个参数就恒使能
Σ-II 走的是功能位定义:Pn50A.1 = 7 表示 /S-ON 输入"常时有效"(不看待外部电平)。实际下发值是整组参数的合成值 Pn50A = 8170,/BK(抱闸输出)相关的 Pn50B = 6548,两项一起写才能既恒使能、又保持抱闸逻辑正确。
抱闸轴(Z 轴、垂直输送)要注意:恒使能后伺服一直通电,抱闸在使能期间是松开的。如果抱闸控制位被误配,上电瞬间负载会自由下落。改完参数先空载验证 /BK 输出动作,再挂负载。
两个必踩的坑
- 多使能来源冲突:FV3 的使能来源有 DI / VDI /
Fn组功能码 / 后台点动 / 惯量辨识 / 两段位置使能——同时用多个会报Er.05.7(伺服使能故障)。上电使能只用一种,别 DI 和 VDI 同时用。XDS1 同理(可分配 DI 优先级:CN1-9(DI1) > CN1-10(DI2) > …)。 - 恒使能后没法用
/S-ON让伺服 OFF:必须保证急停回路、正负限位(POT/NOT)、抱闸(BK)全部有效,否则上电瞬间电机可能异常动作。垂直轴尤其要防坠落。
手册针号矛盾的经验:XDS1 手册 6.1.2 写 S-ON = CN1-40,而 CN1 信号表明确写 DI1 / CN1-9。以实物接线图/丝印为准,别照抄手册某一页就接线。
总线伺服回零:两套坐标系打架
脉冲伺服由 Klipper 独占脉冲计数,不存在原点歧义。总线伺服不是——存在两套原点:
- Klipper 坐标系:撞限位 → 触发瞬间把当前位置设为
position_endstop→ 原点 = 限位触发点。 - 伺服内部坐标系:CSP 模式每周期下发绝对目标位置,伺服用自己的编码器闭环 → 原点 = 编码器零位(或断电记忆的绝对位置)。
回零完成后 Klipper 认为 X = 0,但伺服编码器读数不是对应计数值。第一条绝对位置指令下发时,伺服按"自己原点算的位置"当目标 → 跳位、坐标错乱、跟随误差报警。
三种解法
方案一:回零后同步伺服零点(推荐)。Klipper 正常撞限位回零,再通过总线把伺服实际位置清零(DS402 的 0x2077 Set actual position,该族伺服有位置预设/清零功能),让伺服编码器零位 = Klipper 零点。用 homing_override 包一层:
[homing_override]
axes: xyz
set_position_x: 0
gcode:
G28 X Y Z
SYNC_SERVO_ZERO # 自定义宏:向三轴伺服写实际位置 = 0
方案二:伺服自己回零,Klipper 跟随。把 DI4 配成 HOME(功能号 0x16),伺服硬件锁存回零,精度 ±1 count,比 IO 板 10 ms 轮询端止高一个量级。完成后 Klipper 用 G92 X0 或 SET_KINEMATIC_POSITION 对齐。前提是伺服物理原点与 position_endstop 在同一位置。
方案三:绝对编码器免回零。多圈绝对值编码器断电记忆位置,开机读伺服实际位置后 SET_KINEMATIC_POSITION 恢复坐标,物理上不用每次回零,是工业机的标准做法。
CiA402 回零序列
1. 切回零模式 0x6060 = 6 (homing mode)
回零方式 0x6098 = 1 或 17/19(Hw0:硬件 home 开关)
2. 启动回零 0x6040 控制字 = 0x2F → 0x2F|0x10(bit4 = start)→ 0x2F
3. 等待完成 0x6041 状态字 bit12(homing attained)或 bit10(target reached)
超时保护(30 s,防开关坏了一直撞)
set_position 由开关位置决定
| home 开关位置 | set_position |
position_min |
说明 |
|---|---|---|---|
| X 最小端(左) | set_position_x: 0 |
0 | homing_positive_dir: true |
| X 最大端(右) | set_position_x: 400(= 行程值) |
0 | 写成 0 → 归零后以为在 0、实际在 400 → 撞机/镜像 |
最常见的坑:set_position_x: 0 写死,但开关装在最大端。
四个连带坑
- 软限位:伺服内部软限位必须与 Klipper 的 min/max 一致,否则伺服先报警,Klipper 还以为是自己的问题。
- 跟随误差:回零后第一个运动命令前没做零点同步 → 必报位置偏差过大。
- IO 板端止精度:10 ms 轮询,高速回零误差 ≈
10 ms × 速度;高精度回零走伺服自带 DI。 - 限位方向冲突:
POT/NOT别和 Klipper 的回零方向打架。
Klipper 多轴:从原生到纯宏
原生能力(v0.13.0 起)
Klipper 把多轴从社区宏提升为原生功能,关键项:
| 能力 | 说明 |
|---|---|
| 6+ 轴支持 | 同时控制超出 X/Y/Z/E 的额外轴 |
| Generic cartesian | 通用笛卡尔运动学 |
| Load cell probing | 测力传感器探测 |
| Hybrid CoreXY / CoreXZ | 混合运动学 |
| ldc1612 | 涡流传感器,接近探测 + 快速扫描 + 温度校准 |
| RP2350 | 400+ MHz MCU 支持 |
同一版本还带来 minimum_cruise_ratio(替代 max_accel_to_decel)、Adaptive Bed Mesh、Sweeping Vibrations 共振测试、风扇/GPIO 的 Jinja2 模板,以及 RP2040 提到 200 MHz、命令数从 128 扩到 16384。
纯宏方案(MAF):不改固件
关键是 Klipper 合并的 GCODE_AXIS 支持:manual_stepper 可以绑定到 G-code 轴。
MANUAL_STEPPER STEPPER=stepper_x1 GCODE_AXIS=A
G0 A100 # 现在可以直接用 G-code 控制额外轴
但原生只支持 G0/G1。MAF 多轴框架补全了缺失的部分:
| 命令 | 原生 Klipper | +MAF |
|---|---|---|
G0/G1 多轴 |
✅ | ✅ + 相对挤出 |
G28 多轴归零 |
❌ | ✅ |
G92 多轴设位 |
❌ | ✅ |
M82/M83 多挤出机 |
❌ | ✅ |
T0/T1 工具切换 |
❌ | ✅ |
M104/M109 T<n> |
❌ | ✅ |
配置是纯字典,一轴一条:
[include maf.cfg]
[gcode_macro MY_MAF]
variable_maf = {
"X": { "motor": "stepper_x", "dir": -1, "end_pos": 0 },
"Y": { "motor": "stepper_y", "dir": -1, "end_pos": 0 },
"Z": { "motor": "stepper_z", "dir": -1, "end_pos": 0, "bounce": 2 },
"E": { "motor": "extruder" },
"U": { "motor": "stepper_x1", "dir": -1, "end_pos": 0 }, # 第 2 X 滑架
"V": { "motor": "stepper_x2", "dir": 1, "end_pos": 380 }, # 第 3 X 滑架
"W": { "motor": "stepper_x3", "dir": -1, "end_pos": 0 }, # 第 4 X 滑架
"A": { "motor": "extruder1" },
"B": { "motor": "extruder2" },
"C": { "motor": "extruder3" }
}
dir 与 end_pos 是逐轴的机械定义——dir: -1 表示该轴朝负方向回零,end_pos 是回零后该轴应处的坐标。这两个值写错,表现是"回零往反方向撞"或"归零后坐标偏移一个行程"。
工具轴映射(inline multi-tool)把逻辑工具映射到物理轴:
variable_tools = {
"T0": { "X":"X", "Y":"Y", "Z":"Z", "E":"E" },
"T1": { "X":"U", "E":"W" },
"T2": { "X":"A", "Y":"B", "E":"C" },
"T3": { "X":"I", "E":"K" }
}
配合 inline multi-tool G-code,一行里所有工具同时动作:
G1 T0 X100 Y10 E1 T1 X200 E1 T2 X100 Y200 E1 T3 X200 E1
这是 MAF 最实用的设计:Klipper 没有并行运动队列,但"一行 G-code 内多工具原子执行"可以模拟出多龙门同步动作。
多工具复制(duplication):
variable_duplication = {
"T0": { "offset": [0,0], "size": [200,200], "row": 0 },
"T1": { "offset": [200,0], "size": [200,200], "row": 0 },
"T2": { "offset": [0,200], "size": [200,200], "row": 1 },
"T3": { "offset": [200,200], "size": [200,200], "row": 1 }
}
MAF DUPLICATION=copy # 或 mirror
开启后,单工具 G-code 自动展开为所有工具并行打印——同一构件一次出四件,大幅面批量生产直接用。
硬件配置:驱动必须写在 manual_stepper 之前
[tmc2209 manual_stepper stepper_x1] # 驱动段必须在 manual_stepper 之前
uart_pin: mcu2:PC11
diag_pin: ^mcu2:PC0
run_current: 0.580
stealthchop_threshold: 999999
driver_SGTHRS: 100
[manual_stepper stepper_x1]
step_pin: mcu2:PB13
dir_pin: mcu2:PB12
enable_pin: !mcu2:PB14
microsteps: 16
rotation_distance: 40
endstop_pin: tmc2209_stepper_x1:virtual_endstop # 无传感器归零
顺序错了 TMC 段会挂不上,现象是 Unable to parse 或驱动电流不生效。virtual_endstop(StallGuard 无传感器归零)在大幅面机器上很实用:不用为每个额外轴装限位开关。
限制
- ❌ 没有多运动队列:Klipper 的所有
G0/G1串行执行(RepRapFirmware 有并行队列)。多龙门并行只能靠 inline multi-tool 在单行里做原子操作。 feedrate由主 XYZ 轴决定,额外轴的速度由 MAF 内部保护——意味着给额外轴单独设 F 值不会生效。
一个 11 轴实例
真实配置:2 个 Y 龙门 + 4 个 X 滑架 + 4 个挤出机 = 11 轴。
模式 1:1× Klipper(4 个 MCU)→ 11 轴全同步
模式 2:2× Klipper(各 2 个 MCU)→ 两个龙门松散同步
操作模式是 MAF DUPLICATION=copy(水平/垂直复制)或 mirror(镜像),单份 G-code 由 4 个工具同时执行。
对大幅面/混凝土打印,这套方案的价值在四点:多龙门并行(多个喷嘴同打)、多挤出机独立流量、copy/mirror 批量复制、以及 virtual_endstop 免装限位。而且它兼容 Kalico,不需要为了多轴去改固件分支。
脉冲还是总线:选择判据
同一台机械上,两种驱动方式可以互相做对照实验——出现过"脉冲方式打印正常、EtherCAT 线宽脉动"的案例,正好把问题锁定在主站时序而不是轨迹(见 EtherCAT 伺服 的线宽脉动一节)。
| 维度 | 脉冲(Step/Dir) | 总线(EtherCAT/CANopen) |
|---|---|---|
| 接线 | 每轴 3 对线(PUL/DIR/ENA)+ 限位 | 一根网线串所有从站 |
| 确定性 | 由出脉冲的 MCU 保证,不受主机影响 | 取决于主站实时性(内核态/硬主站) |
| 速度上限 | 集电极开路 200 kpps;3200 脉冲/圈 → 3750 rpm | 受周期与带宽限制,无脉冲频率概念 |
| 状态回读 | 无(只能读驱动器面板/调试口) | 每周期可读位置/速度/扭矩/误差(CiA402) |
| 调参 | 电子齿轮 + 脉宽 + microsteps |
PDO 映射 + 控制字状态机 + DC 同步 |
| 故障现象 | 不动 / 丢脉冲 / 方向反 | 跳位 / 跟随误差 / 同步错误码 |
一批驱动器同时支持三种模式(脉冲 / CANopen / EtherCAT),选型时按"要不要状态回读"和"轴数 × 距离"决定:
- 轴少、行程小、只要动起来:脉冲最省事,参数就那几个,出问题一眼能定位到接线或电子齿轮。
- 轴多、跨距大、要做闭环优化(堵料检测、碰撞检测、压力提前):总线是唯一选择,因为脉冲方式拿不到扭矩和位置误差。
- 两者混用(主轴走总线、辅助轴走脉冲)在工程上可行,代价是回零与坐标系要分别处理——脉冲轴的原点在 Klipper 里,总线轴的原点在伺服里,两套逻辑不能混着调试。
电子齿轮这条链在任何模式下都得算对:总线伺服同样有"每圈多少 counts"的换算,position_scale 就是它的电子齿轮。算错的表现也一致——整体差整倍数。
相关阅读
- EtherCAT 伺服接入 Klipper / Kalico —— 从站拓扑、host MCU、CSP 诊断、1000 mm/s 边界
- Klipper 挤出机配置要点 ——
rotation_distance、microsteps与流量