教程 · 入门 · 25 分钟
每毫米步数:皮带、丝杠与分辨率
80 和 400 步/毫米是怎么来的,皮带和丝杠为何在分辨率与速度之间各有取舍,以及如何用尺子标定这个数,而不是盲信它。
一个数,一个公式
步进驱动器数脉冲。你的机器以毫米移动。把两者换算起来的那个数是每毫米步数,而机器上其他每一项标定都依赖它是对的。
这个公式从不变:
steps/mm = (full steps per revolution × microstepping) ÷ travel per revolution
分子由电机和驱动器定死——一台 1.8° 电机在 1/16 微步下是 200 × 16 = 3200 微步每转,永远如此。分母是唯一依赖你机器的部分,而它是一个关于机械的问题:轴转一圈,轴走多远?
皮带
对齿形皮带来说,每转行程就是同步轮上的齿数乘以皮带节距。GT2 皮带节距 2 mm,而 20 齿同步轮几乎是每一台业余机器的默认选择:
travel = 20 teeth × 2 mm = 40 mm per revolution
steps/mm = (200 × 16) ÷ 40 = 80
就是这个——每一台 3D 打印机 X、Y 配置里那个 80 步/mm。它不是一个神奇常数;它是 20 齿 GT2 配十六微步,而你如果装一颗 16 齿同步轮,它就变成 100。
| 同步轮 | 每转行程 | 1/16 下的步/mm | 分辨率 |
|---|---|---|---|
| 16 齿 GT2 | 32 mm | 100 | 0.010 mm |
| 20 齿 GT2 | 40 mm | 80 | 0.0125 mm |
| 30 齿 GT2 | 60 mm | 53.33 | 0.019 mm |
| 20 齿 GT3(3 mm) | 60 mm | 53.33 | 0.019 mm |
注意 30 齿那一行除不整。53.333… 步/mm 完全合法——固件把它存成浮点并累积小数步——但这意味着没有任何一个位置会正好落在步进边界上,这也是大家都用那几种齿数的一个小理由。
丝杠
对丝杠来说,每转行程是导程——而导程不等于螺距。这是整个主题里最常见的错误。
- 螺距是相邻螺纹之间的距离。
- 导程是螺母转一圈走多远。
- 导程 = 螺距 × 头数。
单头丝杠的导程等于螺距。但“无处不在的 T8”丝杠是 2 mm 螺距、四条独立螺纹螺旋并排绕在一起,所以转一圈螺母前进四个螺纹:
lead = 2 mm pitch × 4 starts = 8 mm per revolution
steps/mm = (200 × 16) ÷ 8 = 400
而这就是你见过的另一个数。如果你用卡尺量 T8 的螺纹间距,量到 2 mm,算出 1600 步/mm,于是每一次移动都短了四倍。数一数丝杠端部的螺纹头数——你能看见那四条独立螺旋——或者干脆对着尺子转一整圈。
| 丝杠 | 螺距 | 头数 | 导程 | 1/16 下的步/mm |
|---|---|---|---|---|
| T8,四头(“T8x8”) | 2 mm | 4 | 8 mm | 400 |
| T8,双头(“T8x4”) | 2 mm | 2 | 4 mm | 800 |
| T8,单头(“T8x2”) | 2 mm | 1 | 2 mm | 1600 |
| M5 螺纹杆 | 0.8 mm | 1 | 0.8 mm | 4000 |
| 滚珠丝杠 1605 | 5 mm | 1 | 5 mm | 640 |
两者之间怎么选
分辨率不是免费的。一根分辨率是皮带十倍的丝杠,相同距离也需要十倍的脉冲——所以在固定最高步进率下它就慢十倍。这就是取舍,而且是个硬的:
| GT2 皮带,20 齿 | T8 丝杠 | |
|---|---|---|
| 每转行程 | 40 mm | 8 mm |
| 1/16 下的分辨率 | 0.0125 mm | 0.0025 mm |
| 100 mm/s 所需步/s | 8 000 | 40 000 |
| 实用极速 | 300+ mm/s | 约 30 mm/s |
| 轴上出力 | 小——皮带会拉伸 | 大——5 倍机械增益 |
| 断电能否保持位置 | 否 | 通常能(自锁) |
| 背隙 | 张紧后很小 | 真实存在,就在螺母里 |
| 用在哪 | X、Y——快、轻 | Z——慢、重、掉不得 |
这正是 3D 打印机 X、Y 用皮带而 Z 用丝杠的原因。X、Y 动得快,几乎不承载东西。Z 动得慢,承载着平台或龙门梁的重量,而且断电时不能下垂——T8 的浅螺旋角让它自锁,所以它在负载下不会反向被驱。
那张表里的 40 000 步/s 也是一个真实的天花板,不是理论值。Arduino Uno 用位操作打步进脉冲大约在每秒 10 000 到 15 000 就到顶了,再快循环就跟不上,而这在 T8 配 1/16 微步下大约就是 30 mm/s。如果你需要丝杠轴动得更快,答案是更少的微步、更快的板子,或者硬件定时器——而不是更大的电机。
转矩,以及那张表没说的事
换机构换掉的不只是速度,还有电机看到的负载。丝杠大致按 2π × 半径 ÷ 导程 放大力,所以 T8 能把不算大的电机转矩变成相当可观的轴向力——这正是 Z 轴上用一台小电机也能抬起沉重平台的原因。
皮带正相反。20 齿 GT2 同步轮的节径是 12.7 mm,所以皮带张力等于电机转矩除以 6.4 mm。一台输出 0.3 N·m 的电机在皮带上大约给出 47 N,而你拿到的就这些。如果你的 X 轴一撞到东西就丢步,这套算术就是原因。
折算惯量同样会变,而且方向一致:机构越细,滑车质量对电机的影响越小,这也是丝杠轴能容忍皮带轴受不了的激进加速度的原因之一。你可以在步进模拟器里直接看到这个效应——其他一切保持不变,只把机构从皮带换成丝杠,然后观察失步角发生了什么。
标定它,别信它
算出来的数是起点,不是答案。皮带会拉伸,同步轮有制造公差,丝杠是带着乐观描述卖的。量:
- 在固定参考物上给滑车做标记。一条胶带加一道锋利的铅笔线。
- 下发一次长距离移动——100 mm,不是 10 mm。误差是个百分比,所以移动越长量得越准。
- 用卡尺或钢尺量实际发生了什么。
- 用一个比值修正:
new steps/mm = old steps/mm × (commanded ÷ measured)
指令 100 mm,量到 98.4 mm,当前是 80:80 × 100 ÷ 98.4 = 81.3 步/mm。
然后重复测量确认。修正一次却不收敛,说明这个误差不是标度误差——而这个区别本身就是诊断:
| 测量模式 | 原因 |
|---|---|
| 每个距离都恒定偏百分比 | 步/mm 错了——用上面的计算修 |
| 与距离无关地恒定偏一个量 | 背隙或同步轮上的紧定螺钉松了 |
| 每次偏的量都不一样 | 丢步——电流、速度或加速度 |
| 一个方向对、另一个方向短 | 背隙,而且你在两个方向上都量了 |
| 正好差 2 倍、4 倍或 16 倍 | 微步跳线与固件设置不一致 |
| 丝杠轴正好短 4 倍 | 该用导程的地方你用了螺距 |
最后两行能抓住大部分第一次的制作,而两者都是算术问题,不是机械问题。
旋转轴:每度步数
不是每根轴都是线性的。转台、挤出机、相机滑轨的横摇轴和机器人关节,问的是同一个问题、只是分母不同——而对旋转轴来说,分母通常是一个减速比而不是一种机构:
steps/degree = (full steps × microstepping × gear ratio) ÷ 360
一台 1.8° 电机在 1/16 微步配 5:1 减速下给出 (200 × 16 × 5) ÷ 360 = 每度 44.4 步,也就是 0.0225° 的分辨率。值得注意:这和皮带是同一套算术,只不过把每转毫米换成了 360 度。
3D 打印机的挤出机是那个异类,因为它虽然是旋转驱动,却按每毫米耗材的步数标称。分母是那个滚花齿轮的有效周长,而不是它的标称直径——齿咬进耗材,所以真实的抓持半径比零件上印的那个小。这就是为什么没人算 E 步数、所有人都去量它:
- 在挤出机入口上方 120 mm 的耗材上做标记。
- 精确挤出 100 mm。
- 从入口到标记再量一次。如果读到 27 mm,那你挤了 93 mm,不是 100。
新值 = 旧值 × 100 ÷ 93。在 93 步/mm 的基础上就是 100 步/mm。
起点取 120 mm 是有意为之:它留足了耗材,使得即使挤出机严重过挤,那个标记也永远到不了入口。
非整数的每毫米步数
一旦标定完,这个数就不再是整数——80 变成 81.3,而一次 10 mm 的移动变成 813.0 步。固件能正确处理这件事,但手写的代码通常不能,因为那个显而易见的实现每次移动都把小数扔掉:
// Wrong: truncates on every call. Two hundred 0.1 mm moves land 1.4 mm short.
long stepsFor(float mm) { return (long)(mm * stepsPerMm); }
在 81.3 步/mm 下,一次 0.1 mm 的移动是 8.13 步,截断成 8。那 0.13 被扔掉了,而且在下一次移动时又被扔掉,再下一次也是。几百段这样的短移动之后——而曲线或填充图案恰恰就是由几百段短移动组成的——误差就累积成看得见的量。
修法是保留余数而不是保留位置:
// Right: carry the fraction forward, so the error never accumulates past one step.
float carry = 0;
long stepsFor(float mm) {
float exact = mm * stepsPerMm + carry;
long whole = lround(exact);
carry = exact - whole; // always within half a step
return whole;
}
现在任何时刻的最坏误差是半步——在这根轴上是 0.006 mm——而且它永不长大。这正是 Bresenham 直线光栅化用的同一个技巧,也是固件用步数而不是毫米跟踪位置的同一个原因:整数步数漂不了,而浮点的毫米位置会漂。
在固件里
Marlin 和 GRBL 都把这个数存成可设参数,所以你很少需要重新编译:
; Marlin — X, Y, Z, E
M92 X80 Y80 Z400 E93
M500 ; save to EEPROM
; GRBL
$100=80 ; X steps/mm
$101=80 ; Y
$102=400 ; Z
把你设的值写下来。这个问题最让人抓狂的版本,是一台曾经被正确标定过、重新刷了固件、然后悄悄退回固件默认值的机器。
下一步
上面这个数告诉机器它走了多远。它对自己是从哪里出发的只字不提——而一台开环机器在上电时没法知道这一点。那就是对着限位归零要做的事。
探索关联图谱
本教程所属的搭建
包含本教程的项目和学习路线。
延伸阅读