控制FPV舵机云台到特定角度
312.7、控制 FPV 舵机云台到特定角度
#include <Servo.h> // 引入 Arduino Servo 库,供两个舵机对象使用
Servo myservo; // 创建第一个舵机对象,对应 D9 上的左右旋转轴
Servo myservo2; // 创建第二个舵机对象,对应 D10 上的上下俯仰轴
int pos = 0; // 保留上一版扫描程序的角度变量;当前活动代码没有使用它
void setup() { // 开发板上电或复位后执行一次
myservo.attach(9); // 将左右轴舵机对象关联到数字引脚 D9
myservo2.attach(10); // 将俯仰轴舵机对象关联到数字引脚 D10
} // setup() 初始化结束
void loop() { // 主循环会不断重复执行
myservo2.write(90); // 将俯仰轴的目标角度反复设为 90°;这是视频最后保留的测试值
delay(1000); // 每次写入相同目标后等待 1000 ms
/* 下面是被视频用块注释禁用的旧往返扫描代码
for (pos = 0; pos <= 180; pos += 1) { // 旧代码:让 pos 从 0 逐次增加到 180
myservo.write(pos); // 旧代码:向左右轴写入递增角度
myservo2.write(pos); // 旧代码:向俯仰轴写入递增角度
delay(15); // 旧代码:每增加 1°等待 15 ms
} // 旧代码:递增循环结束
for (pos = 180; pos >= 0; pos -= 1) { // 旧代码:让 pos 从 180 逐次减小到 0
myservo.write(pos); // 旧代码:向左右轴写入递减角度
myservo2.write(pos); // 旧代码:向俯仰轴写入递减角度
delay(15); // 旧代码:每减小 1°等待 15 ms
} // 旧代码:递减循环结束
*/ // 块注释到此结束,上述旧扫描代码不会编译或运行
} // loop() 本轮结束,随后回到开头继续执行
一、控制舵机转动到指定角度
本节不再让云台连续往返扫描,而是依次给 D9、D10 两个舵机写入 0°、90°或 180°,观察真实姿态,再重新安装舵盘,使“程序角度”和“机构方向”建立明确对应关系。页首代码是视频末段最终可见的草图状态:活动代码只让 myservo2 保持 90°,原扫描程序仍留在文件中但已被 /* ... */ 禁用。
这是一节机械零位与方向校准课,不是自动追光课。视频没有读取光敏传感器,也没有根据光照误差计算目标角度;太阳能板和追光控制只是后续用途。
1.1 上节内容回顾
上一节把下方左右轴信号接到 D9,把上方俯仰轴信号接到 D10。本节最终采用的视频观察方向和角度约定为:
| 舵机对象与引脚 | 机械作用 | 本节最终约定 |
|---|---|---|
myservo / D9 | 左右旋转(pan) | 左侧约为 0°,中间约为 90°,右侧约为 180° |
myservo2 / D10 | 上下俯仰(tilt) | 课件方向图为 0°朝上、90°水平、180°朝下 |
视频开头的课件一度把下轴画成“左 180°、右 0°”,讲解也先按这个方向描述;实际上传 180°、0°并观察机构后,教师在草图顶部重新备注为“左边 0 度极限值,右边 180 度极限值”。因此本节应记录实物测试后确定的最终约定,不能同时把两组互相矛盾的左右关系都当成结论。
同样,口述中曾把俯仰轴 0°与“平行”连在一起,但课件方向图和末段实测把 90°描述为“平”的位置。本节按最终演示记录为 0°朝上、90°水平、180°朝下;这只是该套支架在当前观察方向和舵盘齿位下的项目坐标,不是 SG90 的通用空间方向。
所谓“0°、90°、180°”首先是 Servo.write() 的目标值。Arduino 只知道自己最后写了什么,并不知道支架是否真的到位;Servo 官方 API 也明确说明,读取接口返回的是最后的设定值,不是舵机反馈的真实物理方向。安装方向、花键齿位、个体误差、负载和机械限位都会改变最终姿态。
1.2 转动舵机代码
视频先把上一版的两个往返循环包在多行注释中,再在 loop() 顶部逐个写入固定角度。
//是单行注释标记,从它开始直到该行末尾都不参与编译。/*开始块注释,直到后面的*/才结束,可以跨越多行。- 被块注释包住的
for、write()和delay()都只是留在编辑器里的旧文本,不会进入可执行逻辑。 - C/C++ 块注释不能依靠另一组嵌套的
/* ... */来分层;修改大段代码时应核对起止位置,避免误把后续业务代码一起禁用。
第 312 节开头显示的旧扫描块,在正向和反向循环中都已经含有 myservo2.write(pos)。这与第 311 节视频最终画面“第二只舵机只在正向循环被写入”不同,说明两节之间发生过未展示的代码修改。页首按第 312 节实际画面保留该块,但不能据此倒推或改写第 311 节源码。
视频各阶段实际测试的活动语句如下:
| 阶段 | 活动角度语句 | 用途与画面结论 |
|---|---|---|
| 下轴测试 1 | myservo.write(180) | 观察 D9 舵机的一端姿态,并调整未锁紧的下部连接 |
| 下轴测试 2 | myservo.write(0) | 观察另一端,最终确认当前观察方向为左 0°、右 180° |
| 下轴测试 3 | myservo.write(90) | 验证下轴是否大致停在左右中间 |
| 上轴测试 1 | myservo2.write(0) | 找到 D10 舵机的命令零位,并重新安装舵盘校准支架姿态 |
| 上轴测试 2 | myservo2.write(90) | 校准后验证平台的水平姿态;这是视频最后可见并保留的代码 |
| 上轴 180° | 视频只口述“180 就往下” | 没有看到把活动语句改成 180 并重新上传,不能写成已完成的烧录测试 |
delay(1000) 只让 loop() 每隔约 1 秒再次写入同一个目标,不表示“舵机一定用 1 秒转完”,也不是保持角度所必需。Servo 库会在后台继续输出最近一次设定所对应的控制脉冲;即使程序正停在 delay() 中,舵机信号也不会因此消失。
最终草图虽然还执行 myservo.attach(9),但活动循环没有再调用 myservo.write(...)。AVR 版 Servo 库在对象创建时保存默认的 1500 µs 脉宽,attach() 后即按该默认值输出,所以重新上传或复位后,D9 舵机不会“记住上一份程序写过的 90°”;它只是接收到接近中位的默认脉宽。默认 1500 µs 与 write(90) 的内部映射也不必恰好完全相同,更不能据此认定下轴已经精确校准。
1.3 控制舵机转动示例
1.3.1 校准下方左右轴(D9)
视频中的操作顺序是:
- 保留
myservo.attach(9),把旧往返扫描整块注释掉。 - 写入
myservo.write(180)和delay(1000),选择当时的串口并上传。 - 观察 180°命令下的下轴位置。由于底部连接此前没有完全锁紧,视频转动并放置底部机构,使它与预期的一端方向对齐。
- 把目标值改为 0°并再次上传,观察机构转到另一端。
- 依据实物方向,最终在代码顶部备注“左 0°、右 180°”。
- 再写入 90°并上传,确认下轴大致位于左右行程的中间。
原始笔记中的“控制九号银角”是“控制 9 号引脚舵机”的识别错误。D9 是信号脚编号;180、0、90 是写给 myservo 的目标角度值,两者不能混为一谈。
1.3.2 这里校准的究竟是什么
舵机输出轴和舵盘通过细小花键啮合。把舵盘拔起、旋转若干齿再压回去,相当于改变“程序角度”与“支架机械方向”之间的固定偏移:
程序写入角度 → Servo 库产生脉冲 → 舵机输出轴到达目标附近
↓
舵盘安装齿位决定支架朝向
↓
云台最终呈现左/中/右或上/平/下
这种操作不会改变 Servo 库的 0~180 映射,也不会改变舵机内部电位器的电气零点;它只是重新选择舵盘装在输出轴上的机械齿位。花键只能按离散齿距调整,因此不一定能让平台达到完全精确的几何水平,后续还可能需要在软件中使用安全的角度偏移或范围限制,但本节没有展示相应代码,不能在页首源码中擅自补写。
1.4 内容修改
本节最终确定下轴以 D9 控制,并在当前观察方向采用“左 0°、中 90°、右 180°”的项目约定。0°和 180°本身并不天然代表左或右:把舵机翻转安装、把移动件与固定件互换,或者从机构另一面观察,肉眼方向都可能反过来。
教师说“反过来也可以”,应理解为项目可以重新定义方向或在后续控制逻辑中做反向映射,而不是同一套机械安装下 write(0) 和 write(180) 会任意互换。为了让传感器误差计算和后续调试一致,方向一旦确定,就应在整个项目中保持同一坐标约定。
另外,0°和 180°是 Servo 库允许写入的端点命令,不等于云台一定拥有完整、安全的 180°机械行程。Arduino 官方文档提醒,驱动舵机越过真实端点会出现持续低吼/嗡鸣和高电流状态。若支架在到达命令端点前已经碰撞,应立即断电,把项目可用范围收窄;不能为了让标注“对上”而让舵机长期顶住机械限位。
1.5 控制舵机转动示例
1.5.1 校准上方俯仰轴(D10)
视频先把活动语句改为 myservo2.write(0) 并上传,观察上方平台在命令零位时的实际姿态。随后用一次“错误位置”演示说明如何重新安装舵盘,使零位与项目需要的机械方向一致。结合画面和必要的安全修正,可靠步骤应理解为:
- 在平台无太阳能板负载、周围无遮挡时写入待校准角度,并让舵机到达该目标。
- 断开舵机电源;视频也明确提醒“电要下掉”。不能带电强扭输出轴。
- 用合适的十字螺丝刀卸下舵盘中心的短螺钉,收好螺钉。
- 让舵盘完全脱离舵机输出轴花键。需要调整的是舵盘/支架相对齿位,不是用手硬拧舵机轴和内部齿轮。
- 在输出轴保持已知命令位置的前提下,把平台移动到希望定义的机械姿态,再把舵盘以最接近的齿位压回花键。
- 用原来的匹配短螺钉固定舵盘;不要用过长安装螺钉替代,以免拧入过深损坏舵机。
- 手和工具退出运动范围后重新上电,先验证该校准角度,再小范围测试附近角度。
视频末段把活动语句改为 myservo2.write(90),上传后把此姿态描述为“平”。随后口头说明 180°应继续向下,但没有显示改成 180°并重新烧录,因此验收结论只能写到 90°实测。若要测试 180°,仍须先确认平台、支架、舵机线和未来太阳能板都不会在途中碰撞或拉紧。
1.5.2 固定与后续应用
- 舵盘必须靠正确花键啮合和中心短螺钉固定,不能用胶水代替中心螺钉,也不能让胶进入输出轴或转动关节。
- 教师所说的打胶或拧螺丝,是在方向校准完成后把云台底座固定到项目结构上的可选做法。固定前要再次确认底座哪一侧应保持不动。
- 使用热熔胶枪时应断电,避开舵机外壳接缝、导线、连接器和活动轴;热胶也不适合承担长期反复摆动的精密定位。
- 安装太阳能板后负载和重心都会变化。空载时不碰撞、不抖动,并不能证明负载后仍安全;应重新检查供电压降、保持力、线缆余量和角度范围。
- 真正追光还需要两个方向的光照误差输入和限位逻辑。本节只建立角度坐标与机械姿态的对应关系。
1.6 校准完成后的验收
| 检查项 | 合格表现 | 异常时处理 |
|---|---|---|
| 下轴中位 | 写入 90°后大致位于左右行程中间 | 断电后重新选择舵盘齿位,不带电硬扭 |
| 上轴水平 | 写入 90°后平台符合本项目定义的水平姿态 | 重新校准舵盘;小误差留给后续软件偏移处理 |
| 两端安全 | 接近项目允许端点时无碰撞、无持续嗡鸣、线缆不绷紧 | 立即断电并缩小可用角度范围 |
| 紧固可靠 | 舵盘中心短螺钉和底座紧固件到位,机构无明显空转 | 使用匹配紧固件重装,不用胶堵住转轴 |
| 上电行为 | 机构只小幅回到目标,没有突然撞击支架 | 检查初始目标、舵盘齿位和启动时的默认位置 |
| 负载复测 | 加装太阳能板后仍能稳定到位,UNO 不复位 | 检查重心、供电能力、共地和机械阻力 |
核对依据
- 本地
videos/312.7、控制FPV舵机云台到特定角度.mp4:逐段核对旧扫描代码的块注释、D9 的 180°/0°/90°测试、最终“左 0°/右 180°”备注、D10 的 0°校准、舵盘拆装以及末段myservo2.write(90);确认视频没有显示把俯仰轴改为 180°并再次上传。 - 本地
transcripts/312.7、控制FPV舵机云台到特定角度.txt与.srt:核对讲解顺序、D9/D10 分工、1 秒延时、断电提醒、平台姿态和后续安装太阳能板的用途;结合画面纠正“九号银角”“干信号”等识别错误及前后方向冲突。 - Arduino Servo 库官方 API:核对
attach()、write()、设定值与真实物理方向的区别,以及超过真实机械端点会形成高电流状态的警告。 - Arduino Servo 库头文件与AVR 实现:核对 Servo 对象保存最近脉宽并在后台持续产生脉冲、默认 1500 µs 初值,以及
delay(1000)不会停止舵机控制信号。 - Adafruit《Mini Pan-Tilt Kit Assembly》官方装配说明:其双轴支架结构与本课程相近,用于交叉核对舵盘齿位校准、中心短螺钉、俯仰行程检查和“行程不合适时脱开舵盘后旋转重装”的机械处理原则;课程套件未标明品牌,本文不把它认定为同一产品。