PWM简介
先从应用上讲讲PWM:
有一盏日光灯,一般我们只能打开它或者关闭它,不存在中间状态;
有另一个LED灯,支持在一秒以内极快速的速度开关开关,其变化超过人眼识别的24帧率,LED灯看上去就像一直开着,但亮度比常开暗一些;如果控制灯快速开关过程中的打开时间和关闭时间的比例,就可以调节人眼看到的灯亮度。
以上就是PWM的大概应用原理:用高频率的开关信号,控制输出信号的平均强度,使输出信号能在0%到100%强度间任意调节。
用电路语句讲PWM原理:用数字信号的占空比来调制模拟信号的幅度(电压)。
PWM详细介绍参考:What is PWM: Pulse Width Modulation
脉冲宽度(pulse width)是指单位时间的高电平的持续时间,脉冲宽度越大被调制的模拟信号电压越大。
- 在一定的频率下,通过不同的(高电平)占空比即可得到不同脉冲宽度,进而调节输出的模拟电压信号
- 在一定的占空比下,通过不同的频率实现不同的调节速度;频率要适配不同设备,不能任意设置,例如电机频率50HZ,MCU外设1000Hz。频率不决定被调制电压的幅度。
PWM的调制信号如下:

PWM调制电路通常用RC filter实现:

PWM一般对具体设备使用固定频率,再调整高电平的占空比决定模拟信号的幅度。
如下图,占空比从0%调节到100%,对应输出电压为0V~5V

从原理上讲就是开关控制,在一个周期内调制信号的高电平时间越长,RC电荷积分更多,输出电压越大:

MicroPython控制PWM
官方tutorial参考:
Quick reference for the ESP32 PWM (pulse width modulation)
Pulse Width Modulation 其中有调整频率和占空比的sample code:
Example of a smooth frequency change:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20from utime import sleep
from machine import Pin, PWM
F_MIN = 500
F_MAX = 1000
f = F_MIN
delta_f = 1
p = PWM(Pin(5), f)
print(p)
while True:
p.freq(f)
sleep(10 / F_MIN)
f += delta_f
if f >= F_MAX or f <= F_MIN:
delta_f = -delta_fExample of a smooth duty change:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23from utime import sleep
from machine import Pin, PWM
DUTY_MAX = 2**16 - 1
duty_u16 = 0
delta_d = 16
p = PWM(Pin(5), 1000, duty_u16=duty_u16)
print(p)
while True:
p.duty_u16(duty_u16)
sleep(1 / 1000)
duty_u16 += delta_d
if duty_u16 >= DUTY_MAX:
duty_u16 = DUTY_MAX
delta_d = -delta_d
elif duty_u16 <= 0:
duty_u16 = 0
delta_d = -delta_d
呼吸灯示例
参考:itproject.cn/Python+ESP32快速上手/3.PWM呼吸灯
esp32的micropython代码以script形式执行,主程序必须命名为main.py(参考 Running your first script):
1 | from machine import Pin, PWM |
LED渐变呼吸闪烁:

如果将led duty调整为512,最大亮度会变小,验证了最大占空比决定最大电压
如果将led freq调整为50,最大亮度不变,但led渐变过程中会闪烁,也就是说开关调节频率太低,导致人眼都可以观察到led的开关电,看上去就是led闪烁