1. PWM概念

脉冲宽度调制(英语:Pulse-width modulation,缩写:PWM),简称脉宽调制, 是将模拟信号转换为脉冲的一种技术,
一般转换后脉冲的周期固定,但脉冲的工作周期会依模拟信号的大小而改变。

PWM涉及到两个重要的概念频率占空比

  • 频率 Frequency (freq)
    PWM完成一个周期的速度,如100Hz即是每秒100个周期。理解为PWM在高低态电平之间切换的速度。ESP8266的频率范围为 0 < freq < 78125
  • 占空比 Duty Cycle (duty)
    表示在一个周期内,工作时间与总时间的比值。对应到引脚电路中,即是信号位于高状态的时间量占完成一个周期所花费的总时间的百分比。
    较低的占空比对应于较低的功率,因为电源大多数时间是关闭的。ESP8266的duty取值范围为 0 <= duty <= 1023

下面这一张就能很好的理解周期和占空比的概念。

esp32 获取脉冲 esp8266脉冲_开发板

2. 通俗理解

从电路知识方面来通俗理解,PWM其实就是把直流电逆变为交流电,频率决定交流电的切换周期、占空比其实就是控制输出电压。都已经输出可调的电压了,那么用来控制电机转速、控制LED灯亮度、控制蜂鸣器音量大小就比较容易理解了嘛。

占空比为100%时,其实就是一直输出高电平,那输出电压就等于输入直流电压,占空比为50%可以认为输出一半的电压。

PWM输出来不是那种标准交流电的正弦波形,而且一种模拟出来的脉冲波形,通过改变占空比就能近似模拟出正弦波的效果,比如依葫芦画瓢法(SPWM)

esp32 获取脉冲 esp8266脉冲_开发板_02


原理不过多解释了,知道那么回事儿就得了

esp32 获取脉冲 esp8266脉冲_开发板_03

3. 使用方法

声明PWM引脚时需要指定使用的GPIO引脚和对应的频率、占空比参数,也可以声明后再变更频率和占空比

from machine import Pin,PWM
pwm = PWM(Pin(15, Pin.OUT), freq=500)
pwm.duty(512)

上面代码即是声明使用GPIO15来输出PWM,参数为频率500、占空比50%(上面提到过ESP8266最大duty1023,512即为50%的占空比),使用Europa开发板的D8接口来输出信号,顺便验证一下电压值是不是我们预期的

esp32 获取脉冲 esp8266脉冲_esp32 获取脉冲_04


Europa开发板的D8接口有三个端子输出,红黑是VCC/GND输出,黄线是管脚引线。测量电压红黑是3.3V,黄黑是1.64V。这就验证了前面说的占空比改变电压的说法。

esp32 获取脉冲 esp8266脉冲_esp32 获取脉冲_05

另外一个要注意的,在代码编写中,如果不再需要使用管脚输出PWM模式时,需要释放前面的对象

pwm.deinit()

释放后该管脚就可以继续当作I/O使用了。

4. 实验:呼吸灯

4.1 调节Europa板载LED灯亮度

Europa开发板的板载LED占用的GPIO2管脚,且采用反接的方式焊接,要点亮灯时需要给2管脚输出低电平。

from machine import Pin
led = Pin(2, Pin.OUT)
led.value(0)

将该板载板改为用PWM模式来控制亮度(也要注意反接模式下控制参数)

from machine import Pin,PWM
led = PWM(Pin(2, Pin.OUT), freq=500)
led.duty(500)   # 中间电压,半亮
led.duty(1000)  # 接近低电压,微微亮
led.duty(10)    # 接近高电压,几乎全亮

哦,对了,一直没说freq参数的效果,这个指的是频率(每秒输出多少个周期脉冲),转换为led灯每秒闪几次就方便理解了

from machine import Pin,PWM
led = PWM(Pin(2, Pin.OUT), freq=500)
led.duty(500)   # 半亮
led.freq(500)  # 看不出什么
led.freq(50)   # 有点想抖动的感觉
led.freq(2)   # 每秒闪两下。。。。 有点手机消息提示闪灯的感觉了

4.2 板载LED呼吸灯

我们还是不要让led灯闪了,改成明暗交替变换的呼吸灯,模拟手机有未接来电的那种情况

from machine import Pin,PWM
pwm = PWM(Pin(2, Pin.OUT), freq=500)

def pulse(l, t):
    for i in range(20):
        l.duty(int(math.sin(i/10 * math.pi) * 500 + 500))
        time.sleep_ms(t)
        
pulse(pwm, 200)  # 让板载灯明暗变化一次
pwm.deinit()

一次看不出效果的话,就改成循环

while 1:
	pluse(pwm, 200)

手上没有其它可调节的电机、风扇什么的,就没办法继续做实验了。原理都是一样的,改变频率周期和改变电压。