- Authors

- Name
- Youngju Kim
- @fjvbn20031
- 引言 —— 六个舵机搭出来的手臂,在自重下垮掉了
- 连杆、关节、末端执行器 —— 三个词的精确含义
- 自由度到底数的是什么,为什么以 6 为基准
- 转动关节与移动关节
- 真正驱动关节的东西 —— 舵机、步进电机、BLDC
- 减速器 —— 传动比对扭矩和背隙做了什么
- 用真实数字算出静态扭矩 —— 为什么肩部比腕部大
- 结语 —— 手臂的形状是扭矩计算的结果
引言 —— 六个舵机搭出来的手臂,在自重下垮掉了
决定要做一条机械臂,于是去买零件。搜索结果里出现频率最高的一套组合是:六个 MG996R 舵机,亚克力或 3D 打印支架,5V 电源。
组装起来,通电。舵机们各自找到自己的位置,动了起来。
命令手臂水平伸出。肩部瑟瑟发抖地慢慢往下垂。舵机一直在响,手臂却抬不起来。命令它去抓点什么,直接整条垮掉。
不是代码问题,也不是电源问题。肩关节所需的扭矩,是那个舵机能输出数值的 1.66 倍。
这个数字后面会亲自算出来。眼下重要的是:这个计算本可以在买零件之前就在纸上算完。只要定下臂长和想举起的物体重量,每个关节所需的扭矩就能算出来,再拿这个值去和数据手册比对就行。
这篇文章要讲的,就是这个计算需要的东西:机械臂由什么构成,自由度到底数的是什么,驱动关节的三种方法各自擅长什么、不擅长什么,减速器给了什么、又拿走了什么。最后,把那个扭矩计算从头到尾走一遍。
连杆、关节、末端执行器 —— 三个词的精确含义
先把术语钉准。这三个词的定义,是后面所有计算的地基。
连杆是不发生形变的刚性构件。在机械臂里,它是连接关节与关节之间的结构件。对应到人的手臂,就是上臂骨和前臂骨。运动学之所以把连杆当成刚体来假设,是为了便于计算,而实物会挠曲的那部分,就变成了误差。
关节是连接两根连杆、同时允许它们之间相对运动的元件。它允许哪种运动,就决定了关节的类型。
末端执行器是装在手臂最末端、真正干活的装置:夹爪、吸盘、焊枪、相机。运动学计算里说的「末端位置」,指的是在末端执行器上定义好的一个基准点,这个点叫做工具中心点。
再加上基座,结构就完整了:一条从基座出发,连杆和关节交替相连,终止于末端执行器的链条。这种不分叉、始终是一条链的结构叫开链,绝大多数工业机械臂都是这种形态。
也存在闭链结构,比如并联机器人(delta robot)那样多个分支在末端重新汇合的结构,在刚性和速度上有优势,代价是工作空间窄、运动学复杂得多。这篇文章只讨论开链。
有一个惯例值得了解:给连杆和关节编号时,从基座开始向外数。 基座是连杆 0,第一个关节是关节 1,接下来是连杆 1。这样一来,关节 i 连接的就是连杆 i-1 和连杆 i。正运动学那篇里变换矩阵的下标,遵循的正是这个规则。
自由度到底数的是什么,为什么以 6 为基准
自由度是能够独立指定的运动变量个数。在机械臂里,这通常就等于关节的数量。
为什么以 6 为基准,从目标那一端去数就很清楚了。要在三维空间里完全确定一个刚体的状态,需要多少个数?
位置需要三个:x、y、z。
姿态也需要三个,因为即便把物体固定在原地不动,依然可以绕三个轴独立旋转。
加起来是六个。所以要把末端执行器放到任意位置、任意朝向,至少需要六个关节。
以这个数字为基准,机械臂分成三类。
| 自由度 | 名称 | 能做到什么 | 例子 |
|---|---|---|---|
| 少于6 | 欠驱动 | 只能指定位置或姿态的一部分 | SCARA(4)、并联机器人(3)、业余五轴臂 |
| 6 | 全驱动 | 工作空间内任意位置和姿态 | 大多数工业机器人 |
| 7以上 | 冗余驱动 | 同一个末端姿态可以由多种臂形实现 | 许多协作机器人、人的手臂 |
欠驱动并不代表不好。SCARA 是 4 自由度,但对于往电路板上垂直插元件这种任务来说,只要零件能垂直落下就够了,剩下的自由度根本用不上。少了自由度,换来的是快得多、也强壮和便宜得多。只拥有恰好需要的自由度,这本身就是一种设计,6 是一个基准点,不是上限。
冗余驱动带来的,是在保持末端不动的情况下改变手臂形状的能力。把手按在桌上一点不动、上下摆动肘部,立刻就能体会到这一点。这份余量可以用来避障或者规避关节极限,对应的数学工具就是逆运动学那篇里的零空间。
业余爱好者手臂里常见的 5 自由度处在一个尴尬的位置。手腕缺了一个旋转轴,导致在需要以特定朝向抓取物体的任务中,会突然冒出够不到的姿态。位置能对上,姿态却对不上——只要写程序,迟早会撞上这种情况。
转动关节与移动关节
实际机械臂里用到的关节,基本上只有两种。
转动关节绕一根轴旋转,关节变量是角度。人的肘和肩就是这种,工业机械臂里的关节几乎全是转动关节。
移动关节沿一根轴滑动,关节变量是长度。3D 打印机的每根轴、龙门机器人、SCARA 的 z 轴,都是这种。
两者的差异体现在性能曲线的形状上。
| 标准 | 转动关节 | 移动关节 |
|---|---|---|
| 关节变量 | 角度 | 距离 |
| 工作空间对占地面积 | 宽 | 窄 |
| 刚性 | 连杆越长下降越剧烈 | 大体均匀 |
| 精度 | 越靠近连杆末端误差被放大越多 | 与位置无关,均匀 |
| 负载引起的扭矩变化 | 随姿态大幅变化 | 大体恒定 |
| 运动学 | 三角函数,解有多个 | 大体线性,解唯一 |
| 密封与洁净 | 容易 | 导轨暴露,较难 |
第四行是转动关节在机械臂上带来的独有问题。关节的角度误差,会按连杆长度成比例地放大成末端位置误差。肩关节偏差 0.1 度,在 0.35 米外的末端就是:
0.1度 = 0.001745 rad
0.001745 × 0.35 m = 0.000611 m = 0.61 mm
0.61 毫米。而且这个误差,关节越靠近肩部,放大得越厉害。基座一侧关节的精度,支配着末端的精度。 后面讲减速器时,肩部一侧要用更贵的减速器,原因也在这里。
在国际标准 URDF 里,运动学用关节类型字符串来表达,可用的取值精确地只有六个:revolute(有范围限制的转动)、continuous(无限旋转)、prismatic(移动)、fixed(固定)、floating(6自由度)、planar(平面3自由度)。前三个是实际驱动的关节,fixed 用在只是想在计算上多放一个参考系的时候。
真正驱动关节的东西 —— 舵机、步进电机、BLDC
现在进入正题。知道关节要转动了,但到底是什么在转它?
RC 舵机 —— 下达角度指令,它自己就会到位
在业余爱好者的机械臂里用得最多。内部集成了直流电机、减速齿轮、位置传感器和控制电路。外部只需要给出目标角度,走到那个角度的过程由舵机内部的闭环自己搞定。
指令是靠 PWM 脉冲的宽度来传递的。标准惯例是大约每 20 毫秒发一个脉冲,宽度为 1 毫秒对应一端,1.5 毫秒对应中位,2 毫秒对应另一端。更新频率的容忍度很宽,大致在 40Hz 到 200Hz 之间都能工作。
这里有两点需要提醒。
第一,脉宽范围因厂商和型号而异。 以广泛使用的 SG90 为例,分销商的资料写的是 500 到 2400 微秒,但制造商 TowerPro 自己并没有公布脉宽规格。如果只用 1000 到 2000 微秒,实际上只用到了大约一半的可动范围。真实范围需要一点点转动舵机、亲自摸索出来。
第二,普通 PWM 输出的分辨率完全不够。 Arduino 的 analogWrite() 是 8 位的,把 20 毫秒周期分成 256 份,
20000 μs / 256 = 78.125 μs
一档是 78 微秒。如果 1000 到 2000 微秒对应 180 度,那 1 度就是 5.56 微秒,于是
78.125 μs / 5.56 μs = 14.06度
一档是 14 度。也就是说角度只能以 14 度为单位来指定。这就是为什么舵机要用专用库来驱动,而不是 analogWrite()。Arduino 的 Servo 库直接占用一个定时器,生成微秒级精度的脉宽。
#include <Servo.h>
// 舵机电源务必单独供电,只把GND和板子接在一起。
// 原因会在下面的"电源"一节里用计算来确认。
Servo shoulder;
const int SERVO_PIN = 9;
const int PULSE_MIN = 600; // 这两个值因型号而异。
const int PULSE_MAX = 2400; // 请一点点收窄区间,找出实际极限。
void setup() {
// 给attach同时提供最小/最大脉宽,write(角度)就会被映射到这个范围内。
shoulder.attach(SERVO_PIN, PULSE_MIN, PULSE_MAX);
shoulder.writeMicroseconds(1500); // 从中位开始
delay(500);
}
void loop() {
// writeMicroseconds(微秒)比write(角度)分辨率更高。
// 把每步设为20us,换算成角度大约是2度,已经足够平滑。
for (int us = 1000; us <= 2000; us += 20) {
shoulder.writeMicroseconds(us);
delay(20); // 与更新周期对齐
}
for (int us = 2000; us >= 1000; us -= 20) {
shoulder.writeMicroseconds(us);
delay(20);
}
}
RC 舵机的局限很明确:读不到当前角度,发不出扭矩指令,也不知道自己正在用多大的力。发出指令、然后相信它已经到位,就是全部内容。要是负载太重根本没到位,也完全没办法知道。
解决这个局限的是智能舵机。ROBOTIS 的 Dynamixel 系列是典型代表,通过串行总线把多个舵机串联起来,可以读取每个舵机当前的位置、速度、负载和温度。按厂商资料,AX-12A 在 12V 下能输出 1.5 N·m 的堵转扭矩,位置分辨率 0.29 度(300 度范围分成 1024 份)。更高端的 X 系列分辨率提升到每转 4096,XM430-W350-R 在 11.1V 下能输出 3.8 N·m。这个型号还有基于电流的位置控制模式,可以下达「不要推得比这个力更大」这样的指令。
步进电机 —— 靠数步数前进,但不知道有没有真的到位
步进电机按顺序给线圈通电,把转子一步一步拽着走。就算没有位置传感器,数一数步数,也就等于知道了角度。
最常见的 NEMA 17 规格步距角是 1.8 度,一圈 200 步。直接用这个值,一个关节的分辨率就是 1.8 度,换算成臂长 0.35 米时的末端误差,
1.8度 = 0.031416 rad
0.031416 × 0.35 = 0.011 m = 11.0 mm
11 毫米。用在机械臂上远远不够。所以要用细分驱动(microstepping):不让线圈电流呈阶梯状变化,而是按正弦波近似输出,把每一步再切分开的技术。
| 驱动器 | 最大细分 | 每转步数 | 每步角度 | 0.35m处的末端移动量 |
|---|---|---|---|---|
| 无(整步) | 1/1 | 200 | 1.8度 | 11.00 mm |
| A4988 | 1/16 | 3200 | 0.1125度 | 0.687 mm |
| DRV8825 | 1/32 | 6400 | 0.0563度 | 0.344 mm |
| TMC2209 | 1/256 | 51200 | 0.0070度 | 0.043 mm |
TMC2209 的 1/256 是靠一个叫 MicroPlyer 的插值功能实现的,能用引脚直接选择的数值是 8、16、32、64。
这里有件必须知道的事:细分驱动提高的是分辨率,不是精度。 步分得越细,每个微步产生的保持扭矩就越小,一旦静摩擦或负载扭矩比这个值更大,转子实际上根本不会动。指令上看起来是每次走 1/256 步,但物理上却是每隔几步才猛地跳一下。
而且步进电机还有一个根本性的危险:失步。
步进电机是开环的。它只是假设转子在跟随定子的磁场,从不做确认。这种同步会在三种条件下被打破。
一,负载扭矩超过了该转速下电机能输出的扭矩。步进电机的扭矩会随转速急剧下降,所以不能只看静止时的保持扭矩来选型。厂商资料建议在扭矩-转速曲线上留出 30% 的余量。
二,加速太猛。转子和负载的惯量瞬间要求的扭矩超标了。
三,低频共振。大致在每分钟 50 到 150 转的区间,也就是每秒 167 到 500 整步对应的范围内,转子会像扭转摆一样振鸣,有效扭矩会被抽掉。如果在别的转速下都正常,却单单在某个转速区间丢步,原因就是这个。
失步之所以可怕,是因为它很安静。 丢了十步,驱动器什么都不会说,控制器依然相信自己知道的那个角度。这份误差会一直留着,直到重新回零才会消失。在机械臂上,这意味着关节角度和实际情况不符,也就意味着正运动学算出来的末端位置全都是错的。
顺带一提,常用的 17HS4401S 厂商规格是保持扭矩 43 N·cm,相电流 1.7A,也就是 0.43 N·m,连后面要算的肩关节所需扭矩的四分之一都不到。不经减速就直接联接,是行不通的。
BLDC 与编码器 —— 真正的闭环
如果想要性能的天花板,就得给无刷电机配上编码器,自己直接控制。协作机器人和最近的高性能业余机械臂,走的就是这条路。
BLDC 没有电刷,所以没有磨损,同样体积下扭矩密度比有刷电机高,散热也更有利。代价是必须知道转子的位置,才能决定什么时候给线圈通电,所以位置传感器是必需的。
位置传感器广泛使用磁性旋转编码器。轴端装一块小磁铁,芯片读取磁场的方向。
| 元件 | 分辨率 | 每转分割数 | 角度 | 换算到0.35m末端 |
|---|---|---|---|---|
| AS5600 | 12位 | 4096 | 0.0879度 | 0.537 mm |
| AS5047P | 14位 | 16384 | 0.0220度 | 0.134 mm |
| Dynamixel AX-12A | 1024分割/300度 | 1024 | 0.2930度 | 1.790 mm |
| Dynamixel X系列 | 4096脉冲/转 | 4096 | 0.0879度 | 0.537 mm |
AS5047P 支持每分钟 28000 转,在 ABI 增量输出的二进制模式下每转能给出 4096 步。
想把 BLDC 驱动得好,正确方法是磁场定向控制(FOC)。不直接处理三相电流,而是经过两次坐标变换:克拉克变换把三相映射到静止的两轴坐标系,帕克变换再把它映射到跟着转子一起转动的坐标系。在这个坐标系里,电流变成了直流量,普通的 PI 控制器就能处理,两个分量的作用也彻底分开了。d 轴电流产生磁通,q 轴电流产生扭矩。 所以才能直接下达扭矩指令。
在业余领域,SimpleFOC 库替你干了这件事。截至 2026 年 2 月发布的 v2.4.0,它支持 AVR、STM32、ESP32、Teensy、RP2040 等一大批板子,文档里提到,如果要考虑电流检测,推荐用 STM32 系列。
三种方式总结如下:
| 标准 | RC舵机 | 步进电机 | BLDC+编码器 |
|---|---|---|---|
| 控制回路 | 内置闭环 | 开环 | 自行搭建的闭环 |
| 下达的指令 | 角度 | 步数 | 电流、速度、位置三选一 |
| 读取当前角度 | 不行(智能舵机可以) | 不行 | 可以 |
| 扭矩控制 | 不行 | 不行 | 可以 |
| 静默失败 | 不知道有没有到位 | 不知道丢没丢步 | 误差立刻暴露 |
| 接线难度 | 3线 | 4线+驱动器 | 三相+编码器+驱动器 |
| 上手难度 | 最简单 | 中等 | 最难 |
| 减速器 | 大多内置 | 另配 | 另配 |
减速器 —— 传动比对扭矩和背隙做了什么
选好电机还没结束。机械臂的关节大多是经过减速器驱动的。原因有三个,第三个最重要,却也最少被提起。
把传动比记为 N。
第一,扭矩会放大 N 倍。 更精确地说,是再乘以机械效率 η。
输出扭矩 = 电机扭矩 × N × η
第二,速度会降到 N 分之一。 这是代价。电机每分钟转 3000 圈,经过 100:1 的减速器之后就变成每分钟 30 圈。
第三,负载惯量看起来会降到 N 的平方分之一。 这就是反射惯量,也是减速器真正让控制变简单的原因。20:1 的减速比下,电机感受到的手臂惯量会变成四百分之一。惯量看起来变小,同样的扭矩就能加速得更快;更重要的是,负载的变化传到电机这边会被削弱很多,控制器也就能更稳定地工作。
用数字来看看。给一个输出 0.09 N·m 的小电机配上几种不同的减速比:
| 传动比 | 假设效率 | 输出扭矩 | 速度 | 反射惯量 |
|---|---|---|---|---|
| 5:1 | 0.97 | 0.437 N·m | 1/5 | 1/25 |
| 20:1 | 0.94 | 1.692 N·m | 1/20 | 1/400 |
| 50:1 | 0.90 | 4.050 N·m | 1/50 | 1/2500 |
| 100:1 | 0.90 | 8.100 N·m | 1/100 | 1/10000 |
效率数值只是假设,实际值会因减速器类型和等级不同而有很大差异。精密行星减速器厂商公布的数据,单级 97% 以上、两级 94% 以上,但业余用的廉价减速箱要比这低得多。
背隙 —— 减速器拿走的东西
减速器给出扭矩不是白给的。最大的代价就是背隙。
齿轮要啮合,齿与齿之间必须留有间隙。没有间隙的话,热胀冷缩或者加工误差就会把齿卡死。可正是因为这个间隙,输入一旦反向,输出要先跨过这段间隙,才会跟着动起来。这个角度就是背隙。
在机器人领域,背隙是按角分来管理的。1 角分是 1/60 度。换算到 0.35 米长的手臂:
| 背隙 | 弧度 | 末端处的间隙 |
|---|---|---|
| 10角分 | 2909 μrad | 1.018 mm |
| 5角分 | 1454 μrad | 0.509 mm |
| 3角分 | 873 μrad | 0.305 mm |
| 1角分 | 291 μrad | 0.102 mm |
| 36角秒 | 175 μrad | 0.061 mm |
| 2角秒 | 9.7 μrad | 0.003 mm |
精密行星减速器厂商公布的数值,按等级不同,单级在 1、3、5 角分,两级在 3、5、7 角分。就算是好等级,末端处依然会留下大约 0.1 毫米左右的间隙。
背隙为什么会造成这么大的问题,在控制回路那篇里会再次讲到。简单说:在间隙区间里,电机在转,关节却不动,控制器看到的增益就变成了零;齿一旦重新啮合上,又会突然恢复正常。一个增益在不同区间不一样的系统,很难用单一一组增益去稳定,还会产生极限环——手臂在目标附近来回晃个不停。
谐波减速器为什么用在机器人上
打开工业机械臂的关节,尤其是手腕那一侧,里面装的通常是波动齿轮装置,更广为人知的名字是它的商标——谐波减速器(Harmonic Drive)。
结构很特别,由三个部件组成。
波发生器 椭圆形毂+薄壁轴承。输入轴。
柔轮 薄壁杯状。径向可挠曲,抗扭却很强。
外表面有齿。输出轴。
刚轮 厚圆环。内侧有齿,比柔轮多两个齿。
波发生器把柔轮撑成椭圆形,
只有椭圆长轴附近的齿才会啮合。
输入转一整圈,柔轮就会往后退两个齿的量。
由此产生两个结果。
单级就能得到很大的减速比。 因为齿数差只有 2,减速比可以做得非常大。按厂商资料,元件套件提供 30、50、80、100、120、160:1 等规格,技术文档中提到单级减速比可以从 50:1 到 320:1。用行星减速器要达到 100:1,需要两级甚至三级,而每多一级,背隙就会累积一次。
总是有多个齿同时啮合。 因为椭圆长轴两侧都有大片区域同时啮合,所以厂商把这种啮合描述为零背隙。
这里有一点必须精确地讲清楚。「零背隙」说的是这种啮合本身,不代表输入轴和输出轴之间整体的间隙就是零。 厂商自己也说明,杯型齿轮在啮合处的背隙确实是零,但来自输入联轴器的轴间背隙有 2 到 36 角秒。上表里,36 角秒换算到 0.35 米手臂的末端是 0.061 毫米。而且除此之外,还存在因扭转刚度导致的弹性变形,实际上这一部分往往才是更大的误差来源。
效率方面,厂商给出的数据是最高能到 90%,比精密行星减速器单级 97% 要低。谐波减速器是用效率去换精度和减速比的一种选择。
第三个选项是摆线减速器,用在大型机器人的肩部或腰部这类需要大扭矩的位置。这类元件的资料特别有用,因为它会把误差拆成三部分分别公布:机械背隙 0.1 到 0.3 角分,空程(lost motion)0.3 到 0.6 角分,迟滞损失 0.2 到最多 1 角分。由此可以看出,背隙、空程和迟滞是三个真正不同的量——这正是「零背隙」这个说法能够诚实存在的原因,也正是不能只凭这一句话就去选型的原因。
用真实数字算出静态扭矩 —— 为什么肩部比腕部大
现在来算引言里那个数字。
把手臂设定成这样。
| 部位 | 长度 | 质量 |
|---|---|---|
| 上臂(肩到肘) | 0.20 m | 0.15 kg |
| 前臂(肘到腕) | 0.15 m | 0.10 kg |
| 夹爪(腕部末端) | 距腕轴0.05 m | 0.15 kg |
| 负载(抓取的物体) | 与夹爪同一位置 | 0.25 kg |
要计算的姿态是手臂完全水平伸展。这是重力产生的扭矩最大的最坏情况,而选型就应该按最坏情况来做。
扭矩等于力乘以力臂长度。把均匀杆的重量看作作用在它的中点上。
先算肘部。只统计肘部以外的部分。
前臂: 0.10 kg × 9.81 × 0.075 m = 0.073575 N·m
夹爪: 0.15 kg × 9.81 × 0.15 m = 0.220725 N·m
负载: 0.25 kg × 9.81 × 0.15 m = 0.367875 N·m
------------------------------------------------
合计 0.662175 N·m
再算肩部。把所有距离都重新从肩部量起。
上臂: 0.15 kg × 9.81 × 0.10 m = 0.147150 N·m
前臂: 0.10 kg × 9.81 × 0.275 m = 0.269775 N·m
夹爪: 0.15 kg × 9.81 × 0.35 m = 0.515025 N·m
负载: 0.25 kg × 9.81 × 0.35 m = 0.858375 N·m
------------------------------------------------
合计 1.790325 N·m
腕部只看夹爪加物体的重心到腕轴的距离。
(0.15 + 0.25) kg × 9.81 × 0.05 m = 0.196200 N·m
把三个值摆在一起,
肩部 1.790325 N·m
肘部 0.662175 N·m (肩部的1/2.704)
腕部 0.196200 N·m (肩部的1/9.125)
肩部要求的扭矩是腕部的 9.1 倍。
原因是两件事叠加在一起。一,肩部要承担它外侧所有部件的重量。二,那些重量距离肩部更远。距离和质量同时变大,乘积自然急剧变大。
所以机械臂才会越往下越粗。工业机器人的轮廓根部粗、末端细,不是设计上的偏好,而是这个计算的结果。
import numpy as np
G = 9.81
KGCM_PER_NM = 1.0 / 0.0980665 # 1 kg·cm = 0.0980665 N·m (定义值,所以精确)
# 从肩部到腕部方向: (连杆长度 m, 连杆质量 kg)
LINKS = [(0.20, 0.15), # 上臂
(0.15, 0.10)] # 前臂
GRIPPER_MASS = 0.15 # 装在腕部末端的夹爪
PAYLOAD_MASS = 0.25 # 抓取的物体
WRIST_OFFSET = 0.05 # 从腕轴到夹爪+物体重心的距离
def static_torque(joint_index):
"""手臂完全水平伸展的最坏姿态下,某个关节承受的重力扭矩。
只统计该关节外侧的质量。"""
outer = LINKS[joint_index:]
reach, total = 0.0, 0.0
for length, mass in outer:
total += mass * G * (reach + length / 2) # 均匀杆的重心在中点
reach += length
total += (GRIPPER_MASS + PAYLOAD_MASS) * G * reach
return total
rows = [("肩部", static_torque(0)),
("肘部", static_torque(1)),
("腕部", (GRIPPER_MASS + PAYLOAD_MASS) * G * WRIST_OFFSET)]
print("手臂完全水平伸展的最坏姿态下的静态扭矩")
print(f"{'关节':<6}{'N·m':>10}{'kg·cm':>10}{'2倍安全系数(kg·cm)':>22}")
for name, t in rows:
print(f"{name:<6}{t:10.4f}{t * KGCM_PER_NM:10.3f}{t * 2 * KGCM_PER_NM:22.3f}")
print(f"\n肩部 / 肘部 = {rows[0][1] / rows[1][1]:.3f}倍")
print(f"肩部 / 腕部 = {rows[0][1] / rows[2][1]:.3f}倍")
MG996R_6V = 11.0 * 0.0980665 # 厂商公布的堵转扭矩 11 kg·cm @ 6.0V
print(f"\nMG996R的6V堵转扭矩 11 kg·cm = {MG996R_6V:.4f} N·m")
print(f"肩部所需的扭矩是它的{rows[0][1] / MG996R_6V:.3f}倍(还没算上安全系数)")
运行结果如下。
手臂完全水平伸展的最坏姿态下的静态扭矩
关节 N·m kg·cm 2倍安全系数(kg·cm)
肩部 1.7903 18.256 36.512
肘部 0.6622 6.752 13.505
腕部 0.1962 2.001 4.001
肩部 / 肘部 = 2.704倍
肩部 / 腕部 = 9.125倍
MG996R的6V堵转扭矩 11 kg·cm = 1.0787 N·m
肩部所需的扭矩是它的1.660倍(还没算上安全系数)
用这个数字来选型
算完了,拿去和数据手册比对。
| 元件 | 厂商公布扭矩 | 能否用于肩部(1.790 N·m) |
|---|---|---|
| SG90 | 1.8 kg·cm @ 4.8V = 0.177 N·m | 不行,只有需求的十分之一 |
| MG996R | 11 kg·cm @ 6.0V = 1.079 N·m | 不行,只有需求的60% |
| Dynamixel AX-12A | 1.5 N·m @ 12V | 刚好不够,没有安全余量 |
| Dynamixel XL430-W250-T | 1.4 N·m @ 11.1V | 不行 |
| Dynamixel XM430-W350-R | 3.8 N·m @ 11.1V | 可以,安全系数2.1倍 |
| NEMA 17(17HS4401S)直连 | 0.43 N·m保持扭矩 | 不行,只有需求的四分之一 |
引言里那条手臂为什么会垮,答案就在这里。MG996R 的堵转扭矩,只有肩部所需数值的 60%。
而且这张表里还藏着一个陷阱。堵转扭矩是轴完全停止时能短暂输出的最大值。 那种状态下没有反电动势,电流会冲到最大,电机要是一直这样,线圈会被烧毁。惯例是把连续可用扭矩估计为堵转扭矩的 20% 到 30%,所以 2 倍安全系数只是最低要求,3 倍安全系数是更常见的建议值。
套用 2 倍安全系数,肩部就需要 36.5 kg·cm,也就是 3.58 N·m。上表里能满足这个数值的只有 XM430-W350-R,而且余量也只有 1.06 倍。
另一个方案是加减速器。如果给一个 0.09 N·m 的小型 BLDC 配减速器,所需的传动比是:
N = 3.58 N·m / (0.09 N·m × 0.94) = 42.3
用 50:1 的减速器就够了。这样输出扭矩变成 4.05 N·m,反射惯量降到 1/2500,控制也会更容易。代价是速度:电机每分钟 3000 转,到了关节这里就变成每分钟 60 转。对机械臂来说,关节每分钟 60 转已经足够快了。
还有一个方案是给手臂减重。上面的计算里,0.25kg 的负载占了肩部扭矩的 48%。把负载降到 0.1kg,肩部扭矩就会降到 1.28 N·m,连 AX-12A 都能有 1.2 倍的安全余量。当零件不够用的时候,把电机做大并不是唯一的答案。
电源必须单独计算
就算扭矩对上了,电源跟不上,手臂照样动不了。
六个舵机同时动作,电流会叠加起来。单个 MG996R 的堵转电流是安培量级,六个同时撞上负载,就是好几安培。这份电流要是从单片机板子的 5V 电源轨上取,一定会导致欠压复位。
这个问题的物理原理和对策,在驱动电机与感性负载那篇里已经详细讲过。简单总结就是三条:舵机电源从独立供电装置获取,GND 必须和板子在一点上接在一起,电源输入处要加足够容量的电容。
逻辑电压不匹配的情况也很常见,比如用树莓派的 3.3V 信号驱动 5V 舵机,或者把 12V 步进驱动器的信号线接到 3.3V 板子上。哪个方向安全、哪个方向会烧芯片,已经整理在逻辑电平与电平转换那篇里。接限位开关或回零传感器时需要的上拉电阻和消抖,则在GPIO 上拉与消抖那篇里。
结语 —— 手臂的形状是扭矩计算的结果
这篇文章讲的所有内容,最终都会汇聚到一个计算上:这个关节要承受多少牛顿米。
这个值决定了手臂的形状。肩部要求的扭矩是腕部的九倍,所以肩部一侧的电机更大;电机大了,自身的重量又会进一步增加扭矩需求,于是又有了把连杆做得更短更轻的理由。工业机器人的轮廓之所以都长得很像,是因为它们做的是同一套计算。
这个值也决定了减速器的选择。如果单靠电机达不到所需扭矩,就得靠传动比来凑;买了传动比,就等于同时买了背隙;想减少背隙,就得接受谐波减速器带来的效率损失。没有一样是免费的。
这个值同样决定了驱动方式。舵机简单,但不知道自己的实际状态;步进电机便宜又精确,却会悄无声息地丢步;BLDC 什么都能做到,但控制回路得自己写。
买零件之前,能在纸上完全算完的计算,就是这整篇文章。 定下连杆长度,定下想举起的重量,乘一乘、加一加,每个关节所需的扭矩就出来了。在这个数字上再乘以 2 倍或 3 倍,就是要去数据手册里找的那个数字。不做这一步就去买舵机,得到的就是引言里那条垮掉的手臂。
下一步,是根据这些关节构成的姿态,计算末端到底在哪里。接下来是正运动学那篇。