嵌入式开发 舵机角度控制:SG90/MG996 对比测试与精准定位实战
为什么舵机角度总是不准?
玩过舵机的朋友应该都遇到过这个问题:代码里写的是 90 度,实际转过去一看,要么 85 度要么 95 度,永远对不准。更别提 SG90 和 MG996 这两种常见舵机,价格差 5 倍,性能到底差在哪?
今天我们就来实测对比,顺便把角度校准的坑都填了。
硬件清单
| 型号 | 类型 | 扭矩 | 速度 | 价格 | 适合场景 |
|---|---|---|---|---|---|
| SG90 | 塑料齿轮 | 1.6kg/cm | 0.12s/60° | ¥8-12 | 小型云台、舵机云台 |
| MG996 | 金属齿轮 | 10kg/cm | 0.17s/60° | ¥35-45 | 机器人关节、机械臂 |
| Arduino Uno | 控制板 | - | - | ¥25-35 | 主控 |
| 5V 2A 电源 | 供电 | - | - | ¥15-20 | 独立供电(重要!) |
| 杜邦线 | 连接 | - | - | ¥5 | 若干 |
⚠️ 重要提醒: MG996 工作电流峰值可达 1A+,千万不要用 Arduino 的 5V 引脚直接供电!必须用独立 5V 电源,GND 共地即可。
舵机工作原理简述
舵机内部其实是个闭环控制系统:
PWM 信号 → 控制电路 → 电机 → 齿轮组 → 电位器反馈 → 比较电路
-
PWM 信号: 周期 20ms(50Hz),脉宽 0.5-2.5ms 对应 0-180 度
-
电位器: 检测当前角度,反馈给控制电路
-
控制电路: 比较目标角度和实际角度,驱动电机转动
SG90 和 MG996 的核心区别:
| 对比项 | SG90 | MG996 |
|---|---|---|
| 齿轮材质 | 塑料 | 金属 |
| 轴承 | 塑料套 | 双滚珠轴承 |
| 死区 | 较大(约 5 度) | 较小(约 2 度) |
| 耐冲击 | 差,易扫齿 | 好 |
| 精度 | ±5 度 | ±2 度 |
基础控制代码
先上最基础的 Arduino 代码,使用 Servo 库:
#include
Servo myServo;
void setup() {
myServo.attach(9); // PWM 引脚 9
Serial.begin(9600);
}
void loop() {
// 0 度 → 90 度 → 180 度 → 90 度 → 0 度
myServo.write(0);
delay(1000);
myServo.write(90);
delay(1000);
myServo.write(180);
delay(1000);
myServo.write(90);
delay(1000);
}
看起来很简单对吧?但实际用起来问题一堆。
角度校准实战
问题 1:0 度和 180 度位置不准
不同批次舵机的 PWM 脉宽范围有差异。Servo 库默认:
-
0 度 = 544μs
-
180 度 = 2400μs
但实际可能需要调整。校准方法:
#include
Servo myServo;
void setup() {
// 手动指定脉宽范围(单位:微秒)
myServo.attach(9, 500, 2500); // 根据实际调整
Serial.begin(9600);
Serial.println(\"开始校准...\");
Serial.println(\"发送 0/90/180 测试角度\");
}
void loop() {
if (Serial.available()) {
int angle = Serial.parseInt();
if (angle >= 0 && angle
Servo myServo;
int lastAngle = -1;
const int DEAD_ZONE = 3; // 死区 3 度
void moveToAngle(int targetAngle) {
if (abs(targetAngle - lastAngle) > DEAD_ZONE) {
myServo.write(targetAngle);
lastAngle = targetAngle;
delay(300); // 给舵机转动时间
}
}
void setup() {
myServo.attach(9);
Serial.begin(9600);
}
void loop() {
moveToAngle(0);
delay(1000);
moveToAngle(90);
delay(1000);
moveToAngle(180);
delay(1000);
}
加入死区后,小幅度的角度变化不会触发舵机动作,减少抖动和磨损。
SG90 vs MG996 实测对比
测试 1:角度精度
用角度尺实测 5 个位置(0°/45°/90°/135°/180°):
| 目标角度 | SG90 实测 | 误差 | MG996 实测 | 误差 |
|---|---|---|---|---|
| 0° | 3° | +3° | 1° | +1° |
| 45° | 47° | +2° | 46° | +1° |
| 90° | 92° | +2° | 91° | +1° |
| 135° | 133° | -2° | 134° | -1° |
| 180° | 177° | -3° | 178° | -2° |
结论: MG996 精度明显更好,平均误差±1 度 vs SG90 的±2-3 度。
测试 2:负载能力
挂重物测试最大可用扭矩:
-
SG90: 臂长 2cm 时,超过 800g 就开始丢步
-
MG996: 臂长 2cm 时,1.5kg 仍能保持位置
测试 3:噪音
-
SG90: 塑料齿轮啮合声明显,“滋滋”声
-
MG996: 金属齿轮声音低沉,但更安静
测试 4:响应速度
从 0 度转到 180 度用时:
-
SG90: 约 0.25s(标称 0.12s/60°,实测偏慢)
-
MG996: 约 0.5s(标称 0.17s/60°,实测接近)
进阶:多舵机协同控制
做机械臂或云台时,需要同时控制多个舵机。注意供电!
#include
Servo servo1, servo2, servo3;
void setup() {
// 每个舵机用独立的 PWM 引脚
servo1.attach(9);
servo2.attach(10);
servo3.attach(11);
// 依次初始化,避免同时启动电流过大
servo1.write(90);
delay(200);
servo2.write(90);
delay(200);
servo3.write(90);
}
void loop() {
// 协同运动示例:三舵机同步扫描
for (int angle = 0; angle = 0; angle -= 5) {
servo1.write(angle);
servo2.write(180 - angle);
servo3.write(angle / 2 + 45);
delay(20);
}
}
供电计算: 3 个 MG996 同时启动,峰值电流可能达到 3A+,建议用 5V 5A 电源。
常见问题排查
Q1: 舵机不转动
检查清单:
-
$1
-
$1
-
$1
-
$1
Q2: 舵机转动但抖动严重
可能原因:
-
$1
-
$1
-
$1
-
$1
Q3: 舵机转到奇怪的角度
解决方法:
-
$1
-
$1
-
$1
Q4: 多个舵机时 Arduino 复位
原因: 舵机启动电流导致 Arduino 供电电压跌落
解决:
-
$1
-
$1
-
$1
选型建议
选 SG90 如果:
-
预算有限(¥10 vs ¥40)
-
负载轻(<500g)
-
精度要求不高(±5 度可接受)
-
一次性项目或学习用
选 MG996 如果:
-
需要可靠耐用(金属齿轮)
-
负载较大(500g-1.5kg)
-
精度要求高(±2 度)
-
长期运行项目
其他选择:
-
MG90S: SG90 的金属齿轮版,¥15-20,性价比不错
-
DS3235: 数字舵机,精度±0.5 度,¥80+,高端项目用
-
总线舵机: 多个舵机串联,省 IO 口,适合多自由度机器人
总结
舵机看似简单,但要控制好角度还是需要一些技巧:
-
$1
-
$1
-
$1
-
$1
希望这篇博客文章对您有所帮助!