Catalog
  1. 树莓派记5 (控制LED进阶篇)
    1. 1. 控制LED闪烁
    2. 2. LED呼吸灯
    3. 3. 控制RGB LED
树莓派记5

树莓派记5 (控制LED进阶篇)

干,为什么我一天要写两篇技术博客啊,英语博客都没怎么勤。

这篇大量借鉴芒果大大的博客

  1. 控制LED闪烁
  2. LED呼吸灯
  3. 控制RGB LED

1. 控制LED闪烁

发光原理:与其它二极管一样,发光二极管中电流可以轻易地从p极(阳极)流向n极(阴极),而相反方向则不能。两种不同的载流子:空穴和电子在不同的电极电压作用下从电极流向p、n架构。当空穴和电子相遇而产生复合,电子会跌落到较低的能阶,同时以光子的模式释放出能量(光子也即是我们常称呼的光)。

因为LED需要3-3.3V的光才可以点亮,所以我只要把GPIO从高电平(>3.5V)设置到低电平(<0.4V)LED就会灭。

线路:

代码:

# encoding: utf-8

import RPi.GPIO
import time

# 指定GPIO口的选定模式为GPIO引脚编号模式(而非主板编号模式)
RPi.GPIO.setmode(RPi.GPIO.BCM)

# 指定GPIO14(就是LED长针连接的GPIO针脚)的模式为输出模式
# 如果上面GPIO口的选定模式指定为主板模式的话,这里就应该指定8号而不是14号。
RPi.GPIO.setup(14, RPi.GPIO.OUT)

# 循环10次
for i in range(0, 10):
# 让GPIO14输出高电平(LED灯亮)
RPi.GPIO.output(14, True)
# 持续一段时间
time.sleep(0.5)
# 让GPIO14输出低电平(LED灯灭)
RPi.GPIO.output(14, False)
# 持续一段时间
time.sleep(0.5)

# 最后清理GPIO口(不做也可以,建议每次程序结束时清理一下,好习惯)
RPi.GPIO.cleanup()

效果:

2. LED呼吸灯

原理说明:
我们知道,通过LED的电流越大,LED越亮,电流越小,LED越暗。如果可以控制输出电流大小就可以控制LED的明暗了。
但是树莓派的各引脚并没有直接调整输出电流大小的功能。要想别的办法。


我们先学习一个名词:脉宽调制(PWM)
简单的说,PWM技术就是不停的通断电路并控制通断持续的时间片段长度来控制用电器在单位时间内实际得到的电能。

这么说好像还是复杂了,再简单点说,如果你的手足够快,打开电灯开关后马上关闭,如果这个时间间隔足够短,灯丝还没有全部亮起来就暗下去了。你再次打开电灯再关闭,再打开再关闭。。。如果你一直保持相同的频率,那么电灯应该会保持一个固定的亮度不变。理论上,你可以通过调整开灯持续的时间长度和关灯持续的时间长度的比例就能得到不同亮度了。这个比例被称为“占空比”。


PWM就是差不多这个意思。
树莓派1代B型的26个针脚里,有一个特殊的GPIO口是支持硬件PWM的,不过从B+开始不知道什么原因这个很实用的接口被去掉了。


但是没关系,根据我上面的描述,我们完全可以自己写一个程序来模拟PWM。
不想自己写,没关系,我们强大的GPIO库已经帮我们写好了,直接用就可以了。

连接不变,改代码

# encoding: utf-8

import RPi.GPIO
import time

# 指定GPIO口的选定模式为GPIO引脚编号模式(而非主板编号模式)
RPi.GPIO.setmode(RPi.GPIO.BCM)

# 指定GPIO14(就是LED长针连接的GPIO针脚)的模式为输出模式
# 如果上面GPIO口的选定模式指定为主板模式的话,这里就应该指定8号而不是14号。
RPi.GPIO.setup(14, RPi.GPIO.OUT)

# 循环10次
for i in range(0, 10):
# 让GPIO14输出高电平(LED灯亮)
RPi.GPIO.output(14, True)
# 持续一段时间
time.sleep(0.5)
# 让GPIO14输出低电平(LED灯灭)
RPi.GPIO.output(14, False)
# 持续一段时间
time.sleep(0.5)

# 最后清理GPIO口(不做也可以,建议每次程序结束时清理一下,好习惯)
RPi.GPIO.cleanup()
pi@raspberrypi:~/GPIO $ cat LED2.py
import RPi.GPIO
import time

RPi.GPIO.setmode(RPi.GPIO.BCM)
RPi.GPIO.setup(12, RPi.GPIO.OUT)

# 创建一个 PWM 实例,需要两个参数,第一个是GPIO端口号,这里我们用14号
# 第二个是频率(Hz),频率越高LED看上去越不会闪烁,相应对CPU要求就越高,设置合适的值就可以
pwm = RPi.GPIO.PWM(12, 80)

# 启用 PWM,参数是占空比,范围:0.0 <= 占空比 >= 100.0
pwm.start(0)

try:
while True:
# 电流从小到大,LED由暗到亮
for i in range(0, 101, 1):
# 更改占空比,
pwm.ChangeDutyCycle(i)
time.sleep(.02)

# 再让电流从大到小,LED由亮变暗
for i in range(100, -1, -1):
pwm.ChangeDutyCycle(i)
time.sleep(.02)

# 最后一段是一个小技巧。这个程序如果不强制停止会不停地执行下去。
# 而Ctrl+C强制终端程序的话,GPIO口又没有机会清理。
# 加上一个try except 可以捕捉到Ctrl+C强制中断的动作,
# 试图强制中断时,程序不会马上停止而是会先跳到这里来做一些你想做完的事情,比如清理GPIO口。
except KeyboardInterrupt:
pass

# 停用 PWM
pwm.stop()

# 清理GPIO口
RPi.GPIO.cleanup()

效果:

3. 控制RGB LED

首先,我这里的RGP LED是灯管,不是模块。 其次要分清楚你的灯管是共阴的还是共阳的。市面上大部分是共阴的。也就是说长脚连地(GND)。

电路图:

代码:

# encoding: utf-8

import RPi.GPIO
import time

R,G,B=17,27,22

RPi.GPIO.setmode(RPi.GPIO.BCM)

RPi.GPIO.setup(R, RPi.GPIO.OUT)
RPi.GPIO.setup(G, RPi.GPIO.OUT)
RPi.GPIO.setup(B, RPi.GPIO.OUT)

pwmR = RPi.GPIO.PWM(R, 70)
pwmG = RPi.GPIO.PWM(G, 70)
pwmB = RPi.GPIO.PWM(B, 70)

pwmR.start(0)
pwmG.start(0)
pwmB.start(0)

try:

t = 0.4
while True:
# 红色灯全亮,蓝灯,绿灯全暗(红色)
pwmR.ChangeDutyCycle(0)
pwmG.ChangeDutyCycle(100)
pwmB.ChangeDutyCycle(100)
time.sleep(t)

# 绿色灯全亮,红灯,蓝灯全暗(绿色)
pwmR.ChangeDutyCycle(100)
pwmG.ChangeDutyCycle(0)
pwmB.ChangeDutyCycle(100)
time.sleep(t)

# 蓝色灯全亮,红灯,绿灯全暗(蓝色)
pwmR.ChangeDutyCycle(100)
pwmG.ChangeDutyCycle(100)
pwmB.ChangeDutyCycle(0)
time.sleep(t)

# 红灯,绿灯全亮,蓝灯全暗(黄色)
pwmR.ChangeDutyCycle(0)
pwmG.ChangeDutyCycle(0)
pwmB.ChangeDutyCycle(100)
time.sleep(t)

# 红灯,蓝灯全亮,绿灯全暗(洋红色)
pwmR.ChangeDutyCycle(0)
pwmG.ChangeDutyCycle(100)
pwmB.ChangeDutyCycle(0)
time.sleep(t)

# 绿灯,蓝灯全亮,红灯全暗(青色)
pwmR.ChangeDutyCycle(100)
pwmG.ChangeDutyCycle(0)
pwmB.ChangeDutyCycle(0)
time.sleep(t)

# 红灯,绿灯,蓝灯全亮(白色)
pwmR.ChangeDutyCycle(0)
pwmG.ChangeDutyCycle(0)
pwmB.ChangeDutyCycle(0)
time.sleep(t)

# 调整红绿蓝LED的各个颜色的亮度组合出各种颜色
for r in range (0, 101, 20):
pwmR.ChangeDutyCycle(r)
for g in range (0, 101, 20):
pwmG.ChangeDutyCycle(g)
for b in range (0, 101, 20):
pwmB.ChangeDutyCycle(b)
time.sleep(0.01)

except KeyboardInterrupt:
pass

pwmR.stop()
pwmG.stop()
pwmB.stop()

RPi.GPIO.cleanup()

效果:

终于写完了。累死了,果然晚上有灵感。已经0:26了。圣诞节的树莓派内容应该已经完结了。完结撒花,我睡觉去了。

Author: Peter Duan
Link: https://peter-duan.github.io/hexo/2019/12/22/raspberrypi-5/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.

Comment