舵机——让 Arduino 动起来

前面我们学了光敏电阻,让 Arduino 能感知光线强弱。现在给它装上"肌肉"------舵机,让它能转动、摆动、做动作!

学完这篇,你会完成:

  • 认识舵机:了解舵机的工作原理和类型
  • 控制舵机角度 :掌握 Servo 库的使用
  • 综合项目:自动感应垃圾桶:手靠近自动开盖

一、舵机是什么?

舵机(Servo Motor)是一种可以精确控制转动角度 的电机。普通舵机的转动范围是 0° ~ 180°,连续旋转舵机可以 360° 不停转。

核心原理

舵机内部有一个电位器 (可变电阻)和一个控制电路

  • 控制电路接收 PWM 信号
  • 电位器反馈当前角度
  • 控制电路比较目标角度和实际角度,驱动电机转动到目标位置

舵机有三根线:红(VCC)棕/黑(GND)橙/黄(信号)

常见类型
类型 特点 适用场景
SG90(9g 舵机) 小巧、便宜、扭矩小 小型机器人、云台
MG90S(金属齿轮) 扭矩大、耐用 机械臂、小车转向
MG996R(大扭矩) 扭矩 15kg·cm 大型机械臂、四足机器人
连续旋转舵机 可 360° 旋转 小车驱动、卷线器
SG90 参数
参数 数值
工作电压 4.8V ~ 6V
扭矩 1.8 kg·cm(4.8V)
转动范围 0° ~ 180°
响应速度 0.12 秒/60°
重量 9g

二、PWM 信号

舵机通过 PWM(脉冲宽度调制) 信号控制角度。

PWM 原理
  • 周期:20ms(50Hz)
  • 高电平持续时间决定角度:
高电平时间 对应角度
0.5ms
1.0ms 45°
1.5ms 90°
2.0ms 135°
2.5ms 180°

Arduino 的 Servo 库会自动处理 PWM 信号,你只需要调用 write(angle) 即可。


三、接线方式

舵机线色 接法
红(VCC) 5V(大扭矩舵机建议外接电源)
棕/黑(GND) GND(必须与 Arduino 共地)
橙/黄(信号) 任意数字引脚(推荐 D9)

重要提示 :SG90 可以直接用 Arduino 5V 供电,但 MG996R 等大扭矩舵机启动电流可达 1A 以上,Arduino 的 5V 引脚最大只能提供 500mA,必须外接电源,否则会导致 Arduino 重启或损坏。


四、实验一:基础控制

让舵机从 0° 转到 180°,再转回来。

复制代码
#include <Servo.h>

Servo myservo;  // 创建舵机对象
#define SERVO_PIN 9

void setup() {
  myservo.attach(SERVO_PIN);  // 绑定引脚
}

void loop() {
  // 从 0° 转到 180°
  for (int angle = 0; angle <= 180; angle++) {
    myservo.write(angle);
    delay(15);  // 等待舵机转动到位
  }
  
  // 从 180° 转回 0°
  for (int angle = 180; angle >= 0; angle--) {
    myservo.write(angle);
    delay(15);
  }
}
代码解读
  • #include <Servo.h>:引入舵机库
  • Servo myservo:创建舵机对象
  • myservo.attach(pin):绑定信号引脚
  • myservo.write(angle):设置目标角度(0~180)
  • delay(15):SG90 转 60° 需要 0.12 秒,转 1° 约 2ms,15ms 足够到位

五、实验二:串口控制

通过串口输入角度,控制舵机转动到指定位置。

复制代码
#include <Servo.h>

Servo myservo;
#define SERVO_PIN 9

void setup() {
  Serial.begin(9600);
  myservo.attach(SERVO_PIN);
  Serial.println("Servo Ready! Enter angle (0-180):");
}

void loop() {
  if (Serial.available()) {
    int angle = Serial.parseInt();  // 读取串口输入的角度
    
    if (angle >= 0 && angle <= 180) {
      myservo.write(angle);
      Serial.print("Angle set to: ");
      Serial.println(angle);
    } else {
      Serial.println("Invalid angle! Enter 0-180.");
    }
  }
}
测试方法
  1. 上传代码后打开串口监视器
  2. 输入角度值(如 90),按回车
  3. 舵机转动到指定角度

六、实验三:电位器控制

用旋钮(电位器)控制舵机角度,实现"指哪打哪"。

所需元件
  • Arduino Uno
  • SG90 舵机
  • 10kΩ 电位器
  • 面包板 + 杜邦线
接线
元件 接法
舵机信号 D9
舵机 VCC 5V
舵机 GND GND
电位器两端 5V + GND
电位器中间 A0
代码
复制代码
#include <Servo.h>

Servo myservo;
#define SERVO_PIN 9
#define POT_PIN A0

void setup() {
  myservo.attach(SERVO_PIN);
  Serial.begin(9600);
}

void loop() {
  // 读取电位器值(0~1023)
  int potValue = analogRead(POT_PIN);
  
  // 映射到舵机角度(0~180)
  int angle = map(potValue, 0, 1023, 0, 180);
  
  // 设置舵机角度
  myservo.write(angle);
  
  Serial.print("Pot: ");
  Serial.print(potValue);
  Serial.print(" -> Angle: ");
  Serial.println(angle);
  
  delay(15);
}
效果

旋转电位器,舵机跟随转动,角度完全同步。


七、综合项目:自动感应垃圾桶

手靠近时自动开盖,离开后自动关盖。

所需元件
  • Arduino Uno
  • SG90 舵机
  • HC-SR04 超声波传感器
  • 面包板 + 杜邦线
接线
元件 接法
舵机信号 D9
舵机 VCC 5V
舵机 GND GND
超声波 Trig D2
超声波 Echo D3
超声波 VCC 5V
超声波 GND GND
代码
复制代码
#include <Servo.h>

Servo myservo;
#define SERVO_PIN 9
#define TRIG_PIN 2
#define ECHO_PIN 3
#define OPEN_ANGLE 120    // 开盖角度
#define CLOSE_ANGLE 0     // 关盖角度
#define DISTANCE_THRESHOLD 10  // 触发距离(cm)

void setup() {
  myservo.attach(SERVO_PIN);
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  Serial.begin(9600);
  myservo.write(CLOSE_ANGLE);  // 初始状态:关盖
  delay(500);
}

// 测量距离(cm)
float getDistance() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  
  long duration = pulseIn(ECHO_PIN, HIGH);
  return duration * 0.034 / 2;
}

void loop() {
  float distance = getDistance();
  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.println(" cm");
  
  if (distance < DISTANCE_THRESHOLD && distance > 0) {
    // 手靠近,开盖
    myservo.write(OPEN_ANGLE);
    Serial.println("Open!");
  } else {
    // 手离开,关盖
    myservo.write(CLOSE_ANGLE);
    Serial.println("Close!");
  }
  
  delay(100);
}
效果
  • 手靠近超声波传感器(10cm 以内)→ 舵机转动到 120°,开盖
  • 手离开 → 舵机转回 0°,关盖

八、进阶:平滑转动

直接 write() 会让舵机"瞬间"转到目标角度,看起来比较生硬。可以用插值实现平滑转动。

复制代码
#include <Servo.h>

Servo myservo;
#define SERVO_PIN 9

int currentAngle = 0;
int targetAngle = 0;

void setup() {
  myservo.attach(SERVO_PIN);
  Serial.begin(9600);
}

void loop() {
  if (Serial.available()) {
    targetAngle = Serial.parseInt();
    if (targetAngle < 0) targetAngle = 0;
    if (targetAngle > 180) targetAngle = 180;
  }
  
  // 平滑插值:每次向目标角度靠近 5°
  if (currentAngle != targetAngle) {
    if (currentAngle < targetAngle) {
      currentAngle += 5;
      if (currentAngle > targetAngle) currentAngle = targetAngle;
    } else {
      currentAngle -= 5;
      if (currentAngle < targetAngle) currentAngle = targetAngle;
    }
    myservo.write(currentAngle);
    delay(20);
  }
}
效果

舵机不再"瞬移",而是匀速平滑地转动到目标角度,看起来更自然。


九、常见问题

问题 解决方法
舵机抖动/不动 检查供电是否足够,大扭矩舵机必须外接电源
舵机转动时有异响 检查是否被机械结构卡住,或角度超出范围
Arduino 重启 舵机启动电流过大,Arduino 供电不足,必须外接电源
舵机角度不准 不同舵机的 PWM 脉宽有差异,可用 attach(pin, min, max) 校准
舵机一直转不停 可能是连续旋转舵机,或信号线接触不良
舵机角度校准
复制代码
// 校准 PWM 脉宽范围(单位:微秒)
myservo.attach(SERVO_PIN, 500, 2500);
// 500 = 0° 对应的高电平时间
// 2500 = 180° 对应的高电平时间

不同品牌舵机的脉宽范围不同,SG90 通常是 500~2500μs,MG996R 可能是 500~2400μs。


十、舵机供电方案

方案一:Arduino 5V 直接供电(仅 SG90)
  • 适合 1~2 个 SG90 舵机
  • 简单方便,但电流有限
方案二:外接 5V 电源(推荐)
  • 适合多个舵机或大扭矩舵机

  • 必须共地:外接电源的 GND 与 Arduino 的 GND 连接

    外接 5V 电源
    +5V ──→ 舵机 VCC
    GND ──→ 舵机 GND ──→ Arduino GND(共地!)

方案三:电池供电
  • 4 节 AA 电池(6V)或锂电池(7.4V)+ 降压模块
  • 适合移动机器人项目

十一、本篇小结

回顾一下今天学到的核心知识:

  • 舵机原理:通过 PWM 信号控制转动角度,内部电位器反馈位置
  • PWM 信号:周期 20ms,高电平 0.5~2.5ms 对应 0°~180°
  • Servoattach() 绑定引脚,write() 设置角度
  • 供电注意:SG90 可用 Arduino 供电,大扭矩舵机必须外接电源
  • 共地原则:外接电源的 GND 必须与 Arduino 的 GND 连接
  • 综合项目:串口控制 + 电位器控制 + 自动感应垃圾桶
  • 平滑转动:用插值实现匀速转动,避免"瞬移"

舵机是机器人项目的核心执行元件,广泛应用于机械臂、云台、小车转向等场景。下一篇,我们学习直流电机 + L298N 驱动模块------让 Arduino 驱动小车跑起来!

相关推荐
qq_344920561 小时前
Qt 鼠标双击QLabel全屏显示图像
c++·qt
周洲08302 小时前
STM32 SPI 通信实战|高速通信、片选、数据收发
stm32·嵌入式硬件
POMAGTOR2 小时前
【5G设备POGOPIN连接器 高频弹簧针通信连接器件】
嵌入式硬件·5g·机器人
意法半导体STM322 小时前
【官方原创】LAT1709STM32C5硬件CRC值的计算话题
stm32·单片机·嵌入式硬件·mcu·crc·微控制器·stm32c5
f狐0狸x2 小时前
【C++修炼之路】C++继承的探索
c++·继承
虚无的纽扣2 小时前
【C++】C++11的魔法:不止右值引用,C++11赋予的编程神力
c++
新思维软件2 小时前
基于 STM32 的快递柜自动存取系统设计与实现(项目编号 X604041)
stm32·嵌入式硬件·物联网·物联网开发
xx~t2 小时前
嵌入式——ARM——汇编2
linux·汇编·arm开发·嵌入式硬件·启动代码
码匠许师傅2 小时前
【C++三方组件】RE2:工业级正则的安全与性能
c++