PWM脉冲宽度调制

我们已经可以用GPIO控制LED灯一闪一闪亮晶晶了,这样只有亮和灭的状态似乎还是太简单了,能不能对LED的亮度进行调整呢?

当然没问题,这就要用到接下来学习的PWM脉冲宽度调制了。

PWM脉冲宽度调制原理

在GPIO的数字输入和输出模式中,只有高低电平,高电平一般是3.3V或者5V,低电平就是0V,如果我想要一个折中一点的电压怎么办呢?PWM大家了解一下。

PWM,全称是脉冲宽度调制**,**是一种对模拟信号电平进行数字编码的方法,通过高分辨率计数器,调制出一定占空比的方波,通过这种方式对模拟信号的电平进行编码。
通俗点来说,如果我们有一个10W的灯泡,在一个小时中亮了半个小时,那我们宏观来看,它在这一个小时中的功率就是5W,这样就相当于是它的电压被降低了。而我们还可以通过改变这一个小时中,灯泡被点亮的时长,来等效出不同的电压。

然后,我们把一个小时缩短为很小的一个时间,到达一定的微分程度,表现出来的就是电压的变化,而这个很小的时间,就是PWM频率的倒数,被点亮的时间在这个很小的时间中所占的百分比就叫做占空比。

这里大家也要注意,虽然PWM在尽力呈现出模拟信号的样子,但本质还是数字信号,因为在给定的某一任何时刻,引脚只能高电平或者低电平。
通过PWM技术,可以让数字电路产生类似模拟信号的效果,从而实现类似的无级控制,比如风扇的转速,或者屏幕的亮度,很多都是通过PWM技术实现的调节。

PWM编程

接下来我们就来试一试,通过PWM让一个LED实现不同亮度的变化,也就是我们常见的呼吸灯了。

硬件接线

还是用这个LED灯,一端连接电阻,再到5V高电平的引脚,另外一端,接到33号引脚的PWM接口。

运行示例程序

大家先来运行例程,看看效果如何。
bash
$ sudo python3 simple_pwm.py

我们来看一下实物的操作,按照刚才的设置,将实物连接完成,然后连接到X3Pi,运行刚才的程序。就可以看到这样的一个呼吸灯的效果了。

代码解析

simple_pwm.py:
python
#!/usr/bin/env python3

import Hobot.GPIO as GPIO
import time

# 支持PWM的管脚: 32 and 33, 在使用PWM时,必须确保该管脚没有被其他功能占用
output_pin = 33

def main():
    # Pin Setup:
    # Board pin-numbering scheme
    GPIO.setmode(GPIO.BOARD)
    # 支持的频率范围: 48KHz ~ 192MHz
    p = GPIO.PWM(output_pin, 48000)
    # 初始占空比 25%, 先每0.25秒增加5%占空比,达到100%之后再每0.25秒减少5%占空比
    val = 25
    incr = 5
    p.ChangeDutyCycle(val)
    p.start(val)

    print("PWM running. Press CTRL+C to exit.")
    try:
        while True:
            time.sleep(0.25)
            if val >= 100:
                incr = -incr
            if val <= 0:
                incr = -incr
            val += incr
            p.ChangeDutyCycle(val)
    finally:
        p.stop()
        GPIO.cleanup()

if __name__ == '__main__':
    main()

一样的引入GPIO的库,然后设置管脚编码模式为BOARD,然后创建一个PWM的实例化对象p,同时设置他的频率,之后就可以通过ChangeDutyCycle来改变他的占空比,在循环当中,占空比大于等于100时,就会以5%的梯度减小;当小于等于0时,就会以5%的梯度增大。