游乐游手机版
首页/AI热点日报/热点详情

树莓派Pico PWM实现LED呼吸灯详解

类型:热点整理2026-05-29
本示例中树莓派Pico利用脉宽调制(PWM)模拟输出,通过电位器读取模拟值控制LED亮度。实现时需注意PWM引脚共享限制及ADC引脚配置,并调用duty_u16方法将模拟输入范围映射至占空比,使LED亮度平滑变化,从而实现无级调光。
```html

树莓派 Pico 上的模数转换器(ADC)专门负责将模拟信号转换为微控制器能够处理的数字信号。然而,反向操作——让数字微控制器输出模拟信号——通常需要数模转换器(DAC)。不过,存在一种巧妙的替代方法:脉冲宽度调制(PWM)。

微控制器的数字引脚只能输出 0 或 1 两种状态。通过快速切换引脚的开与关,就形成了一个脉冲。改变开关的频率,也就改变了脉冲的宽度——这正是“脉宽调制”名称的由来。

Pico 的每个 GPIO 引脚都支持 PWM,但内部的 PWM 模块由八个切片构成,每个切片包含两个输出通道。从引脚图来看,每个引脚都标有一个字母和一个数字:数字表示 PWM 引脚编号,字母表示使用的切片。例如,GP0 对应 PWM_A[0],GP1 对应 PWM_B[0]——这是标准配置。GP2 对应 PWM_A[1],同样正常。但如果试图同时在 GP0 和 GP16 上使用 PWM,就会遇到问题,因为它们都连接到 PWM_A[0] 上。

接下来按照电路图搭建:一个 LED 与 330Ω 限流电阻串联,LED 的正极通过电阻连接到 Pico 的 GP15,负极连接到 GND。

在 Thonny 中打开之前使用的 Potentiometer.py 文件,并将 LED 也配置为模拟数字输入:

led = machine.PWM(machine.Pin(15))

这行代码在 GP15 上创建了一个 LED 对象,关键区别在于它启用了该引脚的 PWM 输出——通道 B[7],也就是第 8 个切片的第二个输出(编号从 0 开始计数)。

还需要设置 PWM 频率,这是控制脉冲宽度的两个参数之一。添加一行代码:

led.freq(1000)

频率设置为 1000 Hz,即每秒 1000 个周期。然后在程序底部,删除 print(voltage) 和 utime.sleep(2) 这两行,替换为:

led.duty(potentiometer.read_u16())

这行代码从电位器对应的模拟输入读取原始数值,并将其作为 PWM 的第二个参数——占空比。占空比决定了引脚输出的有效电压:0% 占空比相当于引脚在每秒 1000 次脉冲中始终处于关闭状态,引脚无效;100% 占空比相当于引脚始终开启,功能上等同于固定的数字高电平;50% 占空比时,引脚一半时间开启、一半时间关闭。

点击 Run,转动电位器,观察 LED。你会发现 LED 会随着电位器的转动而变亮或变暗。这是因为从模拟引脚读取的数据被直接转换成了 PWM 占空比:低占空比对应模拟输出的低电压,LED 暗淡;高占空比对应高电压,LED 变亮。

但存在一个问题:电位器还没有拧到头,LED 就已经达到最亮,并且轻轻一动,亮度变化非常剧烈。原因是模拟读数的范围是 0~65535(16 位整数),而占空比对应的值域最大值只有 1024。任何高于 1024 的数值都会被忽略,并视为 1024。

要解决这个问题,使 LED 亮度平滑变化,就需要将模拟输入的值映射到 PWM 切片能够理解的范围。最直接的方法是告诉 MicroPython,将占空比值作为无符号 16 位整数来传递——与 Pico 模拟输入引脚接收的格式相同。

找到这行代码:

led.duty(potentiometer.read_u16())

改成:

led.duty_u16(potentiometer.read_u16())

最终程序如下:

import machine
import utime

potentiometer = machine.ADC(28)
led = machine.PWM(machine.Pin(15))
led.freq(1000)

while True:
    led.duty_u16(potentiometer.read_u16())

再次点击 Run,将电位器从一端拧到另一端。这次,除非你使用的是对数电位器,否则会看到 LED 亮度平滑地从完全熄灭到完全点亮,全程没有突兀变化。

恭喜!你不仅掌握了模拟输入,还学会了利用脉宽调制来生成等效的模拟输出。

```
来源:https://m.elecfans.com/article/2262271.html

相关热点

继续查看同栏目近期热点。

延伸阅读

补充最近整理过的热点入口。