前面的编程里只能给led灯设置1或0,如何控制其明暗?
按照物理原理,通过LED的电流越大,LED越亮;电流越小,LED越暗。如果可以控制输出电流大小就可以控制LED的明暗了。但是树莓派及Pico的各引脚并没有直接调整输出电流大小的功能。还得想其它办法。
这里要用到PWM技术了,PWM是指脉冲宽度调制(Pulse Width Modulation),简称脉宽调制(PWM)。
先读一下百度的解释:
脉冲宽度调制是一种模拟控制方式,根据相应载荷的变化来调制晶体管基极或MOS管栅极的偏置,来实现晶体管或MOS管导通时间的改变,从而实现开关稳压电源输出的改变。这种方式能使电源的输出电压在工作条件变化时保持恒定,是利用微处理器的数字信号对模拟电路进行控制的一种非常有效的技术。脉冲宽度调制是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。
读完它,我是没看懂。实际上,PWM技术就是不停地通断电路并控制通电和断电的持续时间来控制电器在单位时间内实际得到的电能。这篇文章有个类比挺容易理解:
如果你的手足够快,打开电灯开关后马上关闭,如果这个时间间隔足够短,灯丝还没有全部亮起来就暗下去了。你再次打开电灯再关闭,再打开再关闭……如果你一直保持相同的频率,那么电灯会保持一个固定的亮度不变。理论上,你可以通过调整开灯持续的时间长度和关灯持续的时间长度的比例就能得到不同亮度了。这个比例被称为“占空比(duty cycle)”。
树莓派4B和Pico都支持GPIO的PWM控制,可以利用PWM技术实现板载LED灯的呼吸灯的效果,即忽明忽暗的效果。
import machine import utime pwm = machine.PWM(machine.Pin(25)) pwm.freq(1000) duty = 0 direction = 1 while True: duty += direction if duty > 255: duty = 255 direction = -1 elif duty < 0: duty = 0 direction = 1 pwm.duty_u16(duty * duty) utime.sleep(0.002)
MicroPython里已经有PWM类直接可用,duty_u16(int dc)可以设置占空比,参数是0到65535的整数,dc / 65535.0就是占空比。
注意代码是个死循环,停止程序后,Pico没有回到初始状态。搞的我的MicroPython也有点不太正常。
再来用一张图理解占空比的具体含义,当引脚电压为3.3V,占空比为25%时,LED上的电压约为3.3V * 0.25 = 0.825V。如果频率设置为1000Hz,则这里的period为0.001秒,即1毫秒。
import machine import utime pwm = machine.PWM(machine.Pin(25)) pwm.freq(1000) duty = 0 direction = 1 try: while True: duty += direction if duty > 255: duty = 255 direction = -1 elif duty < 0: duty = 0 direction = 1 pwm.duty_u16(duty * duty) utime.sleep(0.002) # 最后一段是一个小技巧。这个程序如果不强制停止会不停地执行下去。 # 而Ctrl+C强制终端程序的话,GPIO口又没有机会清理。 # 加上一个try except 可以捕捉到Ctrl+C强制中断的动作, # 试图强制中断时,程序不会马上停止而是会先跳到这里来做一些你想做完的事情,比如清理GPIO口。 except KeyboardInterrupt: pass machine.Pin(25).off() pwm.deinit()
视频效果:
https://v.qq.com/x/page/j3279kxpkjj.html