实验10:舵机角度控制
这个实验做完你会得到什么
拖手机上的滑动条,舵机臂精确转到对应角度(0~180°)。再把它接上实验05 的光照数据, 就是一个指针式光照仪表。
电机是”转多快”,舵机是”转到哪” —— 机械臂、云台、开关阀门都靠它。
| 项目 | 说明 |
|---|---|
| 难度 | ★★★☆☆ |
| 用时 | 约 35 分钟 |
| 前置 | 实验09:PWM 电机 |
完成品工程:Arduino101Servo.aia
一、器材清单
| 器材 | 数量 | 说明 |
|---|---|---|
| Arduino 101 | 1 | |
| Seeed Grove 扩展板 | 1 | |
| SG90 或同类舵机 | 1 | 三线:棕/黑=GND,红=5V,橙/黄=信号 |
| 外接电源 | 1 | 多个舵机或大扭矩舵机时必须 |
二、接线
舵机信号线接一个支持 PWM 的数字引脚(Arduino 101 上只有 3、5、6、9 四个),
本文按 D5,代码里 Pin 填 5。
| 舵机线 | 接到 |
|---|---|
| 棕(或黑) | GND |
| 红 | 5V |
| 橙(或黄) | D5 |
固件:.ino 里把 SERVO 设为 ENABLED,其余 DISABLED。
舵机启动瞬间电流很大。只靠板子供电时,舵机一动板子可能掉电重启(手机突然断连)。 单个小舵机空载通常没问题,带负载或多个舵机就必须外接电源,注意共地 (外部电源的 GND 要和板子的 GND 连一起,否则信号没有参考电平,舵机会乱抖)。
三、界面组件
| 组件 | 命名 | 关键属性 |
|---|---|---|
| 滑动条 | 滑动条_角度 |
最小值 0、最大值 180、初始 90 |
| 标签 | 标签_角度 |
字号 32,文本「90°」 |
| 按钮 | 按钮_归中 |
文本「归中 90°」 |
| 按钮 | 按钮_扫一遍 |
文本「0→180 扫描」 |
| 计时器 | 计时器1 |
计时器启用取消勾选、间隔 30 |
| Arduino101Servo | Arduino101Servo1 |
不可见,BluetoothDevice = BluetoothLE1、Pin = 5 |
四、分步搭代码块
第 1 步:滑动条控角度
when 滑动条_角度.PositionChanged(thumbPosition) {
Arduino101Servo1.SetPosition(round(thumbPosition))
标签_角度.Text = join(round(thumbPosition), "°")
}
中途验证:拖滑动条,舵机臂跟着转;松手停在那个角度不动。
SetPosition的参数是角度 0~180。超出范围舵机会顶到机械限位、 持续嗡嗡响并发热,别硬撑。
第 2 步:确认到位
when Arduino101Servo1.PositionWritten(position) {
标签_状态.Text = join("已到位:", position, "°")
}
中途验证:每次转动后状态栏显示实际写入的角度。
这是写入回执,说明指令送到了板子;不代表舵机机械上已经转到位 (舵机没有位置反馈)。转动需要时间,大角度大约几百毫秒。
第 3 步:归中与自动扫描
global 当前角 = 90
global 方向 = 1
when 按钮_归中.Click() {
global 当前角 = 90
Arduino101Servo1.SetPosition(90)
滑动条_角度.ThumbPosition = 90
标签_角度.Text = "90°"
}
when 按钮_扫一遍.Click() {
计时器1.TimerEnabled = not 计时器1.TimerEnabled
}
when 计时器1.Timer() {
global 当前角 = 当前角 + 方向 * 5
if 当前角 >= 180 {
global 当前角 = 180
global 方向 = -1
} else if 当前角 <= 0 {
global 当前角 = 0
global 方向 = 1
}
Arduino101Servo1.SetPosition(当前角)
标签_角度.Text = join(当前角, "°")
}
中途验证:点「0→180 扫描」,舵机来回匀速摆动;再点一次停下。
计时器间隔 30 毫秒、每次走 5° —— 太快会让指令堆积在 BLE 通道里, 表现为舵机动作卡顿或滞后一大截。每一步都是一次 BLE 往返,别贪快。
第 4 步:连续旋转舵机(另一种舵机,可选)
舵机分两类:定位舵机(本文主角,转到指定角度停住)和连续旋转舵机 (改装过的,只能控制转速和方向,没有角度概念)。后者要用另一个方法:
when 滑动条_转速.PositionChanged(thumbPosition) {
Arduino101Servo1.SetPositionMicros(round(thumbPosition))
标签_状态.Text = join("转速参数:", round(thumbPosition))
}
加一个 滑动条_转速,最小值 1000、最大值 2000、初始 1500。
SetPositionMicros设置的是连续旋转舵机每转所需的时间(微秒)。 组件文档写明:1000 = 全速逆时针,2000 = 全速顺时针,中间值 1500 附近是停止。⚠️ 别拿它给定位舵机校准角度 —— 它不是”脉宽微调”接口。 定位舵机一律用
SetPosition(0~180)。
第 5 步:收尾
when Screen1.BackPressed() {
计时器1.TimerEnabled = false
BluetoothLE1.Disconnect()
}
五、排错表
| 现象 | 原因与处理 |
|---|---|
| 舵机不动 | ① 固件 SERVO 没 ENABLED;② Pin 不是支持 PWM 的引脚(Arduino 101 只有 3/5/6/9);③ 信号线接错(橙/黄才是信号) |
| 舵机一直抖 | 供电不足;或外部电源没和板子共地 |
| 一动板子就重启 | 舵机堵转/负载大,电流拉垮供电。接外部电源 |
| 转到端点后嗡嗡响发热 | 角度超出机械范围。回到 0~180 内 |
| 动作卡顿、滞后 | 指令发得太频繁。加大计时器间隔或步长 |
| 0° 和 180° 位置不准 | 舵机个体差异,机械上装配时错开一点补偿;或在代码里给角度加一个固定偏移 |
六、下一步
- 实验11:RGB LCD 显示屏 —— 把手机上的信息显示到硬件上
- 把 实验05 光照 的读数映射成角度,做一个指针式光照仪表
扫码添加客服咨询