玩硬件这东西,最容易踩的坑往往不是代码,而是电路和理解。今天我们就拿一个最不起眼的三色灯珠——RGB LED,配上树莓派 Pico 的 PWM,把从硬件原理到代码控制整条链路彻底走一遍。
先说清楚:我们不是在跑一个“点灯”的 hello world,而是在解决一个真实问题——怎么让一颗 LED 按你的意志平滑地变化颜色和亮度。核心工具是 PWM(Pulse Width Modulation,脉冲宽度调制),它干的活就是把数字信号变成“看起来像模拟”的输出。Pico 这颗板子,主控是 RP2040,双核 Cortex-M0+,跑 133MHz,价格不过几十块,做这类底层控制实验性价比极高。这篇文章适合刚接触嵌入式、被“PWM 占空比”这类词吓住的零基础新人,也适合想把手头 Pico 派上用场的硬件爱好者。我会把原理、接线、代码和那些文档里不写的坑一次性讲透。
1. 动手前的硬件基础:RGB LED 到底在做什么
1.1 共阳与共阴:买之前必须先搞清楚的事
RGB LED 并不是什么神秘器件,它本质上是把三颗独立的 LED 晶粒封装在一个外壳里,分别发出红光(Red)、绿光(Green)、蓝光(Blue)。晶粒的一端全部连在一起,拉出来作为一个公共引脚,另一端各拉一个引脚出来单独控制,这就形成了四引脚封装。关键分水岭在于:公共端是接到正极还是负极。
如果是公共端接到电源正极,这个就叫共阳(Common Anode),控制端要拉低电平才能点亮对应颜色。如果是公共端接到负极,就叫共阴(Common Cathode),控制端要给高电平才能点亮。听起来简单,但很多人栽在第一步——代码没问题,灯死活不亮,最后发现是共阳、共阴搞反了。
我的建议是:买之前一定看规格书,淘宝详情页如果连个引脚图都不给,直接换一家。实操时也可以用万用表二极管档确认:红表笔接某个引脚,黑表笔分别碰其余三个引脚,如果有电压读数,说明红表笔接的是共阳端;反过来有读数则是共阴。这个方法在传感器上也通用,可以避免很多“假故障”。
1.2 限流电阻计算:为什么不能直接接引脚
RGB LED 本质还是二极管,它的伏安特性特别陡峭。这一特性我们在物理课上都学过:电压稍微高一点点,电流就会指数级上升。而单片机的 GPIO 输出能力有限,Pico 每个引脚最大只能提供约 12mA 的电流,如果你直接拿 3.3V 去怼一个额定 2V 的红光 LED,电流会瞬间飙到几十甚至上百毫安,这个时候 LED 不会像宣传的那样“更亮”,而是直接烧掉,甚至有可能损坏引脚。
那限流电阻值怎么算?核心公式是初中物理就学过的欧姆定律:
[ R = \frac{V_{source} - V_{forward}}{I_{desired}} ]
以 Pico 的 3.3V 供电、红光 LED 正向压降 (V_F) 约 2.0V、目标电流 (I) 设为 5mA 为例:
[ R = \frac{3.3 - 2.0}{0.005} = \frac{1.3}{0.005} = 260\Omega ]
标准电阻 E24 系列里最接近的是 270Ω。绿光和蓝光的正向压降稍高,一般约 3.0V,算下来:
[ R = \frac{3.3 - 3.0}{0.005} = 60\Omega ]
可以取标准值 68Ω 或 62Ω。但说实话,我把三个通道都统一用了 330Ω,因为便于备料,亮度稍低一点在室内完全够用,而且能更好地保护 LED。如果你嫌暗,再降到 220Ω 一组整体替换就行,不要三个通道各用不同规格搞得自己麻烦。
注意:电流不是越大越好。5~10mA 在室内已经是明显可见的亮度,15mA 以上就开始刺眼,超过 20mA 对普通指示型 LED 就是寿命加速器。尤其是做呼吸灯这种持续点亮场景,小电流反而更合适。
2. 树莓派 Pico 的 PWM 原理:从定时器到占空比
2.1 RP2040 的 PWM 硬件架构:Pico 到底有多少路 PWM
很多新手以为 PWM 是“用延时函数在代码里翻转引脚电平”弄出来的。那叫软件 PWM,CPU 被占得死死的,干不了别的活。RP2040 内部是有独立硬件 PWM 外设的,配置好之后自动输出,CPU 可以解放出来跑其他逻辑。
RP2040 芯片里内置了 8 个 PWM slice(切片),每个 slice 又分成 A、B 两个通道,所以总共可以同时输出8 路独立的 PWM,对应到的是芯片上不同的 GPIO 引脚。引脚映射是有讲究的,每个 GPIO 都绑定了某个 slice 的某个通道:
| GPIO 引脚 | PWM 通道 |
|---|---|
| GPIO 0 / GPIO 1 | slice 0 A / B |
| GPIO 2 / GPIO 3 | slice 1 A / B |
| GPIO 4 / GPIO 5 | slice 2 A / B |
| GPIO 6 / GPIO 7 | slice 3 A / B |
| GPIO 8 / GPIO 9 | slice 4 A / B |
| GPIO 10 / GPIO 11 | slice 5 A / B |
| GPIO 12 / GPIO 13 | slice 6 A / B |
| GPIO 14 / GPIO 15 | slice 7 A / B |
| GPIO 16 起 | 复用映射,可配置到不同 slice |
我们的 RGB LED 刚好需要三路 PWM。最省心的选择是 GPIO 0、1、2——但要注意,GPIO 0 和 GPIO 1 属于同一个 slice 0,它们俩共享同一个计数器,只共享频率,不共享占空比。换句话说,你给 GPIO 0 设了 1kHz,GPIO 1 也必须是 1kHz,但你可以分别设置不同的占空比。对 LED 调色来说完全够用,因为频率一样,相位关系也不敏感。
如果想三个通道完全独立调整频率,那就选不同 slice 的引脚组合,比如 GPIO 0(slice 0 A)、GPIO 4(slice 2 A)、GPIO 8(slice 4 A)。这就要靠你翻数据手册查复用表。我第一次用 Pico 的时候没注意这件事,结果两个引脚共用 slice,想设成不同频率,怎么设都无效,后来翻手册才恍然大悟。
2.2 频率、占空比与分辨率:三个参数的相互影响
PWM 有三个关键参数:频率(Frequency)、占空比(Duty Cycle)、分辨率(Resolution)。搞清楚这三者的关系,整个 PWM 控制就通了一半。
频率就是每秒方波重复的次数,单位 Hz。频率低到一定程度,人眼能看出 LED 在闪。我实测下来,低于 200Hz 的闪烁感非常明显,高于 1kHz 就完全感觉不到。做 LED 控制,频率设在 1kHz~5kHz 之间最舒服,既不闪烁,也不会因为频率太高导致开关损耗显著上升。
占空比就是高电平时间占整个周期的百分比,0% 就是全灭,100% 就是全亮,50% 就是一半亮度。注意:LED 的亮度和占空比在硬件上近似线性,但人眼感知是非线性的,这涉及到后文要说的 Gamma 校正。
分辨率说的是占空比能够精细到什么程度。RP2040 的 PWM 计数器是 16 位的,理论上占空比可以从 0 到 65535 任意取值。这个数值就是你要写进频率寄存器的最顶层参数。在 MicroPython 里,你直接设freq()和duty_u16(),底层帮你把分频和计数值都算好了,但理解寄存器还是有价值的。例如你要 1kHz 输出,系统时钟 125MHz,分频系数为 1,那么计数器的周期值就是 125000000 / 1000 = 125000,这个值不能超过 65535……诶,等等,这里就暴露问题了。
对,如果分频系数为 1,频率最低只能到 125MHz / 65536 ≈ 1907Hz,想要更低的频率就必须加大分频。RP2040 的分频器支持 1~255 的整数倍频,加上一个 16 位的小数部分。细节不用背,用 MicroPython 的PWM()接口时这些都自动处理了。但你要知道一个结论:分辨率不是永远是 16 位,频率越低,计数器周期越大,能表达精细占空比的余量越大;频率越高,计数器周期被压缩,分辨率就越低。在 LED 场景下,1kHz 配 16 位分辨率绰绰有余,但在某些高频电力电子场景,几百 kHz 的 PWM 分辨率可能掉到 8 位以下,这就需要在控制精度和输出频率之间做权衡了。
2.3 PWM 在真实世界中的几个典型用途
PWM 的用处远远不止点灯这一件事。热搜里那些相关词其实都指向同一个核心外设。
- 舵机控制:舵机的转角靠一个 50Hz(周期 20ms)的 PWM 信号控制,脉宽 0.5ms 对应 0°,1.5ms 对应 90°,2.5ms 对应 180°。这个不是 LED 的亮度逻辑,而是靠高电平持续时间长短直接控制。搞过 Pico 的人基本都试过
duty_u16设置脉宽,其实算一下就清楚了。 - 电机调速:直流电机的等效电压和占空比成正比,50% 占空比就是大约一半转速。但电机是感性负载,开关瞬间有反电动势冲击,所以通常要加续流二极管和半桥驱动电路,不能直接拿 GPIO 驱动。
- 开关电源与恒温控制:热搜里那些“PWM 故障保护”“死区设置”往往指向电力电子领域。比如全桥电路里上下桥臂必须设置死区时间,防止上下管直通短路。这个属于进阶话题,但底子都是同一个 PWM 外设。
做嵌入式越久,你会发现 PWM 是一个绕不开的基石外设。今天我们拿 LED 切入,既因为它好观察、容易成功,也因为它背后映射的这套规则,可以直接平移到舵机、电机甚至逆变器控制。
3. 接线与硬件搭建:用最少物料搭一个可靠实验环境
3.1 物料清单与选型建议
搭建这套实验环境,物料非常便宜:
| 序号 | 物料 | 规格建议 | 备注 |
|---|---|---|---|
| 1 | 树莓派 Pico | 任意版本,最好是带排针的 | 引脚引出来方便接线 |
| 2 | RGB LED | 四脚共阴或共阳,直径 5mm | 我以共阴为例,共阳逻辑反转即可 |
| 3 | 电阻 | 330Ω 三颗(或者按 1.2 节计算值) | 建议 1/4W 直插电阻 |
| 4 | 面包板 | 400 孔或 830 孔 | 面包板电容效应小,LED 场景够了 |
| 5 | 杜邦线 | 公对公、公对母若干 | 建议多备几种颜色区分信号 |
| 6 | MicroUSB 线 | 数据线,不是充电线 | 很多“连不上”是线的问题 |
有些人可能会问:能不能不用面包板,直接拿杜邦线怼进 Pico 的排针里?能用,但不建议。RGB LED 四只引脚间距很近,手一抖就搭到旁边引脚,短路瞬间就可能烧板子。面包板多花两块钱,却能避免大多数低级事故。
特别提醒:千万别用那种淘宝买的“LED 模块”,上面集成了三色灯和限流电阻,虽然接线方便,但你少了亲自计算电阻的环节,也就失去了理解硬件的绝佳机会。做入门实验,就是要亲手把这些细节过一遍。
3.2 共阴接法 vs 共阳接法
共阴接法的电路逻辑是:公共端接 GND,三个颜色引脚分别通过限流电阻接到 Pico 的 GPIO。GPIO 输出高电平时,电流从引脚流进 LED,再从公共端回 GND,灯亮。想要哪个颜色亮,就把哪个引脚拉高。
共阳则反过来:公共端接 3.3V,三个颜色引脚分别通过限流电阻接到 Pico 的 GPIO。GPIO 输出低电平时,电流从 3.3V 经 LED 流入 GPIO,灯亮。
注意一个细节:共阳接法下,点亮一个颜色靠的是 GPIO 灌入电流(sink current),Pico 的吸入电流能力也是有限度的,我实测灌 20mA 没大问题,但超过手册标称值就不保证稳定性。所以限流电阻按 5~10mA 设置,三种接法都可以稳定运行。
我的接线方案(共阴):
GND ---- RGB LED 公共阴极 GPIO 0 ---- 330Ω ---- R 引脚(红) GPIO 1 ---- 330Ω ---- G 引脚(绿) GPIO 2 ---- 330Ω ---- B 引脚(蓝)如果是共阳,把 GND 改成 3.3V,代码里逻辑反过来用就行。
接线顺序也有一点讲究。先把 Pico 的 USB 线拔掉,断电状态下接线。接好后,先不插 Pico,用万用表通断档检查有没有不该通的回路。尤其是共阴接法下,公共阴极如果误接到了 3.3V,那个 GPIO 高电平起来的时候岂不是直接正负短路?这种低级错误排查起来才最费时间。
接好之后,插上 USB,板载 LED 亮起,你就可以尝试写代码了。
4. MicroPython 实战代码:从单色点亮到颜色渐变全流程
4.1 准备工作:固件与开发环境
用 Pico 做开发,最爽的就是可以用 MicroPython。你不需要编译器、不需要调试器,一个串口 REPL 就能交互式地控制硬件。步骤就三步:
- 去树莓派官网下载 MicroPython UF2 固件,选带最新稳定版的那一个。
- 按住 Pico 上的 BOOTSEL 按键不松,同时插入 USB 线,电脑上会弹出一个名为 RPI-RP2 的 U 盘。
- 把下载的
.uf2文件拖进 U 盘,它会自动退出,板子自动重启。
重启之后,在电脑装一个串口终端工具,比如 PuTTY 或 Thonny。我最推荐 Thonny,因为它内置了 MicroPython 的 shell 和图形化文件管理器,调试起来非常直观。如果插上 USB 后找不到串口,多半是你用了充电线而不是数据线——这个我一年能提醒别人八百次。
4.2 第一版:用 PWM 点亮单色并进行亮度调节
先从一个最简单的实验开始:让红色 LED 发光,然后调节亮度。
from machine import Pin, PWM # 初始化 GPIO 0 为 PWM 输出 pwm_red = PWM(Pin(0)) # 设置频率为 1kHz pwm_red.freq(1000) # 设置占空比为 50%(范围 0~65535) pwm_red.duty_u16(32768)这段代码上去,红色 LED 应该处于半亮状态。如果你看到的是全亮或者不亮,先检查接线,再看duty_u16的数值含义。占空比的对应关系是duty_u16(65535)对应 100%,duty_u16(0)对应 0%。如果你习惯用百分比,可以封装一个辅助函数:
def set_duty(pwm, percent): pwm.duty_u16(int(percent * 65535 / 100))注意这里的percent取值范围是 0~100。有了这个函数,设置亮度就直观多了。我实测下来,Pico 的 PWM 在占空比接近 0% 时,LED 确实会完全熄灭;但在占空比接近 100% 时,由于 MOSFET 导通电阻并非完全为 0,会有约 0.1V 压降,肉眼看不出来,不影响。
4.3 第二版:经典呼吸灯与代码注释
呼吸灯的效果就是 LED 亮度从暗到亮再回到暗,循环往复。实现思路是用一个计数器,在 0~65535 之间来回扫。但这有个问题:人眼对亮度的感知不是线性的,暗部的变化非常敏感,亮部的变化很难察觉。如果直接线性扫描,你会发现灯在暗部“突突突”地闪,亮部却感觉没什么变化。
为了解决这个问题,我采用一个简单的 Gamma 校正曲线。思路是让占空比的增长按平方曲线而不是直线进行,暗部变化放缓,亮部变化加快,整体视觉更平滑。
import math from machine import Pin, PWM import time pwm_red = PWM(Pin(0)) pwm_red.freq(1000) # 呼吸灯,带简易 Gamma 校正 while True: for i in range(0, 628, 2): # 2π 范围,用弧度近似 # value 从 0 到 2π 变化 brightness = (math.sin(i / 100) + 1) / 2 # 0.0 ~ 1.0 # 平方 Gamma 校正,让视觉过渡更线性 duty = int(brightness * brightness * 65535) pwm_red.duty_u16(duty) time.sleep_ms(10)这段代码里math.sin出来的正弦波值域是 -1 到 1,加 1 除以 2 后变成 0 到 1,再平方,就是暗部更柔和、亮部更有层次感的呼吸曲线。如果你不加 Gamma 校正直接线性扫 0~65535,对比一下就知道差别有多大。呼吸周期可以通过调整range的步长和sleep_ms微调,我这里的步长 2 对应大约 3 秒一个完整周期(628 次循环 × 10ms ≈ 6.28s,半周期约 3.14s)。
你可能会问,为什么不用math.sin直接生成占空比,还要平方?因为 LED 的电压-亮度在低电流区域其实是接近线性的,但人眼在暗部的分辨率更高,同一个 5% 的亮度变化,暗部看起来比亮部更明显。这个平方修正是最简单粗暴的近似,高级做法会用真实 Gamma 表(sRGB 曲线),但对入门足够用了。
4.4 第三版:三通道全彩混合与颜色渐变
现在把三路 PWM 都接上,开始混合颜色。
from machine import Pin, PWM import time # 初始化三路 PWM pwm_red = PWM(Pin(0)) pwm_green = PWM(Pin(1)) pwm_blue = PWM(Pin(2)) for pwm in [pwm_red, pwm_green, pwm_blue]: pwm.freq(1000) pwm.duty_u16(0) def set_color(red, green, blue): """参数范围 0~255,符合大多数上位机习惯""" pwm_red.duty_u16(int(red * red * 65535 / (255 * 255))) pwm_green.duty_u16(int(green * green * 65535 / (255 * 255))) pwm_blue.duty_u16(int(blue * blue * 65535 / (255 * 255))) # 循环切换几种固定颜色 colors = [ (255, 0, 0), # 红 (0, 255, 0), # 绿 (0, 0, 255), # 蓝 (255, 255, 0), # 黄 (0, 255, 255), # 青 (255, 0, 255), # 品红 (255, 255, 255), # 白 ] while True: for color in colors: set_color(*color) time.sleep_ms(800)这里我把set_color的输入范围定成了 0~255,方便你对标大多数颜色选择工具的调色盘。红、绿、蓝都设 255 就是白,设 128、128、128 就是灰色。再配合循环扫描 R、G、B 的值,你就能让颜色在色环上自由流走。
有一个非常关键但大多数人不知道的点:在set_color里做了平方 Gamma 校正后,颜色混合的“中间色”会变得正常得多。如果不做校正,你调黄色(255, 255, 0)出来可能偏绿,调白色出来可能偏蓝。因为不同颜色 LED 的发光效率不一样,红光通常偏弱,绿光和蓝光偏亮。要严格校准颜色,可以用一颗色温校准的相机或者手持色度计,把三通道的校正系数做成查找表,但我认为对于入门实验,平方 Gamma 加微调即可——你按视觉把红色系数往上调一点,比如实际输出 255, 180, 180,让白色接近纯白,这就够了。
我在实际使用中发现一个经验:Pico 的 PWM 在高占空比时(90% 以上)会有轻微的非线性,肉眼表现为颜色在最高亮度段变化不明显。这不影响使用,但如果你要做高精度的混色,尽量避免让三个通道同时工作在 90% 以上,可以把整体亮度压到 80% 左右再调色。另外,Pico 的 GPIO 输出高电平不是严格的 3.3V,接不同负载会有一点点压降,这也是电阻和电流选型的容差来源之一。
4.5 进阶玩法:把颜色渐变写成可复用的轮询程序
颜色循环谈不上“实战”,真正的乐趣在于让它动态渐变。这里给出一个更常用的滑条渐变逻辑,适合做氛围灯:
def lerp(a, b, t): """线性插值:返回 a 到 b 之间按 t(0~1)比例的值""" return int(a + (b - a) * t) # 从红色渐变到绿色 while True: for t in range(0, 101): t /= 100 red = lerp(255, 0, t) green = lerp(0, 255, t) set_color(red, green, 0) time.sleep_ms(15)这个lerp函数是几乎所有颜色动画的基础,学会了之后可以玩出彩虹渐变、颜色循环、Pulse 呼吸等多种效果。思路就是把颜色空间想象成一个三维立方体,你在里面画线,让一个点从 A 点滑到 B 点,每帧把坐标转换成 PWM 占空比输出。
5. 常见问题排查与避坑速查表
5.1 现象对照排查:灯不亮、颜色不对、亮度异常
我整理了运行这套实验最常见的几类故障,按排查优先级排列:
| 现象 | 可能原因 | 排查方式 |
|---|---|---|
| 完全没反应 | 接线错误、共阳共阴接反、MicroPython 刷错 | 用万用表测电源和引脚电平,确认固件版本 |
| 颜色偏得很厉害 | 电阻选型不合理、PWM 频率太低导致闪烁 | 确认三个通道限流电阻是否一致,提高频率到 1kHz |
| 亮度变化有明显的阶跃感 | 占空比分辨率不足 | 降低 PWM 频率(如 200Hz~1kHz),但不要低于人眼闪烁频率 |
| 某个颜色始终偏暗 | 该通道 GPIO 损坏或接线接触不良 | 用万用表量该引脚对地电压是否随占空比变化 |
| 过高亮度下颜色异常 | 电源电流不足或 USB 线劣质 | 换一根高质量数据线,或者给面包板外接 3.3V 电源 |
“颜色偏得离谱”这个坑最隐蔽,因为新手往往第一时间怀疑代码。实际上,很多 USB 供电线内部压降巨大,Pico 在带动三路 LED 全亮时,总线电压可能从 5V 掉到 4.4V,3.3V 稳压输出就会偏低,红光和蓝光的亮度比例就变了,白色看起发红或者发蓝。尤其是白色,随便哪个通道偏一点都特别明显。这种情况下,除了换线,还可以把亮度整体降到 70% 左右,减少电流压力。
5.2 和 PWM 外设相关的常见问题速查
借助热搜词,我把和 PWM 相关的几个高频问题一并列出来。这些问题在 LED 控制里不一定会碰到,但理解后对你后续做舵机、电机控制帮助极大:
同一 slice 的 A、B 两路能不能设不同频率?不能,同一 slice 共用分频器和计数器,A、B 只能设不同占空比,频率必须相同。如果必须不同频率,把引脚切到不同 slice。
占空比调成 100% 时出现异常怎么办?有些外设在 100% 占空比时会产生极窄的灭脉冲(Dead Band)问题,Pico 的 PWM 模块本身没有这个问题,但如果你用 STM32 之类的 MCU,部分定时器在 100% 占空比时确实可能输出恒低电平,需要检查定时器的极性位和预装载配置。
频率设置极高(几百 kHz 以上)时,LED 亮度会异常?是的,LED 的开关响应有物理极限,频率太高时 PN 结电容造成的损耗变大,LED 的等效亮度可能下降。LED 场景频率设在 500Hz~10kHz 都没问题,不用更贪高。
用 MicroPython 的
duty_u16到底对应什么?它是对应 PWM 周期内高电平时间占整个周期乘以 65535。不是直接对应电压,而是对应时间比例。duty_u16(0)全灭,duty_u16(65535)全亮。PWM 的
freq()返回值是整数还是浮点?MicroPython 里,PWM.freq()是整数 Hz,PWM.duty_u16()是 16 位整数。底层是硬件计数器自动算的,你设置了 freq 之后,如果想看底层实际算出来的分频值,可以读pwm.freq()或者直接翻寄存器的当前值,但这会导致部分 API 在某些固件版本上精度丢失。
5.3 最后分享几个小技巧
我调试这套电路的经验里,最有价值的几条大概是:
- 调试时给每个通道写一个独立的最小测试程序,先让红灯常亮,再让绿灯常亮,最后才是混色。三步走完,问题定位就清楚一半。
- 用 Thonny 的时候,如果程序卡死在
while True里,你可以用“停止/重启”按钮把当前程序中断。但如果 Pico 连串口都无响应,那就按住 BOOTSEL 重新上电,重新刷一遍固件,这是最后保命手段。 - 面包板上同一个排线如果接头松了,可能会造成那种“偶尔亮偶尔不亮”的灵异现象。我建议把 LED 的公共端用跳线直接接到 GND(共阴)或 3.3V(共阳),并在插紧后用万用表量一遍通断,至少能排除 80% 的接触问题。
6. 从 LED 控制延伸出去:PWM 还能做什么
学会了 LED 的 PWM 控制,你的技能树其实已经长出了大半根主干。这里给出两个真实世界的延伸方向,方便你在玩腻了混色之后继续深入。
6.1 舵机控制:同样是对脉冲宽度的精确掌控
舵机常用 50Hz PWM,周期 20ms,高电平持续时间(脉宽)决定角度去。如果你在树莓派 Pico 上用freq(50),然后把duty_u16换算成脉宽,就会发现问题来了:20ms = 20000us,占空比 1/20 = 5%,宏观看duty_u16就是0.05 * 65535 = 3276。实际上 0.5ms 对应的是0.0005 / 0.02 * 65535 = 1638,2.5ms 对应8192。把这些算清楚,你的 Pico 就能驱动舵机做出机器人手臂动作。PWM 是舵机控制的核心,但难点不是 PWM 本身,而是脉冲宽度与角度的映射关系。
6.2 电机调速与闭环控制
直流电机的 PWM 调速就更日常了。PWM 占空比决定等效电压,转速近似线性变化。但电机是感性负载,不能直接接到 GPIO,必须通过 MOS 管、H 桥等驱动电路。一旦开始玩电机,你就会遇到“死区时间”“互补 PWM”“故障保护”这些概念——这些词在前面的热搜里频繁出现,它们都是电力电子控制里的关键词。Pico 的 PWM 外设在这些场景依然够用,但你要更深入地研究的是外部驱动电路和保护电路,而不是 Pico 本身。
现在回过头看,RGB LED 项目就像是嵌入式世界的“乘法口诀表”:电路基本功练到了,PWM 外设玩明白了,再往任何方向走,都会比没有挥过这板斧的人顺畅得多。我到现在还会时不时拿一颗三色灯珠做点小玩意,是因为它简单到不会甩脸色给你看,又丰富到永远有新的玩法——这大概就是硬件的魅力。