
第一次拿起 SG90 180 度位置舵机时多数人的状态差不多三根线一根红一根棕一根橙接上 Arduino UNO下载一段现成示例舵机确实动了。问题通常从第二步开始——为什么有的代码里attach(9)就够了有的却要写attach(9, 500, 2500)注释写着“0 到 180 度”那 500 和 2500 到底是什么意思还有人说舵机是闭环控制可我明明只发了一个 PWM 信号出去没看到任何反馈回来。这些困惑其实指向同一个核心SG90 真正的入门门槛不在代码而在理解“脉宽即角度”这件事以及舵机内部那个你看不到、也读不出来的位置闭环。这篇文章会围绕 Arduino UNO 实测展开把接线、attach参数、角度标定、供电问题、内部闭环和外部开环的区别串成一条线。你会发现真正卡住新手的往往不是write(90)而是“为什么舵机在某个角度会咔咔响”“为什么一动起来 Arduino 就重启”“为什么明明写了 180 度却转不到位置”。1. attach 里的两个数字说的不是角度而是微秒1.1 先理解舵机要的是 50Hz 下的高电平宽度SG90 这类位置舵机接收的不是普通直流电压而是一串周期 20ms 的脉冲信号对应频率就是 50Hz。真正关键的不是这个周期而是每个周期里高电平持续了多久。常见位置舵机的典型映射大约是0.5ms 的高电平对应 0 度方向2.5ms 左右对应 180 度方向1.5ms 正好是中位。不过你最好不要把“0.5 到 2.5 对应 0 到 180”当成所有 SG90 的绝对事实。不同厂家、不同批次甚至不同商家贴牌的同型号舵机实际脉冲范围都可能不同。很多舵机实际能稳定走到的范围要小于标称值。这也解释了为什么你搜教程时会看到两种写法。一种直接myservo.attach(9);另一种带上范围myservo.attach(9, 544, 2400);544和2400是 Arduino Servo 库的默认最小值和最大值单位是微秒。如果不传这两个参数库就会按默认544us对应 0 度、2400us对应 180 度来工作。这不是“SG90 标称范围”的官方结论只是 Arduino 库的保守默认值。它适合让舵机先动起来但不一定适合你的具体舵机。1.2 attach 参数范围意味着你给舵机画了一条可活动边界attach(pin, min, max)中的min和max本质上是在告诉 Servo 库这个舵机的脉冲范围从哪里到哪里。调用write(0)时库会把 0 映射到min调用write(180)时映射到max中间角度按近似线性关系均匀分配。所以你在attach里写的不是角度而是你根据手里这颗舵机实测出来的脉冲宽度范围。很多新手会犯这样的错误把min和max写得很宽比如attach(9, 500, 2500)结果一运行舵机往两端转的时候发出“咔咔咔”的声音或者到某个位置后明显在用力顶住机械限位。这不是代码语法错误而是你给舵机画的运动范围超出了它真实的机械行程。我建议第一次接上未知批次 SG90 时不要直接信任某个固定范围。先用writeMicroseconds做标定把脉冲宽度一点点往两端试探找到你这颗舵机真正能到达、又不会堵转的安全边界。注意write(0)和write(180)并不一定对应你舵机真实的 0 度和 180 度。它只是 Servo 库按照你attach时设定的min、max映射出来的结果。角度标定的关键在于确认脉宽和实际位置是否一致。2. 同一个 SG90 外壳可能是两种完全不同的舵机2.1 位置舵机与 360 度连续旋转舵机SG90 这个名字其实覆盖了两类产品。一类是常见的 180 度位置舵机也叫有限角度舵机另一类是 360 度连续旋转舵机外形几乎一样但内部已经被改造成类似直流电机的持续旋转设备。如果你的项目真的需要让舵机“一直转”比如做小车驱动那你需要的是连续旋转版本。但如果你买到的是一颗 180 度位置舵机却期待它能像电机一样转个不停那结果就是它转到边界后顶着限位咔咔响。区分方法不复杂。位置舵机收到对应 0 度的脉宽时会朝一个方向转动直到它在机械上被挡停收到对应 180 度的脉宽时会朝另一个方向转到被挡停。连续旋转舵机收到相同信号后通常会以某个速度持续转动而不是停在某个角度。一个更安全的测试方式是在代码里发writeMicroseconds(1500)也就是理论上位于中位的脉冲。位置舵机会尝试回到中间位置停下连续旋转舵机通常会在 1.5ms 附近停止。如果接到的是连续旋转版本你想通过角度映射去控制它方向就完全错了。2.2 从 180 度位置舵机到串行总线舵机多出来的能力是反馈SG90 在舵机家族里属于非常基础的模拟位置舵机塑料齿轮、小扭矩、无反馈引出。以常见规格来说体积小、重量轻适合云台、小机械臂手指、小车转向这一类轻负载场景。网上很多仿生手臂项目会大量使用 SG90 或其他 9g 舵机因为单只重量轻、关节尺寸小。但这并不代表它适合所有机械臂。仿生手如果每个手指都承担负载SG90 的小扭矩会很快暴露短板表现为抖动、过载发热、舵机臂松动。再往上一层还有数字舵机、金属齿轮大扭矩舵机、以及带串行总线的总线舵机。总线舵机和普通舵机最大的区别不只是控制方式从 PWM 变成了串口通信而是它通常能反馈角度、电压、温度、负载等信息。对多关节机械臂来说能读到每个关节当前角度意味着可以在外部建立真正的闭环控制。这也是为什么很多人玩到后期会把 SG90 换成总线舵机不是 PWM 控制太难而是只知道目标角度、不知道实际角度系统一旦累加误差或遇到外力干扰就很难继续精确工作。2.3 SG90 适合先把“位置执行”这件事跑通SG90 最大的学习价值是让你第一次理解位置舵机的本质你给的不是“让它转到 90 度”的电平而是一段特定宽度的高电平脉冲。舵机内部会把这段脉冲翻译成一个目标位置。它不会读取外部角度也不会告诉你现在转到了哪里。所以它能帮你在一个低成本、低风险的环境里理解“指令、执行、反馈”三者的关系。3. Arduino UNO 实测先跑一个不会毁齿轮的最小流程3.1 接线与供电为什么不要迷信 USB 口供电接线的颜色顺序需要特别注意。常见 SG90 有三根线线色连接位置说明棕色或黑色GND和 Arduino 共地红色5V 或外部电源正极舵机供电橙色或黄色Arduino 数字引脚信号线接入attach指定引脚很多新手把红线接到 Arduino 的 5V 引脚棕线接 GND橙线接 D9代码下载后也能转。但要注意Arduino UNO 板载稳压器能提供的电流有限当你只驱动一个空载 SG90 时临时这样跑问题不大一旦舵机带负载、瞬间启动或堵转电流会明显上升USB 电压可能被拉低PC 端会识别到 Arduino 重新枚举也就是俗称的“复位”。我建议从第一次接线开始就养成外接电源的习惯。拿一个 5V 电源单独给舵机供电Arduino 用 USB 供电然后把两边负极连在一起。这个“共地”操作容易被忽略但对舵机控制至关重要。如果不共地Arduino 发出的信号和舵机电源之间没有统一参考点信号会变得极不可靠。3.2 第一步不是扫 0 到 180而是先验证中位很多人上电第一件事就是让舵机从 0 扫到 180看起来很有成就感但这其实不是最佳路径。因为你没确认这颗舵机真实的脉宽范围可能一个write(0)就把舵机推向物理限位此时如果舵盘被什么东西挡住齿轮和电机都会承受额外压力。更稳的顺序是先让舵机回中位。最小代码可以这样#include Servo.h Servo myservo; const int servoPin 9; void setup() { myservo.attach(servoPin, 544, 2400); myservo.write(90); delay(1000); } void loop() { }上电后舵机应该会转到一个接近中间的位置然后停下。如果它在中位附近安静停住说明供电和接线大概率正常。接下来再用writeMicroseconds直接发脉冲绕过角度映射做一次更可控的行程测试myservo.writeMicroseconds(1500); delay(1200); myservo.writeMicroseconds(1000); delay(1200); myservo.writeMicroseconds(2000); delay(1200);这段代码的含义是1500微秒理论中位。1000微秒尝试往一个方向转动。2000微秒尝试往另一个方向转动。如果舵机在1000或2000时出现了“咔咔咔”的堵转声说明这个值已经超过了你手上这颗舵机的实际安全范围。此时要把数值往回收比如改成1100和1900重新确认边界在哪里。注意别让舵机长时间处于堵转状态。位置舵机收不到目标位置时控制电路会继续驱动电机但机械部分已经转不动了电流会持续升高齿轮和驱动芯片都容易受损。3.3 标定好 min / max再考虑要不要 writeMicroseconds当你通过writeMicroseconds找到左右两个安全边界后再把它们换算成attach参数。比如你实测发现这颗 SG90 在600us附近能到达一侧极限在2350us附近能到达另一侧极限那你就可以写myservo.attach(servoPin, 600, 2350);这样后续使用write(0)到write(180)时角度映射会更接近这颗舵机的真实行程。很多教程喜欢让新手直接使用attach(9, 500, 2500)作为标准写法。但在实际项目中我更建议做一次 5 分钟的标定。因为 SG90 这类低成本舵机的个体差异实在太明显了A 舵机在500us时还能正常转动B 舵机可能已经顶死限位。标定的价值不是追求精确而是避免让舵机在堵转状态下工作。writeMicroseconds的另一个用途是你想精确控制某个位置时可以直接写微秒而不必经过角度映射。例如发现1450us才是真正的机械中位那就让舵机停在1450不要简单写write(90)。4. SG90 到底是不是“闭环”为什么从 Arduino 看它又像开环4.1 电位器 控制板组成了舵机内部的迷你位置环这是个容易引起混淆的问题。说 SG90 是闭环设备有道理说从外部看它是开环控制也有道理。两句话站的角度不同。SG90 外壳里不是只有一个普通直流电机而是由电机、减速齿轮、电位器、控制电路共同组成。输出轴转动时会带动一个电位器跟着转电位器把当前机械角度转换成电压信号。控制电路把输入脉冲的目标位置与电位器反馈的当前位置进行比较如果两者有误差就驱动电机朝消除误差的方向转。误差变小到控制电路的死区范围内后电机停止。所以SG90 内部确实存在一个位置闭环。只是这个闭环做得非常基础精度有限而且没有把电位器采样值引出到外部。这会带来两个直接结果你给舵机一个目标脉冲它可以自主消除外部干扰造成的部分位置偏差。你无法从 Arduino 端读到“它当前实际在哪个角度”。用一句话概括SG90 的内部是闭环对外是开环。4.2 外部没有反馈所以真做闭环得额外加传感器或换总线舵机如果你需要的是一个外部可见的位置反馈普通 SG90 显然不够。比如你要求机械臂在负载变化时仍然能精准回到某个角度单靠write(90)是不行的因为你不知道它实际有没有到位。要让外部系统获得舵机当前角度通常有三种路径第一种在舵机输出轴或负载转轴上额外安装一个角度传感器例如电位器、霍尔角度传感器把模拟量接到 Arduino ADC再通过代码形成一个外部位置环。这样 Arduino 不仅能发目标角度还能读取实际角度并计算误差。第二种直接把普通位置舵机更换成带反馈的总线舵机。总线舵机可以通过串口通信向控制器上报角度、电压甚至负载状态。你在外部代码里读取到的是真实关节位置而不是靠推测。第三种在更高层应用里使用其他传感器推算末端姿态。比如做一个太阳能追光云台可以用光敏电阻阵列判断光照方向再驱动两个舵机去调整太阳能板朝向。此时你关心的不是舵机自身角度而是云台是否对准光源反馈信号来自光敏传感器而非舵机本身。这三种路径的难度和成本完全不同。对新手学习来说我建议先理解“外部反馈”和“执行器内部位置环”是两码事再根据实际项目决定是否要上传感器。4.3 PID 控制电机转速不是同一回事热词里经常出现“PID 闭环控制电机转速”。这个方向经常让人误解以为用 PID 调舵机是理所当然的进阶操作。PID 控制的前提是反馈量要能反映你的控制目标。控制电机转速时通常需要编码器或其他测速元件告诉我们当前转速控制器算出目标转速和实际转速的差值再调整输出。SG90 没有编码器输出也不适合作为一个需要连续调节转速的电机。它的控制目标是“到达某个角度并停住”而不是“以某个转速连续旋转”。如果你感兴趣的是电机转速闭环应该换一个带编码器的直流减速电机或者无刷电机和对应驱动方案。如果只是想让舵机转得更平滑、不抖动那要调整的方向通常是控制频率、电源质量、机械结构刚性以及脉宽变化速率而不是套一个 PID。下面是几个容易混淆的方案对比方案能否读取实际角度反馈来源典型场景SG90 直接使用不能内部电位器反馈仅用于自身定位小型云台、舵机小车转向、入门演示SG90 外接角度传感器能外部电位器、霍尔传感器等需要外部角度反馈的小型机构带编码器直流电机能测转速/位置编码器PID 电机调速、移动底盘串行总线舵机能舵机内部控制板通过总线上报机械臂、仿生机器人等多关节系统5. 踩坑清单这五件事会决定舵机能不能长期稳定动5.1 电流与共地SG90 出现抖动、乱转、Arduino 重启供电问题排在第一位。现象通常是这样的舵机空载时一切正常一装到机械结构上就开始抽搐或者带动机构转到一半时 Arduino 串口断开。因为舵机在启动和堵转瞬间需要明显更大的电流如果电源线路电阻大、稳压能力弱电压就会被瞬间拉低。解决方法是给舵机单独接一个功率足够的电源而不是把所有电流都压在 Arduino 板载 5V 引脚上。电源负极与 Arduino GND 必须相连。信号线只负责传递脉冲不负责驱动电机。5.2 堵转与发热舵机发出“咔咔咔”响声时其实是在告诉你我收到了目标信号也拼命想往那里转但机械上已经转不动了。堵转状态下舵机内部电机持续受力电流明显增大表现为发热、抖动、舵机臂来回寻找位置。长时间堵转会损坏塑料齿轮、电机电刷甚至烧坏内部控制电路。代码层面可以做的保护有两个方向。第一把角度和脉宽边界设置得比机械极限略小一点给舵机留出安全余量。第二在控制逻辑里避免让舵机长时间保持在一个不可达的位置比如加一个定时保护如果到了设定时间舵机还没有停止就主动停止发送继续逼近的信号。5.3 Servo 库占用 Timer1 的联动问题Arduino UNO 的 Servo 库默认会占用 Timer1。Timer1 同时负责 pin 9 和 pin 10 的analogWrite功能。所以当你用 Servo 库控制一个舵机又试图用analogWrite在 pin 9 或 pin 10 上输出另一路 PWM 时很可能发现那一路 PWM 不工作或者输出异常。这不是你接线错误而是定时器资源冲突。如果项目里同时需要舵机控制和普通 PWM 输出可以这样调整把analogWrite挪到其他支持硬件 PWM 的引脚上比如 pin 3、pin 5、pin 6。或者不要让 Servo 库和普通analogWrite共用一个定时器。5.4 一上来就用 analogWrite 驱动舵机还有一个高频误解以为舵机是 PWM 设备所以可以用analogWrite(pin, 90)来控制。analogWrite输出的 PWM 频率大约是 490Hz和舵机需要的 50Hz 完全不同。更重要的是analogWrite控制的是占空比也就是高电平在整个周期里的比例舵机控制需要的是高电平持续的具体时间。两者看着都是“方波”但信息编码方式不一样。驱动 SG90推荐方式是使用 Servo 库