LEDs
树莓派 Pico 上的模拟-数字转换器只能以一种方式工作,它将模拟信号转换为微控制器可以理解的数字信号。如果你想走另一种方式,并让你的数字微控制器创建一个模拟输出,你通常需要一个数字到模拟转换器(DAC),但有一种方法来「伪造」模拟信号,使用所谓的脉宽调制或 PWM。
微控制器的数字输出只能是 0 或 1。打开和关闭数字输出被称为脉冲,通过改变引脚打开和关闭的频率,你可以改变或调制这些脉冲的宽度,因此称为「脉宽调制」。
Pico 上的每个 GPIO 引脚都能够进行脉宽调制,但是微控制器的脉宽调制块是由八个切片组成的,每个切片有两个输出。如图所示,你会看到每个 Pin 都有一个字母和一个数字。数字表示 PWM 引脚的编号,而字母表示使用的哪一个 PWM 片来输出。
如果你在引脚 GP0 上使用 PWM_A[0],在引脚 GP1 上使用 PWM_B[0],一切都正常。如果你在引脚 GP2 上添加 PWM_A[1],依然正常运行。但是如果你尝试在引脚 GP0 和引脚 GP16 上使用 PWM 通道,你会遇到问题,因为它们都连接到 PWM_A[0]。
下面按照图示搭建电路,LED 和 330Ω 限流电阻,LED 正极通过 330Ω 电阻连接 Pico 的 GP15。LED 负极连接到 Pico 的 GND 引脚。
在 Thonny 中打开前面章节中的 Potentiometer.py 代码文件。再将 LED 设置为模拟数字输入:
led = machine.PWM(machine.Pin(15))
这段代码将在 GP15 引脚上创建了一个 LED 对象,但有一个区别,它激活了引脚上的脉宽调制输出,通道 B[7],第 8 片的第二个输出(从零开始计数)。
你还需要设置 PWM 的频率,这是你可以更改的两个值之一,以控制或调制脉冲宽度。在下面再加一行:
led.freq(1000)
这设置了 1000 赫兹的频率,即每秒 1000 个周期。接下来,到程序的底部,删除 print(voltage) 和 utime.sleep(2) 两行,添加下面一行:
led.duty(potentiometer.read_u16())
这行从连接到电位器的模拟输入中获取原始读数,然后使用它作为脉宽调制的第二个参数:占空比。
占空比控制引脚的输出,0% 占空比使引脚在每秒 1000 次脉冲中处于打开,并有效地关闭 引脚;100% 占空比使引脚处于开启状态,达到每秒 1000 次脉冲,在功能上相当于将引脚作为固定数字输出为打开;50% 占空比的引脚有一半脉冲是开的,一半脉冲是关的。
点击 Run 运行程序,转动电位器时观察 LED。转动电位器时 LED 会变亮,反向转动电位器时 LED 会变暗。这是因为从连接到电位器的模拟引脚读取的数据被转换为 PWM 信号占空比的值,低占空比就像模拟输出上的低电压,使 LED 暗淡;高占空比就像高电压,使 LED 变亮。
不过,你会注意到,LED 在电位器旋钮达到停止点之前就已经达到最大亮度,非常轻微的移动 就会引起亮度的巨大变化。这是因为模拟读数是一个介于 0 到 65535 之间的数字(一个 16 位整数)但占空比 0 – 100%,对应的值域最大值仅为 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,这一次,除非你用的是对数电位器,否则你会看到 LED 的亮度平滑地从电位器旋钮的一端完全关闭到另一端完全点亮。
祝贺你!你不仅掌握了模拟输入,而且现在可以使用脉宽调制创建等效的模拟输出了!
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !