180度位置版
像一个听话的指针,给它 0~180 度目标角度,转到后会停住。
SG90 Servo Comparison
同样叫 SG90,180度位置舵机是“转到指定角度就停”,360度连续旋转舵机是“按方向和速度一直转”。本页整理本店实测接线、Arduino IDE 代码、外部 5V 供电要求,以及 360 度版 write(90) 停不住的排查结论。
Quick Answer
客户问“SG90 180度和360度有什么区别”,最短答案是:180度版控制角度,360度版控制方向和速度。
像一个听话的指针,给它 0~180 度目标角度,转到后会停住。
像一个小减速电机,给它方向和速度,自己不知道转了多少度。
360度版要用 writeMicroseconds(1500) 停,不能把 write(90) 当停止。
SKU
| 版本 | SKU | 适合场景 | 页面可信度 |
|---|---|---|---|
| SG90 180度位置舵机 | I56 | 做指针、机械臂、云台、扫角测试,需要“转到某个角度”。 | ✓ 实拍图和规格已核对,代码已编译并实机验证。 |
| SG90 360度连续旋转舵机 | 01401 | 做小车轮、转盘、连续旋转机构,需要“往某方向转多快”。 | ✓ SKU 已确认;代码和停止点实测;实拍图和模块规格待补充。 |
选型钩子:“180度这只知道自己转到几度,360度这只呢?它只知道自己在转,转了多少度,连它自己都不知道。”
Choose
| 客户需求 | 推荐 | 原因 |
|---|---|---|
| 让机构停在 0度、45度、90度、180度 | 180度位置版 | 内部有位置反馈,目标角度到了就停。 |
| 让轮子持续正转、反转、调快慢 | 360度连续旋转版 | 指令本质是速度和方向,不是角度。 |
| 要精确知道转了多少圈 | 另选带编码器电机 | 普通 360度连续旋转舵机没有角度反馈,单片机也不知道实际圈数。 |
| 客户说“360度版停不住” | 先看代码 | 常见不是舵机坏,而是用了 write(90) 或停止点没有校准。 |
Parameters
本店实拍图,带“明武电子”水印,规格来自图片标注和 SKU 素材库。
| 项目 | 值 | 来源 |
|---|---|---|
| 型号 | SG90,塑料齿轮 | ✓ SKU 素材库 |
| 扭矩 | 1.5kg/cm | ✓ 产品图标注 |
| 工作电压 | 4.2V~6V | ✓ 产品图标注 |
| 反应速度 | 0.3sec / 60度 | ✓ 产品图标注 |
| 动作死区 | 10us | ✓ 产品图标注 |
| 工作模式 | 模拟 | ✓ 产品图标注 |
| 使用温度 | 0~55度 | ✓ 产品图标注 |
| 尺寸 | 23mm × 12.2mm × 29mm | ✓ 产品图标注 |
| 重量 | 14克 | ✓ 产品图标注 |
| 360度连续旋转版规格 | 待补充 | 暂无单独实拍图和 SKU,不编参数。 |
Pins
| 连接点 | 接到哪里 | 说明 |
|---|---|---|
| 舵机信号线 | Arduino D9 | 180度或360度都用同一个脚,换舵机时不用改接线习惯。 |
| 舵机红线 | 外部 5V 电源正极 | 不要只靠电脑 USB,转大角度时容易复位。 |
| 舵机棕线 | 外部电源负极 + Arduino GND | 必须共地,否则信号参考点不一致。 |
| OLED A4/A5 | Sensor Shield V5.0 专用 IIC 接口 | UNO R3 硬件 I2C:A4=SDA,A5=SCL。 |
Wiring
最容易接错:舵机红线接外部 5V,棕线接外部电源负极,并且这个负极要和开发板 GND 连在一起。只接信号线、不共地,舵机会乱动或不响应。
看图补充:新版接线图按学习套件画出 A0 电位器和 Sensor Shield 的 SEL 跳帽位置。当前页面下载的两份 OLED 测试代码不读取 A0;如果只跑本页代码,舵机 D9、OLED IIC、外部 5V 与共地是必接重点。
PWM
Arduino Servo 库里的 write(angle) 本质会按 attach(min,max) 的范围,把 0~180 映射成脉宽。对 180度舵机,这样写很顺手;对 360度舵机,停点要按微秒精确控制。
sg90.attach(9, 500, 2400) 后,write(0) 到左端,write(90) 回中位,write(180) 到右端。
最终代码使用 sg90.attach(SERVO_PIN, 900, 2100),停止指令仍然明确写成 writeMicroseconds(1500),正转和反转在 1500us 两侧加减速度档位。
实测结论:360度连续旋转舵机不要把“90度”当成“停在90度”。它控制的是转向和速度,停止点请在代码里直接用 writeMicroseconds(1500) 表达;如果个别舵机仍轻微慢转,再围绕 1500us 小幅校准。
Principle
180度舵机像个“听话的指针”:里面自带电位器,知道自己转到哪了,转到指定角度就停住不动。这叫闭环控制。
360度舵机像个“没有仪表盘的马达”:里面就是电机加齿轮,压根没有任何零件能测出转到了哪。发给它的指令根本不是“转到几度”,是“往哪个方向转、转多快”。它自己不知道转了多少圈,单片机也不知道,没人知道。这叫开环控制。
Arduino IDE
以下两份代码来自本店实测工程,开发环境是 Arduino IDE。代码顶部注释里的接线说明保留原样,上传前请安装 Servo、Adafruit_GFX、Adafruit_SSD1306 等库。
/*
* SG90 180度舵机 + OLED 单独测试 · Arduino UNO R3
*
* 只接一只 180 度舵机,OLED 实时显示当前角度。360度那只这次不接。
*
* ── 接线 ────────────────────────────────────────────
* D9 180度舵机,红线接外部5V电源,棕线接外部电源负极+UNO的GND
* A4/A5(硬件I2C) OLED,接 B302 扩展板专门的 IIC 接口
*
* ── 串口命令(115200)────────────────────────────
* l = 左转到头(0度) r = 右转到头(180度) m = 回中位(90度)
* 0~180 = 直接打到这个角度
*/
#include <Servo.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SERVO_PIN 9
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_ADDR 0x3C
Servo sg90;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
int currentAngle = 90;
int stepMs = 150; // 每步间隔,USB供电必须留够回血时间,2026-08-10实测过
String buf = "";
void drawAngle(const char *hint) {
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.println(F("SG90 - 180 degree"));
display.drawFastHLine(0, 10, SCREEN_WIDTH, SSD1306_WHITE);
display.setTextSize(4);
display.setCursor(20, 20);
display.print(currentAngle);
display.setTextSize(1);
display.setCursor(0, 56);
display.print(hint);
display.display();
}
void moveTo(int angle, const char *tag) {
angle = constrain(angle, 0, 180);
int step = (angle > currentAngle) ? 3 : -3;
while (abs(angle - currentAngle) > 3) {
currentAngle += step;
sg90.write(currentAngle);
drawAngle(tag);
delay(stepMs);
}
sg90.write(angle);
currentAngle = angle;
drawAngle(tag);
Serial.print("[");
Serial.print(millis() / 1000.0, 1);
Serial.print("s] ");
Serial.print(tag);
Serial.print(" 角度=");
Serial.println(angle);
}
void setup() {
Serial.begin(115200);
Serial.println(F("SG90 180度 + OLED 单独测试"));
Serial.println(F("l=左转到头 r=右转到头 m=回中位 或直接打0~180"));
if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
Serial.println(F("!! OLED 没反应,检查IIC接线"));
}
display.setTextColor(SSD1306_WHITE);
sg90.attach(SERVO_PIN, 500, 2400);
moveTo(90, "ready");
}
void loop() {
while (Serial.available()) {
char c = Serial.read();
if (c == '\n' || c == '\r') {
buf.trim();
if (buf.length() == 0) return;
String cmd = buf; cmd.toLowerCase(); buf = "";
if (cmd == "l") moveTo(0, "left / 0deg");
else if (cmd == "r") moveTo(180, "right / 180deg");
else if (cmd == "m") moveTo(90, "middle / 90deg");
else {
int a = cmd.toInt();
if (a >= 0 && a <= 180 && (a != 0 || cmd == "0")) moveTo(a, "manual");
else Serial.println(F(">> l左 r右 m中位 或 0~180"));
}
} else if (buf.length() < 8) buf += c;
}
}
/*
* SG90 360度(连续旋转)舵机 + OLED 单独测试 · Arduino UNO R3
*
* 只接一只 360 度舵机,OLED 实时显示"转/停"和方向。180度那只这次不接。
*
* ── 接线 ────────────────────────────────────────────
* D9 360度舵机,红线接外部5V电源,棕线接外部电源负极+UNO的GND
* (沿用 PIN 9,跟180度那条素材同一个脚,两条视频不用改接线习惯)
* A4/A5(硬件I2C) OLED,接 B302 扩展板专门的 IIC 接口
*
* ── 串口命令(115200)────────────────────────────
* s = 停(writeMicroseconds 1500,不用write(90)这种角度写法表示停止)
* f = 正转 b = 反转 1/2/3 = 慢/中/快
*/
#include <Servo.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SERVO_PIN 9
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_ADDR 0x3C
#define US_STOP 1500 // 本次实测停止点,停止时直接写微秒值更明确
Servo sg90;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
int dir = 0; // -1反转 0停 +1正转
int speedLevel = 1;
const int SPEED_TABLE[3] = {80, 200, 400};
const char *SPEED_NAME[3] = {"slow", "mid", "fast"}; // 对应 1/2/3 = 慢/中/快
String buf = "";
void drawState(const char *hint) {
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.println(F("SG90 - 360 degree"));
display.drawFastHLine(0, 10, SCREEN_WIDTH, SSD1306_WHITE);
display.setTextSize(3);
display.setCursor(15, 20);
if (dir == 0) display.print(F("STOP"));
else if (dir > 0) display.print(F(" GO>"));
else display.print(F("<GO "));
// 速度档位:s停的时候不显示速度(停了速度没意义),转动时显示当前档位
display.setTextSize(1);
display.setCursor(0, 44);
if (dir != 0) {
display.print(F("speed: "));
display.print(SPEED_NAME[speedLevel]);
display.print(F(" ("));
display.print(speedLevel + 1);
display.print(F("/3)"));
}
display.setCursor(0, 56);
display.print(hint);
display.display();
}
void apply(const char *tag) {
int us = (dir == 0) ? US_STOP : US_STOP + dir * SPEED_TABLE[speedLevel];
sg90.writeMicroseconds(us);
drawState(tag);
Serial.print("[");
Serial.print(millis() / 1000.0, 1);
Serial.print("s] ");
Serial.print(tag);
Serial.print(" 脉宽=");
Serial.print(us);
Serial.println("us");
}
void setup() {
Serial.begin(115200);
Serial.println(F("SG90 360度 + OLED 单独测试"));
Serial.println(F("s=停 f=正转 b=反转 1/2/3=慢/中/快"));
if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
Serial.println(F("!! OLED 没反应,检查IIC接线"));
}
display.setTextColor(SSD1306_WHITE);
sg90.attach(SERVO_PIN, 900, 2100);
apply("ready, stopped");
}
void loop() {
while (Serial.available()) {
char c = Serial.read();
if (c == '\n' || c == '\r') {
buf.trim();
if (buf.length() == 0) return;
String cmd = buf; cmd.toLowerCase(); buf = "";
if (cmd == "s") { dir = 0; apply("stop (1500us)"); }
else if (cmd == "f") { dir = 1; apply("spin forward"); }
else if (cmd == "b") { dir = -1; apply("spin backward"); }
else if (cmd == "1" || cmd == "2" || cmd == "3") {
speedLevel = cmd.toInt() - 1;
apply("speed changed");
} else Serial.println(F(">> s停 f正转 b反转 1/2/3调速"));
} else if (buf.length() < 8) buf += c;
}
}
Troubleshooting
现象:串口发了 90 度,舵机还是慢慢转。原因:360度连续旋转舵机的“90”不是目标角度,代码里应该把停止点明确写成脉宽,不要靠角度语义猜。动作:改用 servo.writeMicroseconds(1500),必要时围绕 1500us 微调。
现象:串口反复打印开机横幅,舵机转一点点就停,又从头开始。原因:USB 供电扛不住舵机大幅度转动的电流冲击。动作:舵机红线接外部 5V,棕线接外部电源负极,并与开发板 GND 共地。
普通 360度连续旋转舵机不能只靠这根 PWM 信号知道自己转了多少度。它没有角度反馈,控制的是方向和速度;要精确圈数,需要另选带编码器的电机或额外加传感器。
Support
复制下面这段填一下发给客服,我们一次就能定位,不用来回问。
Downloads
下载包内含两份已编译通过、实机验证过的 Arduino IDE 例程,文件名保持原始工程名。
Sources
assets/modules/sg90-180-vs-360-servo/I56_sg90_180.jpg,来自本店 SKU 素材库。info.md,页面按模块参数处理。write(90) 不是 360度版停止点、USB 供电不足导致复位,均来自本店实测踩坑记录。