我用树莓派Pico学Python (4) – PWM
PWM全称是脉冲宽度调制(Pulse width modulation
),也叫脉宽调制,从波形上看PWM就是方波。PWM的频率是1秒内有多少个方波脉冲,PWM的占空比是方波的一个周期内高电平所占的百分比。
介绍另一篇博文,对PWM的解释比较好:
https://blog.csdn.net/as480133937/article/details/103439546
从本专题的前几篇可以看到,树莓派Pico的GPIO可以输出高电平(可以点亮LED)或低电平(可以熄灭LED)。同时,树莓派的所有GPIO也都可以输出PWM,即按照一定的频率的高低电平的变化,而且频率和占空比可以很方便的设定和更改。
当然,按照之前闪烁LED的程序,GPIO实际上输出的也是PWM,只不过PWM的频率比较低(1Hz)。如果要提高频率、改变占空比的话,就要麻烦一些。 而按照直接输出PWM的方法,就非常的方便。
先来把闪烁LED的程序改为PWM输出的方式:
import time
from machine import Pin, PWM
# 设定GPIO25为PWM输出方式
pwm = PWM(Pin(25))
# 设定PWM的频率为10Hz,这是Pico的PWM输出的最低频率
pwm.freq(10)
# 设定PWM的占空比,取值范围0~65535, 而32768大约是一半,也就是50%
pwm.duty_u16(32768)
运行这段程序后,可以看到绿色LED
以10Hz的频率快速闪烁(树莓派Pico的PWM不能输出1Hz脉冲,也就不能让LED每1秒闪一次),而程序运行完毕后返回了命令提示符(如下所示),说明这段程序不是死循环,PWM是主芯片 “自动” 一直在输出的
MicroPython v1.16 on 2021-06-18; Raspberry Pi Pico with RP2040
Type "help()" for more information.
>>> %Run -c $EDITOR_CONTENT
>>>
呼吸灯
如下程序代码来自于树莓派Pico的官方文档
https://datasheets.raspberrypi.org/pico/raspberry-pi-pico-python-sdk.pdf
第17页
不过我将最后一句的延时时间改为0.005秒,让呼吸的速度慢一些。 程序运行后会让绿色LED
呼吸闪烁4次。
# Example using PWM to fade an LED.
import time
from machine import Pin, PWM
# Construct PWM object, with LED on Pin(25).
pwm = PWM(Pin(25))
# Set the PWM frequency.
pwm.freq(1000)
# Fade the LED in and out a few times.
duty = 0
direction = 1
for _ in range(8 * 256):
duty += direction
if duty > 255:
duty = 255
direction = -1
elif duty < 0:
duty = 0
direction = 1
pwm.duty_u16(duty * duty)
time.sleep(0.005)
更进一步
我们再来尝试同时在几个GPIO产生不同频率、不同占空比的PWM。
在此之前,先说明几点树莓派Pico的PWM需要注意的地方:
-
树莓派Pico一共有8个独立PWM引擎,被称为
slices
。 -
每一个slice有一个
A通道
和一个B通道
可以输出PWM。 -
不同的
slice
可以产生不同的频率,但是一个slice
的不同GPIO只能有一个相同的频率 -
A通道
和B通道
可以有不同的占空比,但是一个slice
的一个通道的GPIO只能有相同
的占空比 -
需要注意,对PWM的设定会影响一个slice的所有GPIO
-
PWM的8个Slice对应的GPIO如下表:
Slice | A | B |
---|---|---|
0 | 0, 16 | 1, 17 |
1 | 2, 18 | 3, 19 |
2 | 4, 20 | 5, 21 |
3 | 6, 22 | 7, 23 |
4 | 8, 24 | 9, 25 |
5 | 10, 26 | 11, 27 |
6 | 12, 28 | 13, 29 |
7 | 14 | 15 |
在前面的博文可以看到,树莓派Pico核心板的绿色LED
连接到GPIO25
,而01Studio
开发学习板的红、黄、蓝LED
分别连接到GPIO18
,GPIO19
,GPIO20
。
GPIO25
在Slice 4
,GPIO18
和GPIO19
在Slice 1
,GPIO20
在Slice 2
。
也就是说,红色LED
和黄色LED
只能有相同的闪烁频率,但是可以有不同的占空比,而绿色LED
、红色LED
、蓝色LED
则可以有不同的闪烁频率。
import time
from machine import Pin, PWM
pwm_green = PWM(Pin(25))
pwm_red = PWM(Pin(18))
pwm_yellow = PWM(Pin(19))
pwm_blue = PWM(Pin(20))
# 绿色LED闪烁频率 1000Hz
pwm_green.freq(1000)
# 红色LED闪烁频率 10Hz
pwm_red.freq(10)
# 黄色LED闪烁频率 10Hz
pwm_yellow.freq(10)
# 蓝色LED闪烁频率 20Hz
pwm_blue.freq(20)
# 绿色LED闪烁占空比 10%
pwm_green.duty_u16(6553)
# 红色LED闪烁占空比 1%
pwm_red.duty_u16(655)
# 黄色LED闪烁占空比 50%
pwm_yellow.duty_u16(32768)
# 蓝色LED闪烁占空比50%
pwm_blue.duty_u16(32768)
运行程序后可以看到:
绿色LED
因为闪烁频率是1000Hz,肉眼看不出闪烁,但是因为占空比只有10%,所以亮度比正常低很多;红色LED
和黄色LED
的闪烁频率是一样的,但是红色LED的亮起时间明显短很多;蓝色LED
的闪烁频率明显比红色LED
、黄色LED
的快,但是还是肉眼可见的闪烁
此时,在 Thonny 的 Shell 区域的命令提示行中尝试运行如下命令:
pwm_yellow.freq(100)
然后再运行
pwm_red.freq()
可以看到结果
>>> pwm_red.freq()
100
说明我们在更改黄色LED
闪烁频率为100Hz时,红色LED
的频率也变为100Hz了。
而观察开发板上的LED,也可以看出,此时红色LED
和黄色LED
肉眼都看不出闪烁了,只是红色LED
的亮度比黄色LED
的亮度低很多,因为驱动红色LED
的PWM的占空比只有1%。