
1. 初识Arduino Uno与SG90舵机第一次拿到Arduino Uno和SG90舵机时我完全被这个小家伙迷住了。Arduino Uno就像是一个万能遥控器而SG90舵机则像是一个听话的小手臂让它转哪儿就转哪儿。这种通过代码控制物理世界的感觉简直太神奇了SG90舵机是一种微型伺服电机它最大的特点就是能够精确控制旋转角度。市面上常见的SG90有两种规格180度标准舵机和360度连续旋转舵机。我们今天要玩的是180度版本它有三根引线红色线接5V电源棕色线接地(GND)橙色线信号线(接数字引脚)这个小东西虽然看起来简单但性能可不含糊。在4.8V电压下它的无负载转速能达到0.12秒/60度堵转扭矩有1.2-1.4公斤/厘米。这意味着它不仅能快速响应还能带动一定的负载。我实测用它来控制一个小型垃圾桶盖完全没问题。说到Arduino Uno它是最经典的入门级开发板。板载ATmega328P微控制器14个数字输入/输出引脚(其中6个可用于PWM输出)6个模拟输入非常适合用来学习舵机控制。特别提醒新手朋友Uno的5V引脚输出电流有限如果同时控制多个舵机建议使用外部电源供电否则可能会出现舵机抖动或板子重启的情况。2. Servo库的六大核心函数详解2.1 attach() - 舵机的启动键attach()函数就像是给舵机按下了启动键。我第一次使用时犯了个错误直接把舵机信号线接到了任意数字引脚上结果舵机纹丝不动。后来才知道在Arduino 0016及之前的版本中Servo库仅支持第9和第10引脚。现代版本的Servo库已经解除了这个限制但为了兼容性我还是习惯使用9或10号引脚。attach()有两种用法myservo.attach(9); // 简单用法指定信号引脚 myservo.attach(9, 544, 2400); // 高级用法可自定义脉宽范围第二个参数544和第三个参数2400分别代表0度和180度时的脉冲宽度(单位微秒)。有些特殊舵机可能需要调整这些值我遇到过一款需要设置为500-2500的舵机这时候就需要用第二种写法了。2.2 write() - 角度控制的核心write()函数是控制舵机角度最直接的方法。它的参数范围是0-180对应舵机的旋转角度。但要注意这个角度并非绝对精确不同品牌的舵机可能会有±10度的误差。我在项目中常用这种方式myservo.write(90); // 让舵机转到中间位置 delay(1000); // 等待1秒 myservo.write(0); // 转到0度位置实际测试中发现如果连续发送write()指令而没有适当延迟舵机可能会跳过某些中间位置。这是因为舵机需要时间完成机械运动建议每次角度变化后至少延迟15ms。2.3 writeMicroseconds() - 精准控制的秘密武器当write()的精度不能满足需求时writeMicroseconds()就派上用场了。它直接控制脉冲宽度理论上可以实现更精确的角度控制。标准舵机的脉宽范围1000μs完全逆时针(0度)1500μs中间位置(90度)2000μs完全顺时针(180度)但实际使用中发现很多舵机的有效范围更宽可以达到500-2500μs。我建议先用write()大致定位再用writeMicroseconds()微调myservo.write(90); // 先转到中间位置 delay(500); myservo.writeMicroseconds(1600); // 微调到约100度位置2.4 read() - 获取当前角度read()函数可以返回最后一次通过write()设置的角度值。注意它读取的是代码发送的指令值而不是舵机实际的物理位置。如果舵机被外力阻挡read()返回的值可能与实际位置不符。一个实用的技巧是结合read()和write()实现相对运动int currentPos myservo.read(); myservo.write(currentPos 10); // 在当前基础上增加10度2.5 attached() - 连接状态检测attached()用来检查舵机是否已经通过attach()连接到某个引脚。在复杂的项目中这个函数很有用if(myservo.attached()) { // 舵机已连接可以安全操作 } else { Serial.println(舵机未连接); }2.6 detach() - 释放引脚资源detach()函数用于断开舵机连接释放引脚。这在需要动态切换引脚用途时特别有用。需要注意的是在Uno上使用Servo库会影响9和10引脚的PWM功能即使没有连接舵机也是如此。调用detach()后这些引脚才能恢复正常的PWM功能。3. 实战项目自感应开盖垃圾桶3.1 硬件组装让我们把这些知识应用到一个实际项目中 - 制作一个自动感应的智能垃圾桶。你需要准备Arduino Uno ×1SG90舵机 ×1HC-SR04超声波模块 ×1小垃圾桶 ×1杜邦线若干接线方式舵机红线接5V棕线接GND橙线接数字5引脚超声波模块VCC接5VGND接GNDTrig接D8Echo接D2我建议使用面包板进行连接并用热熔胶固定舵机。测试时发现直接用舵机带动垃圾桶盖可能会扭矩不足可以加装一个延长臂来增加力矩。3.2 代码实现#include Servo.h #define Echo D2 #define Trig D8 #define PIN_SERVO D5 Servo myServo; void initSensor() { pinMode(Echo, INPUT); pinMode(Trig, OUTPUT); } long getDistance() { digitalWrite(Trig, LOW); delayMicroseconds(10); digitalWrite(Trig, HIGH); delayMicroseconds(10); digitalWrite(Trig, LOW); return pulseIn(Echo, HIGH) / 58; // 将回波时间转换为厘米 } void setup() { initSensor(); myServo.attach(PIN_SERVO); myServo.write(150); // 初始位置关闭状态 Serial.begin(115200); } void loop() { long distance getDistance(); Serial.print(距离); Serial.print(distance); Serial.println(cm); if(distance 28) { // 当手接近时 myServo.write(10); // 打开盖子 } else if(distance 50) { // 手离开后 myServo.write(150); // 关闭盖子 } delay(500); }3.3 调试技巧在实际调试中我发现几个常见问题及解决方法舵机抖动通常是电源供电不足导致建议使用外部电源或增加大容量电容开盖角度不合适调整write()中的角度值我测试发现10度和150度比较适合我的垃圾桶感应不灵敏调整超声波的距离阈值我的设置是28cm触发开盖50cm以上关盖为了让动作更平滑可以改用for循环实现渐进式运动void smoothMove(int from, int to) { int step (from to) ? 1 : -1; for(int posfrom; pos!to; posstep) { myServo.write(pos); delay(15); } }4. 进阶技巧与常见问题4.1 多舵机控制虽然Servo库理论上支持Uno控制12个舵机但实际使用时受限于电源和引脚我建议不超过3个。控制多个舵机时务必注意使用独立电源供电所有GND必须共地错开舵机动作时间避免同时启动造成电流过大示例代码#include Servo.h Servo servo1, servo2; void setup() { servo1.attach(9); servo2.attach(10); } void loop() { servo1.write(90); delay(1000); servo2.write(90); delay(1000); }4.2 省电优化对于电池供电的项目可以通过detach()在不使用时断开舵机节省电力void openLid() { if(!myServo.attached()) myServo.attach(5); myServo.write(10); delay(1000); myServo.detach(); }4.3 常见故障排查舵机不转检查接线是否正确确认attach()的引脚号正确测量电源电压是否达到4.8-6V舵机发热严重可能是被堵转检查机械结构是否卡住避免长时间让舵机保持在极限位置角度不准尝试校准脉宽范围检查电源稳定性我在一个天气站项目中使用SG90控制风向标时发现低温环境下舵机会变慢。后来通过增加writeMicroseconds()的脉宽值解决了这个问题。这说明实际应用中需要考虑环境因素的影响。