Arduino Uno 的 5 V 脚撑得住的,大约是一只空载的 SG90 —— 不是四只。四只微型舵机在手臂动起来的时候要吃 0.4–1 A,全部一起弹到位的瞬间可以到 2.8 A,而 USB 那边能给的大约只有 450 mA。给舵机自己一组 4×AA 电池盒,把地接在一起,再用增量的方式驱动每一个关节 —— 手放开,手臂才停得住。
一组属于自己的电源,加上放手也停得住的控制方式:这两件事是四关节手臂逼着你做,而两轴云台永远不会逼你做的。剩下的就是纸皮和耐心。这里全程不超过 6 V,所以没有触电的风险 —— 会受伤的是堵转的舵机(会烧)和尼龙齿轮组(会崩牙)。
Arduino Uno 的 5V 供电,实际撑得住几只 SG90 舵机?
Arduino Uno 可以指挥十二只舵机,却只供得起大约一只。发信号几乎不花成本:Servo 库占用一个 16 位定时器,把它分给最多十二只舵机,每 20 ms 给每只送一个 544–2400 µs 的脉冲。ATmega328P 只有一个 16 位定时器 Timer1 —— 这既是十二这个上限的由来,也是为什么只要挂上一只舵机,pin 9 和 pin 10 上的 analogWrite() 就失效了:定时器被库拿走了。这些都写在库的 Servo.h 里。
真正咬住你的预算是电流。一只 SG90 的电路板本身待机大约 10 mA,但它后面接着一颗有刷直流马达和一组尼龙齿轮,吃多少电,要看它干多重的活:
| 舵机在做什么 | 一只 SG90 | 四只加起来 |
|---|---|---|
| 通电,空手保持姿势 | ~10 mA | ~40 mA |
| 带着一支纸皮手臂在动 | 100–250 mA | 0.4–1 A |
| 堵转 —— 卡住、超载,或者上电瞬间弹到位 | 350–700 mA | 1.4–2.8 A |
堵转电流是一个范围,不是数据表上的一个数字:公开的 SG90 数据表给了扭力、速度和脉宽,却完全没给电流值,所以电源要按这个范围的上限来配。Uno 那边能拿出来对付它的,被两个元件卡住:
| Uno 的供电方式 | 5V 供电被什么限制 | 5V 实际给得出多少 |
|---|---|---|
| USB 2.0 端口 | USB 输入端 500 mA 的自恢复保险丝 | 约 500 mA,扣掉板子自己吃的,剩大约 450 mA |
| 电源座输入 9 V | SOT-223 封装线性稳压器的散热 | 约 270 mA |
| 电源座输入 12 V | 同一颗稳压器,压差更大 | 约 155 mA |
电源座那两个数字,是你可以自己算一遍的算术。Uno 的 5 V 来自一颗 SOT-223 封装的 1117 系列线性稳压器,而线性稳压器不会把多余的电压转换掉 —— 它是烧掉,烧掉 (Vin − 5) × 电流 瓦。一个封装在热保护动作之前散得掉 (TJ(max) − 环境温度) ÷ θJA 瓦:以 125 °C 的结温上限、SOT-223 的 88 °C/W 和 30 °C 的工作台环境温度来算,大约是 1.08 W。9 V 输入时压差 4 V,所以 1.08 W ÷ 4 V ≈ 270 mA;12 V 输入时压差 7 V,同样这一瓦只换得到 155 mA。输入电压越高,5 V 那边给得出的电流越少,不是越多。
最先绊倒人的是上电那一刻:attach() 和第一次 write() 会让每一只舵机同时猛地弹到被指定的角度,电流接近堵转值。那颗自恢复保险丝是 PTC 元件 —— 它是发热、电阻跟着爬升,所以供电是往下塌,而不是干脆断掉。塌到低于 ATmega328P 的欠压复位门槛,芯片就复位,setup() 再跑一遍,舵机再弹一次:手臂在复位循环里抽搐,看起来完全像是程序写错了。
材料清单 —— 四个关节、两支摇杆,和一组不是 Uno 的电源
选配 —— 手臂垂下来、想接市电,或者关节不够用的时候
金属齿轮的 MG90 舵机:手臂被自己的重量压得垂下来时,把底座和肩关节换成它。5V 3A 适配器配一条电源座转接线,是比电池更整齐的工作台方案。PCA9685 驱动板只有在你用完四个直接输出脚之后才需要。
怎样给四只舵机一组属于它们自己的电源?
4×AA 电池盒是最简单的正确答案,而且它的电压刚好落在该落的地方:四颗碱性电池标称 6.0 V,四颗镍氢 4.8 V,两者都在 SG90 额定的 4.8–6 V 窗口里,也都拿得出安培级的电流。刚拆封的碱性电池空载每颗接近 1.6 V,所以新电池盒量出来大约 6.4 V —— 这没关系,因为舵机一开始吃电,内阻就把它拉回窗口里;这也正是不要去拿更大电压电池组的理由,因为 7.2 V 的电池组没有可以往下塌的空间。
把电池盒的红线接到面包板的红色电源条,黑线接到蓝色那条 —— 多股软线插进面包板孔里会散开,所以先上锡,或者把它绕在一根公头杜邦针上。一只舵机都还没插进去之前,先量这两条电源条:SG90 上没有防反接二极管,所以正负接反一次,四只会一起报销,而且悄无声息。之后四条舵机红线全部进红色电源条,四条棕线全部进蓝色。
然后把地接在一起。这一步就是最常被跳过的那一步。舵机并不是把你的脉冲当成一个抽象的「脉冲」来读 —— 它读的是橙线上的电压相对于它自己那条棕线的值。如果电池的负极和 Uno 的地不是同一个电气节点,这两个参考点就会各自漂移,舵机看到的是一个它解不出来的信号:手臂发抖、自己爬动,或者干脆不动。从 Uno 的 GND 排针拉一条黑色杜邦线到蓝色电源条,就解决了。
绝对不要把电池盒接到 Uno 的 5V 脚。那只脚在稳压器之后,直接连到一颗 ATmega328P,而这颗芯片的规格是最高工作电压 5.5 V、绝对最大值 6.0 V。一盒新的碱性电池正好压在这个天花板上,而且 USB 还插着的话,你等于把它一路推回电脑的 USB 口里去。VIN 是另一种失败方式:线性稳压器需要大约一伏的压差余量,所以 6 V 进去撑不出 5 V 出来。Uno 就让它吃 USB。想用市电代替电池的话,5 V 3 A 适配器配一条电源座转接线接到电源条上,四只舵机同时堵转也够。
要让手臂脱离笔记本电脑独立跑,就从板子的电源座喂电:7–12 V 的电池组或者一颗 9 V PP3 方形电池在那里很舒服,因为 Uno 加两支摇杆加起来,离那 270 mA 还远得很。禁令是针对舵机那条电源,不是针对板子。
四个关节和两支摇杆要怎么接线?
一支最精简的 Arduino 机械手臂有四个关节:绕垂直轴转的底座、把大臂抬起来的肩关节、把小臂折起来的肘关节,还有一个夹爪。两个摇杆模块刚好给出四个模拟轴 —— 左边那支管底座和肩,右边那支管肘和夹爪。

每只 SG90 的引线末端是一个黑色的三针母座,所以要用公对公杜邦线去接 Uno 的母排针和面包板电源条。摇杆模块正好相反 —— 它是弯针的公头 —— 所以要用公对母杜邦线;我们的杜邦线选用教程把哪一头配哪一头讲得很清楚。
| 从 | 接到 | 备注 |
|---|---|---|
| 舵机橙线(信号)×4 | D9 底座、D10 肩、D11 肘、D3 夹爪 | 任何数字脚都行;不管接哪里,Servo 库都会拿走 9 和 10 的 PWM |
| 舵机红线 ×4 | 面包板红色电源条 | 来自电池 —— 绝不来自 Uno |
| 舵机棕线 ×4 | 面包板蓝色电源条 | |
| 电池 + / − | 红色电源条 / 蓝色电源条 | 电池盒上的开关就是总断电开关 |
| Uno GND | 面包板蓝色电源条 | 共地 —— 必须接 |
| Uno 5V | 面包板另一边的红色电源条 | 逻辑电源 —— 只给摇杆,绝不给舵机 |
| 两条蓝色电源条 | 用一条杜邦线接起来 | 电池、Uno 和摇杆同一个地 |
| 摇杆 1:+5V、GND、VRx、VRy | 逻辑红色电源条、蓝色电源条、A0、A1 | 底座和肩 |
| 摇杆 2:+5V、GND、VRx、VRy | 逻辑红色电源条、蓝色电源条、A2、A3 | 肘和夹爪 |
| 摇杆 2:SW | D2 | 归位按钮,用内部上拉 |
摇杆的 5 V 可以从 Uno 拿,而且它们是唯一可以这样拿的东西:每一块 HW-504 模块就是两个 10 kΩ 电位器跨在电源上,一个轴大约半毫安。VRx 和 VRy 是那两个模拟轴;SW 是一个对地短路的按压开关,不是第三个轴,所以它需要一个上拉。
这条规则的方向,和规则本身一样重要。摇杆就是一个电位器,所以 VRx 输出的是喂给它那个电压的一个比例,而 analogRead() 是拿 Uno 自己的 5 V 当满量程去量这个比例:改用 6 V 电池组喂摇杆,回中的轴读到的就不是 512 而是大约 614,程序会当成摇杆被一直推着不放 —— 关节自己就漂走了。Uno 只有一只 5 V 脚,而两支摇杆各要一组 5 V 和 GND,所以把面包板另外那条长边交给这件事:一条杜邦线从 Uno 5V 接到那条红色电源条,两支摇杆的 +5V 都插进去,它们的 GND 插旁边那条蓝色,再用一条杜邦线把那条蓝色和电池那条蓝色接起来。两组电源共用地,绝不共用正极。
为什么摇杆要控制速度,而不是角度?
模拟摇杆是弹簧回中的:一放手它就回到中间,那里 analogRead() 报出来大约是 1023 里的 512。把它直接映射成角度 —— 对云台来说这是对的做法,我们的摇杆云台教程就是这样做的 —— 那么中间就等于 90°。于是你一放手,每一个关节都被命令回到 90°,手臂就折下来了。
增量控制把这件事反过来:推的幅度决定速度,不是位置。每 20 ms,程序量一次摇杆离中间有多远,再按比例把零点几度加到一个存起来的目标角度上。推一半,关节慢慢爬;推到底,大约每秒走 60 °;放手回中,什么都不加,手臂就停在原地。
有三个细节让它真的听话。先减掉 512 两侧大约 40 个计数的死区,再去加 —— 因为一支静止的摇杆从来读不出一个干净的 512,电位器的机械中点和 ADC 噪声会飘上好几个计数,没有死区手臂就会自己爬。constrain() 把每个目标夹在各关节自己的上下限之间,这样关节就不会被推进自己的结构里去。目标值用的是 float,所以轻轻的推动累积的是零点几度,而不是四舍五入成零。那 20 ms 的节拍本身就是舵机的一个刷新帧 —— 库每帧给每只舵机发一个脉冲,所以更新得比这更快的目标值,根本到不了马达。

Arduino 机械手臂的程序长什么样?
这份程序只需要 Arduino IDE 自带的 Servo 库,编译出来占 5162 bytes 的 Flash(Uno 的 16%)和 282 bytes 的 RAM。先把限位数组改成你自己手臂的真实行程。AXIS_PIN 决定哪一支摇杆管哪一个关节,INVERT 决定它往哪一边转:某个关节转反了,就翻那一项 INVERT;动的是错的关节,就把两项 AXIS_PIN 对调。
// Arduino Uno 上的 4 舵机机械手臂,由两支模拟摇杆驱动。
// 摇杆控制的是速度,不是角度:推着它,关节就往那边慢慢走,
// 放开手,关节就停在原地。手臂能保持姿势靠的正是这一点:
// 直接把 analogRead 映射成角度的话,摇杆一弹回中间,
// 手臂就会立刻塌下来。
//
// 舵机的电不来自 UNO。四条舵机红线接到另外一组 4xAA 电池盒
//(或者一个 5V 电源);只有地是共用的。
#include <Servo.h>
Servo joint[4]; // 底座、肩、肘、夹爪
const uint8_t SERVO_PIN[4] = { 9, 10, 11, 3 }; // 信号脚(舵机橙线)
const uint8_t AXIS_PIN[4] = { A0, A1, A2, A3 }; // 摇杆 1 VRx/VRy,摇杆 2 VRx/VRy
const bool INVERT[4] = { false, true, false, false };
const uint8_t MIN_DEG[4] = { 10, 30, 20, 25 }; // 机械限位 - 量你自己那支手臂
const uint8_t MAX_DEG[4] = { 170, 150, 160, 90 };
const uint8_t HOME_DEG[4] = { 90, 90, 90, 60 }; // 归位姿势
const uint8_t PARK_BUTTON = 2; // 摇杆 2 的 SW 脚,接到 D2
const int CENTRE = 512; // 静止时的 analogRead(),0..1023
const int DEADBAND = 40; // 中间这么多计数的抖动直接忽略
const float MAX_STEP = 1.2; // 推到底时每个节拍走多少度
const unsigned long TICK_MS = 20; // 一个节拍等于舵机的一个刷新帧
float target[4]; // 我们正在下达的姿势,单位是度
unsigned long lastTick = 0;
void setup() {
Serial.begin(9600);
pinMode(PARK_BUTTON, INPUT_PULLUP); // 按下时 SW 对 GND 短路
for (uint8_t i = 0; i < 4; i++) {
target[i] = HOME_DEG[i];
joint[i].attach(SERVO_PIN[i]);
joint[i].write(HOME_DEG[i]);
delay(400); // 一次只归位一个关节:四只舵机
} // 同时弹到位,是这支手臂
// 会遇到的最大一次电流冲击
Serial.println(F("Arm parked. Servos must run from their own supply."));
}
void loop() {
unsigned long now = millis();
if (now - lastTick < TICK_MS) return; // 两帧之间没事可做
lastTick = now;
bool parking = (digitalRead(PARK_BUTTON) == LOW);
for (uint8_t i = 0; i < 4; i++) {
if (parking) {
// 用推到底同样的速度,慢慢爬回归位姿势。
if (target[i] < HOME_DEG[i]) target[i] = min(target[i] + MAX_STEP, (float)HOME_DEG[i]);
else target[i] = max(target[i] - MAX_STEP, (float)HOME_DEG[i]);
} else {
int offset = analogRead(AXIS_PIN[i]) - CENTRE;
if (abs(offset) <= DEADBAND) continue; // 摇杆静止:不写入,关节保持
// 减掉死区,让关节从零速开始,而不是跳一下。
offset += (offset > 0) ? -DEADBAND : DEADBAND;
float step = (float)offset * MAX_STEP / (float)(CENTRE - DEADBAND);
if (INVERT[i]) step = -step;
target[i] = constrain(target[i] + step, (float)MIN_DEG[i], (float)MAX_DEG[i]);
}
joint[i].write((int)(target[i] + 0.5)); // 四舍五入,再送出这一帧的角度
}
}
有两行的分量比看起来重:delay(400) 把舵机错开,让它们一只一只回到归位角度,把整个使用过程中最大的一次电流冲击拆成四次小的;而 continue 跳过了 write() —— 一只什么都没收到的舵机会保持它上一次的角度,所以「什么都不做」本身就是保持。
手臂的框架要用什么做?
我们卖的是电子件,不是框架 —— 我们的目录里没有手臂结构件,也没有现成的打印件。这件事没有听起来那么要紧:瓦楞纸皮,用美工刀裁、热熔胶粘,就是第一版最合适的材料,因为这个几何形状你会重画三次。亚克力或者 3 mm 夹板是之后的升级。
决定这个几何形状的是扭力。我们这只 SG90 的额定值是 4.8 V 下 1.3 kg/cm —— 也就是 1.3 kg 挂在离轴心一厘米的地方,所以挂到十厘米就只剩大约 130 g,还要再扣掉手臂自己的重量。每一节控制在 10–12 cm,夹爪做轻,然后可以预期最先撑不住的是肩关节:它要同时抬起小臂、肘关节舵机、夹爪和负载,用的还是整支手臂上最长的那根杠杆。MG90 是直接替换的答案:一样的外形和引线,6 V 下 2.2 kg/cm,齿轮是金属的,不是尼龙的。
每个关节都要在舵机对面那一侧做一个枢轴 —— 一根螺丝,或者一颗螺丝穿过一片纸皮垫圈,位置就在关节的转轴线上。SG90 的输出是尼龙齿轮组上一根小小的尼龙花键轴,它是设计来转动负载的,不是用来承受负载的,所以把小臂单独吊在它身上,等于把所有弯曲的力都灌进那组齿轮里。底板也要压重,不然转起来的是底座,不是手臂。
舵盘最后才装。先让每个关节走到它的归位角度,然后才拧舵盘的螺丝,而且每一片舵盘都要装在行程的中段:在行程的一端把舵盘装上去,你的动作范围就有一半消失在结构里了。我们的180° / 270° / 360° 舵机怎么选把舵盘和角度范围讲清楚了 —— 手臂要的是 180° 的定位型舵机,绝对不是连续旋转型的。这里看着一支四关节框架装起来会有帮助:
什么时候四个直接输出脚就不够用了?
有三件事会把你推向 PCA9685 16 路驱动板:关节数量超过了手上方便用的脚位;想把 pin 9 和 pin 10 拿回来做 analogWrite();或者用到会长时间关闭中断的库 —— SD 卡、某些显示屏 —— 那会让定时器产生的脉冲抖动,而 PCA9685 是用自己的振荡器发脉冲,不受影响。我们的 PCA9685 教程讲的就是这一步。它做不到的是变出电流来:它的 V+ 螺丝端子照样要接同一组外部电源。
我们常看到的错误
用一只舵机接在 Uno 的 5 V 脚上,证明「这样可以」。一只 SG90 确实跑得动那只脚,所以第一次测试通过了,接线看起来就定案了。两只往往也没事 —— 然后第三只或者第四只关节把供电压垮,全部一起失灵,而背黑锅的是最后改过的那个地方,不是电源。
没有把地接起来。电池接舵机接得完全正确,但电池负极那条和 Uno 的 GND 之间什么都没有:接线看起来是对的,手臂的行为却是随机的。在动手改程序之前,先查这一点。
关节限位靠猜。一只被命令超出框架允许范围的舵机不会认输 —— 它会停在堵转状态,吃着最大电流发热,直到有东西崩掉。这就是 MIN_DEG 和 MAX_DEG 要防的事:每个关节先保守地从 60–120° 开始,一次放宽五度,因为关节开始嗡嗡叫的那个角度,就是它碰到自己限位的角度。夹爪要一样小心,理由却不同:它的闭合限位不是一个机械挡点,而是手指刚好碰到物体的那个角度,再过一度,只要你还夹着这个东西,它就一直堵转。
把嗡嗡声当成故障。定位型舵机是一个闭环:它拿自己内部的电位器和你送进去的脉冲比较,然后驱动马达直到两者一致。带着负载的时候它永远差那么一点,所以它会在目标附近来回微动 —— 那阵轻微的嗡嗡声就是关节在干活。大声到整个框架都在震的嗡嗡声,那是关节到了扭力极限:把这一节缩短、做轻,或者换上 MG90。
拿一颗 9 V 电池去喂舵机。两个地方都错:9 V 高过 SG90 的 6 V 上限,而且 PP3 方形电池那几颗小电芯,在四只舵机要的电流下会塌得很厉害。
常见问题
Arduino Uno 带得动 4 只 SG90 舵机吗?
带不动。四只 SG90 动起来吃 0.4–1 A,堵转时最高 2.8 A;Uno 那条供电用 USB 时大约只给得出 450 mA。四条信号线它驱动得很好 —— 电流要有自己的电池组。
为什么机械手臂一动,我的 Arduino 就复位?
舵机把 5 V 供电拉到了 ATmega328P 的欠压复位门槛之下。芯片复位,舵机弹回归位角度,供电又塌下去。给它们自己的电源,并且把地接在一起。
Arduino 机械手臂该用什么电池?
四颗 AA:碱性 6.0 V 或者镍氢 4.8 V,两者都在 SG90 的 4.8–6 V 窗口里,也都拿得出安培级电流。5 V 3 A 适配器是更整齐的替代方案。9 V PP3 方形电池不要碰舵机那条电源 —— 接在 Uno 自己的电源座上倒是没问题。
为什么我一放开摇杆,机械手臂就掉下来?
因为程序把摇杆读数直接映射成了角度,而放开的摇杆读数大约是 1023 里的 512 —— 换算过去就是每个关节 90°。改成按推的幅度、每个节拍加零点几度,回中时什么都不加。
做一支 4 舵机机械手臂,需要 PCA9685 驱动板吗?
不需要。四只舵机直接接 Uno 的四个数字脚就能跑。PCA9685 是在你需要的通道数超过脚位、想把 pin 9 和 pin 10 拿回来做 analogWrite(),或者用了会干扰定时器脉冲的库时,才有它的价值。它不提供电流。
最后更新:2026 年 8 月。有问题?WhatsApp 联系我们。



SG90 MG90 Tower Pro Micro Servo Motor 9g 180 360 Servo Motor for Arduino Robotic - SG90- 180°
Arduino Uno Compatible SMD UNO R3 with Type B Cable - ATMEGA328P with CH340G-Microcontroller Project
Joystick Module X Y Z axis 5 Pin Analog Joy Stick Controller for Arduino Robotic
MB102 Breadboard 170 400 830 Holes Breadboard Donut Board Arduino Prototype Multi Color - BREADBOARD (400 HOLES)
AA Battery Holder with Cover On/Off Switch 2/3/4 Slots Battery AA Holder Red/Black Wire - AA BATTERY CASE (4S)
40pcs Dupont Wire 10cm 20cm 30cm for Breadboard DIY Experiment Jumper Wire Breadboard wire - DUPONT WIRE M-M 20CM
40pcs Dupont Wire 10cm 20cm 30cm for Breadboard DIY Experiment Jumper Wire Breadboard wire - DUPONT WIRE M-F 20CM
SG90 MG90 Tower Pro Micro Servo Motor 9g 180 360 Servo Motor for Arduino Robotic - MG90- 180°
Power Supply Adapter DC Universal AC to DC Converter PSU 5V2A 5V3A 9V2A 12V2A - P.S. ADAPTOR (5V3A)
5.5x2.1mm DC Power Male Connector Plug Jack Adapter for Arduino DIY Electronics Projects - 5.5x2.1 DC CONNECTOR (F)
16 Channel PWM Servo Motor Driver PCA9685 16 PWM Output with I2C Communication For Arduino Robotic