模块熟悉
第 18 课:舵机——让角度转起来
第一次做"模拟输出"——不是开或关,而是"转到 37 度"
我是吴老师。这节课是「输出」这一侧的分界线。
你回想一下前面那些课,凡是让东西"动起来"的,全都是同一个套路:灯要么亮要么灭,蜂鸣器要么响要么不响。它们只有两种状态——你从来没办法跟板子说"亮 37%"这种话,因为做不到。
但从舵机开始,事情变了。你要说的是:"转到 37 度。"
一个具体的、连续的、有零有整的角度。 这是你这门课第一次做模拟输出。第 10 课你学过模拟输入(拧旋钮读一个连续的值),今天我们在输出的方向上,把同一件事再做一遍。
一、先认识它
舵机就是一个能转到指定角度的小马达。
它长得像个蓝色的小方块,顶上伸出来一个塑料小摇臂(叫"舵盘")。你让它转 30 度,它就转 30 度;你让它转 150 度,它就转 150 度。它不会转圈,只在一个扇形范围里来回走——普通舵机的范围是 0 ~ 180 度。
套件里这颗是 MG90S,金属齿轮的小舵机,力气不大但很耐用,做云台、做机械臂、做指针表盘都够用。
说个有意思的事:舵机怎么知道"自己转到几度了"?
它内部除了电机和齿轮,还有一个小电位器——对,就是你第 10 课拧的那个东西。电机一转,它跟着转,舵机里的电路就靠它的电压变化知道"我现在到哪了";没到目标角度,就继续使劲。
你发现没有——这是一个做在舵机内部的、小小的闭环(第 9 课那个"传感器 → 判断 → 执行器")。你现在不用记,知道有这回事就行。
二、它要的信号:还是"快速开关"
板子怎么表达"转到 37 度"?
它没法直接吐出一个中间值的电压。引脚只会两件事:输出高电平(3.3V)或者低电平(0V)。 没有"输出 1.2V"这个选项。
这块 C3 芯片里没有 DAC 这个部件(别的型号的 ESP32 有些带),所以它天生就不会"输出中间电压"。你可以翻一下你板子的引脚图确认——查一遍比我告诉你更牢。
那怎么办?用"快速开关"来假装。
这个比喻你一定要记住:
你家老式的水龙头,只有"全开"和"全关",拧不到中间。 现在我需要"半桶水",怎么办?我快速开关——开一秒、关一秒、开一秒、关一秒……接在水桶里的水,平均下来正好是一半。
我没法把水龙头定在中间,但我可以让它"一半时间开着"。
电也是一样的:让引脚快速地在 3.3V 和 0V 之间切,切得够快,后面的东西感受到的就是一个"中间值"。
这招的正式名字叫 PWM(脉冲宽度调制,Pulse Width Modulation)。那个"开的时间占整体的比例",叫占空比(duty cycle)。
你看图上那三条波浪线:同一个开关动作,开的时间越长,平均下来就越"高"。灯是这样变亮的,舵机是这样变角度的——同一个道理。
舵机数的是"每次开多久"
不过舵机有个小脾气:它不看"平均多少",它看"每次开的那一下有多长"。
具体是这样:
| 每次"开"多久 | 舵机转到 |
|---|---|
| 1 毫秒 | 0° |
| 1.5 毫秒 | 90° |
| 2 毫秒 | 180° |
而且它要求这个开关动作每秒重复 50 次(也就是每 20 毫秒来一轮)。
你算一下:20 毫秒里开 1.5 毫秒,占空比是 7.5%。所以它说到底还是占空比,只不过数值很小,而且是固定的频率、只有"开多久"在变。
这三个数字(1ms / 1.5ms / 2ms)你不用背——库会帮你把"角度"换算成脉冲宽度,你只管写
write(90)。但你得知道底下发生了这么一回事,不然以后碰到舵机抖动、嗡嗡响,你就不知道该往哪儿想。
三、接线:橙、红、棕
舵机的线是三根并排的,颜色是固定的,认颜色就行:
| 线色 | 是什么 | 接到 |
|---|---|---|
| 橙 | 信号 | GPIO7 |
| 红 | 电源 | 独立 5V 的正极 |
| 棕 | 地 | GND(要和板子共地) |
顺序就是橙 / 红 / 棕,顺着线看,一根挨一根。
注意:接错是有区别的。 橙线(信号)接错一般不会烧,顶多不动;红线和棕线接反(电源接反)会烧——这是要命的那个。所以插之前先看颜色,别凭手感,舵机那个插头长得很对称,反着也能插进去。
顺带说一句:
GPIO7只是我给你的建议(图形化平台里舵机的默认脚也是它)。信号线接哪个 GPIO 都行,只有电源那两根不能乱接。
四、最大的坑:电不能从板子上取
这是这节课最重要的内容。
先把现象告诉你,你等下会亲眼看到:你把舵机的红线接到板子的 3.3V 上,一上电——舵机抖一下,然后串口监视器里又打印了一遍启动信息。
板子重启了。
我知道你在想什么:"是不是我程序写错了?是不是板子坏了?" 都不是。
为什么
舵机里面是个电机。电机的脾气是——不转的时候不太耗电,一启动那一下特别费电。 那一下能有多大?几百毫安;要是被东西挡住转不动,一安培都打不住。 没概念的话这么比:手机充电器一般也就输出 1~2 安培。
而板子上那个 3.3V 是从哪来的?USB 的 5V 经过一颗很小的稳压芯片变出来的。 那颗芯片设计上只够给主控、传感器、LED 这些"细活"用,就是几十毫安的量级。
你让舵机从这儿取电,等于让一根台灯的电线去带一台空调。
还记得吗——夏天一开空调,家里的灯会闪一下。 那就是大功率电器启动的瞬间把电压拉下去了。板子这儿发生的是同一件事,只是它更脆弱:电压一被拉低,欠压保护就动作,直接重启。
配张图看得更清楚:
图里那根灰色的、从电池盒一路绕到板子上的线,就是"共地"——下一段专门讲它。
正确做法
舵机的电,单独给它。
按推荐顺序,你有这几个选择:
- 一个 5 号电池盒(4 节 = 6V)。MG90S 的标称工作电压是 4.8~6V,6V 完全没问题,而且电池的电流能力远比板子强
- 一个 5V 电源适配器 / 充电宝,能引出正负极的那种
- 手头什么都没有、只想先看一眼效果:临时从拓展板上的
5V脚取电——那个脚是从 USB 直接过来的,比3.3V强不少,做做演示可以
但第 3 条是权宜之计。 一旦舵机被挡住(比如做机械臂时顶到桌子了),电流一冲上去,USB 供电照样会垮。想做得像样,就上独立电源——这是后面 12 个实战课题里反复出现的一件事。
注意:不要接 3.3V,一定不行。 就算电流够,电压也不够——MG90S 要 4.8V 以上才有力气,你给它 3.3V,它会转得软绵绵、抖个不停。
共地:那根不能省的线
独立供电之后,还有一步绝对不能忘:把电池盒的负极,和板子的 GND 用一根线连起来。 这叫共地。
为什么?因为电压是"相对于地"的一个差值。板子说"我在信号线上输出 3.3V",它真正的意思是"比我这边这个地,高 3.3V"。如果舵机那边用的是另一个地(电池负极),两边没有共同的零点,那板子说的"3.3V",在舵机眼里可能是 8V,也可能是 0.5V。
打个比方:两个人量身高,得背靠背站在同一个地面上。 一个站一楼、一个站三楼,报出来的数根本没法比。
这个坑特别阴。 因为不共地的时候,线看起来全都接对了——电源给了,信号接了,可舵机就是乱转、发抖,或者干脆一动不动。这时候别猜,用第 5 课那套顺序查:电 → 信号 → 代码。
- 电压档量舵机的电源脚:转的时候有没有 5V?(没有 → 电源的问题)
- 通断档量电池负极和板子
GND之间:通不通?(不通 → 就是共地没接)
五、动手,分四步
第一步:装库(代码路线)
舵机不是"读一个引脚"那么简单,得装个库。先搜一下:
arduino-cli lib search servo然后装那个给 ESP32 用的舵机库(通常叫 ESP32Servo):
arduino-cli lib install "ESP32Servo"搜出来的名字可能和我写的不完全一样,以你搜到的为准。装不上也别卡在这儿——先走图形化路线,平台里有现成的"舵机"积木,拖出来写上角度就行。你是来学"舵机需要什么"的,不是来跟库管理器较劲的。
第二步:让它转到三个角度
#include <ESP32Servo.h>
Servo myServo; // 给这个舵机起个名字
void setup() {
myServo.attach(7); // 信号线接在 GPIO7
}
void loop() {
myServo.write(0); // 转到 0 度
delay(1000);
myServo.write(90); // 转到 90 度
delay(1000);
myServo.write(180); // 转到 180 度
delay(1000);
}烧进去。你会看到摇臂一格一格地跳过去。
现在注意那几个 delay(1000)——它们不是可有可无的。
第三步:为什么必须有 delay
这是舵机的一个关键脾气:
write(90)不是"把它掰到 90 度",而是"告诉它:请去 90 度"。
说完这句话,程序立刻就往下走了,可舵机还在慢慢转。它转过去是要花时间的——MG90S 空载大概 0.1 秒转 60 度。
你要是说完立刻说下一句"去 180 度",它转了一半就被喊回来,表现就是抖、顿、嗡嗡响,看着像坏了。
给够时间,它就顺了。 试试这个扫动的程序:
void loop() {
for (int a = 0; a <= 180; a++) { // 从 0 扫到 180
myServo.write(a);
delay(15);
}
for (int a = 180; a >= 0; a--) { // 再扫回来
myServo.write(a);
delay(15);
}
}你看,就是"反复做一件小事"而已——for 循环干的就是这个。换个零件,骨架还是那个骨架。
delay(15)是怎么来的? 上面说了,它每度大概要 1.7 毫秒,给 15 毫秒是留了余量的。这就是第 11 课那个"先测,再定"——你可以自己试:改成delay(5)会顿,改成delay(50)会很慢但特别顺。自己试出来的数,比抄来的数记得牢。
第四步:故意踩一次坑
这一步是这节课的重点,别跳过。
把舵机的红线从独立电源上拔下来,插到板子的 3.3V 上(或者拓展板那个 5V 也行,效果弱一点)。串口监视器保持打开,跑上面那个扫动程序。
看着。
你会看到其中一种:舵机抖两下就不动了、板子上的电源灯暗了一下、串口里又打印一遍启动信息、扫到一半突然从头开始。
这就是"舵机一转,板子就重启"。
恭喜你,你把本套课最有名的一个坑亲脚踩了一遍。
为什么我要你故意踩? 因为做第 31 课"追光小雷达"时,你会同时接光敏、舵机、OLED。那个现象会在你最没防备的时候出现,如果你没提前认识它,你一定会怀疑程序写错了、模块坏了、板子烧了——然后花一晚上改代码,而代码一个字都没错。
现在你认识它了。这就是"出错是教学内容,不是事故"。
顺便记一件事:改回独立供电以后,现象是不是立刻消失了? 这就是证据——故障不是猜没的,是被排除掉的。
自测
答案与解析
LED 和蜂鸣器只有"开/关"两种状态,那是数字输出。而"90 度"是一个具体的中间值,数字输出表达不了它。板子不能直接吐出中间电压,于是用 PWM 快速地开关,让后面的器件感受到一个"平均下来"的中间值——这就是模拟输出。
3.3V 脚取电?答案与解析
板子上的 3.3V 是 USB 的 5V 经过一颗小稳压芯片变出来的,设计上只够芯片和传感器用(几十毫安)。舵机启动要几百毫安、堵转时能到 1 安培,一取电就把电压拉垮,板子的欠压保护一动作就重启了——"一开空调,灯就闪一下"是同一件事。 注意:不是电压太高(3.3V 反而偏低,舵机要 4.8V 以上才有力气),也不是信号问题。
GND 连起来?答案与解析
第一个选项是看起来最像的错答案:舵机的回路其实是靠"电池正极 → 舵机红线 → 舵机棕线 → 电池负极"闭合的,跟板子没关系,所以不共地它照样有电(可能有电却乱转)。共地那根线的作用是给两边一个共同的零点——就像两个人量身高得站在同一个地面上,不然报出来的数没法比。
write(90) 后面一定要给 delay?不给会怎么样?答题要点
答题要点应该包含:write() 只是"下达命令",不是"立刻完成"——它告诉舵机"请去 90 度"之后,程序马上继续往下执行,而舵机还在慢慢转(MG90S 空载大约 0.1 秒转 60 度)。如果不给时间就接着发下一条命令,舵机刚转一半就被喊回来、再被喊出去,表现是抖动、顿挫、嗡嗡响、发热,严重的还会堵转。正确做法是给它留够时间,具体留多少可以自己试(本课是 15 毫秒一度)。这背后是一个通用观念:很多硬件动作是"慢慢完成"的,代码不能假设它瞬间就好了。
拓展舵机怎么知道自己现在转到了几度?
这个问题课上不讲,留给你自己找答案——**问 AI 是最好的办法**。
提示:搜"舵机 内部结构 电位器 反馈"、"舵机 闭环控制 原理"。想一想:第 10 课那个电位器,如果被装进舵机里,它能告诉电路什么信息?要是这个电位器坏了,舵机会有什么表现?
拓展舵机为什么规定信号是"每秒 50 次"?改了会怎样?
这个问题课上不讲,留给你自己找答案——**问 AI 是最好的办法**。
提示:搜"舵机 PWM 50Hz 脉宽 1ms 2ms"、"模拟舵机 数字舵机 区别"。想一想:这个频率是随便定的,还是跟舵机内部电路有关?
⚠️ 这个别拿自己的舵机乱试。 频率改错可能让它嗡嗡叫、发热甚至堵转。先查资料搞明白,再决定动不动手。
本节你要动手做的事
- [ ] 认清三根线:橙=信号、红=电源、棕=地。插之前看颜色,别凭手感(红棕接反会烧)
- [ ] 接对信号和地:橙线→
GPIO7,棕线→板子GND - [ ] 给舵机独立 5V:电池盒或 5V 电源,并且把电源负极和板子
GND连起来(共地) - [ ] 转三个角度:
0、90、180,每一步之间给够delay - [ ] 扫过去再扫回来:用
for循环,再自己调调delay的大小,看手感有什么不同 - [ ] 故意踩坑:把红线接到板子的
3.3V,亲眼看板子重启——然后再改回来 - [ ] 用万用表量一次:舵机电源脚在"不动"和"正在转"的时候,电压一样吗?(转的时候会掉一点,那就是"电流大"的证据)
这节课你做了一件前面十几节课都没做过的事:让板子输出了一个"既不是开、也不是关"的东西。
从今天起,"让它到 90 度""让它亮三成""让它慢一点"这类话,你都有办法表达了——方法就是那一个:快到人感觉不出来,平均下来就是中间值。
还有那个坑。 你今天是故意踩的,踩完还知道为什么。但很多人是在做实战课题的时候第一次撞上它——正调着机械臂,板子突然重启,然后开始怀疑人生。你现在比那时候的他们,多知道一件事。
下一节课我们学 OLED 显示屏——套件里唯一一个能显示信息的模块。前面所有模块要么"读"、要么"动",从下一课开始,你的作品能说话了。
顺带一提,它也是唯一一个用 I²C 的模块——两根信号线,而不是一根。这里面有个特别省引脚的思路,下一课讲。