很早之前就有写过使用 Arduino 开发板(C++) 和 树莓派的 GPIO(Python) 控制 LED 灯相关示例,只是比较的零碎,完全是个人兴趣驱动,当时过程中遇到的一些问题,也没有很好的记录下来,由于当时比较懒吧(不过,现在仍是依旧)。

  最近由于工作需要,于是乎又拾起了兴趣,拼凑了一个相对比较完善的示例,过程中也入了一些坑,由于对 RGB 全彩 LED 特性不是很了解,特别在调试时,用了不少时间,真的是眼睛快被闪瞎了!

  之所以能更加完善,完全是因为需要为组内来一场生动的分享(是不是真的生动,我也无从而知了),分享主题为 趣玩 Python,Python 还能玩 LED?嗯,是的,既然是趣玩,当然是拿些大家不太熟悉,但又不太陌生的东东来玩玩吖,于是乎我拿出了百分之一百二精力,一个月的时间里,时常搞到凌晨一二点,第二天又需早早爬起来上班,当然啦,该示例只是其中之一,其实在较早的时候,这样的作息也属于常态,加班几乎成为了程序员的代名词,问我累不累,不,怎么会累呢,一切为工作!哈哈,价值观还可以吧!其实更多的是习惯了这样的生活,也就不觉得怎样了!

  好了,回归正题,先了解一下,示例中使用的元件 树莓派、RGB LED、220Ω 电阻、面包板,公母杜邦线,开发语言是 Python (Python 分 2.X 版本 和 3.X 版本,语法上是有区别的,示例使用的 Python3.X 版本),不得不说,这是我做过的 PPT 中最好看和最满意的了。

 
  了解过 树莓派 的同学应该知道,树莓派之所以很畅销,个人认识最大的原因是树莓派集成了 丰富的 GPIO(General Purpose Input-Output),它们是程序与外部世界对话的窗口,增强了趣味性。再有就是强大的开源社区以及第三方对树莓派大力支持,这也是当下最有趣味的板子之一。本示例是使用 Python,树莓派搭载的系统是基于 Debian Stretch 的 Raspbian,Python 和 Linux 有者强大的开源社区。掌握了这两样工具的工具(元工具),网上遍地是趁手的兵器。先让我们了解一下树莓派的 GPIO 引脚。

  RGB LED 多元的特性,可以通过程序实现色彩绚丽灯光效果,不过,在使用之前需要先确认一下手中的 RGB LED 是共阴还是共阳,所谓共阴就是公共端接负极 -,而共阳就是公共端接正极 +,一般商品介绍上会有说明,或者如果看到 RGB LED 的引脚有 GND 字样,说明是共阴的,也可以自行测试;这点很重要,这会影响接下来的灯光效果实现及调试。调试时建议串连一个 220Ω 的电阻,防止因电流过大而烧坏了 RGB LED。

   首先确保树莓派安装了 Python3.X ,一般系统会自带 Pthon2.7 以及 RPi.GPIO 模块程序包(该包提供了一个在 Raspberry Pi 中控制 GPIO 的类),如果未安装,则执行 sudo apt-get install python3 进行安装 Python3,执行 sudo apt-get install RPi.GPIO 安装 RPi.GPIO 模块程序包(Python 是区分大小写的,你没看错,就是 RPi.GPIO ,i 是小写的,写错了会报错的),必要的软件安装好,就可以愉快的编码了。

  开始之前还是需要再了解一下 PWM,PWM 脉冲宽度调制的英文缩写,在一个脉冲循环内,通电时间相对于总时间所占的比例叫占空比,方波的占空比为50%,占空比为0.5,说明正电平所占时间为0.5个周期。是不是似懂非懂,在本示例只需要知道 PWM 可以控制 RGB LED 亮度即可,但真正做一个产品时,对相关知识点不能完全明白的掌握,会遇到不少麻烦,也是会有很大的风险的。

  相信很多同学对万能充电器,在熟悉不过了,此时就不得不说那时是 诺基亚 王朝,是否还记得高中时为了给手机充器,不得不像防贼似的防着班主任,话说你的东东有没有被班主任撞见过呢!对,该示例就是实现那迷人的万能充电器里面的跑马灯,嗯,那我们开始吧,执行 sudo nano led.py 创建一个名称为 led.py 文件, 将下面的代码复制到该文件中保存,执行 sudo python led.py 就可以看到效果了,聪明的你对 RGB LED 的接线应该不在话下吧,具体示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
import time
import random
# 指定引脚 共阴LED(R、G、B、-)
R, G, B, GND = 11, 13, 15, 9
# BOARD 编码方式
GPIO.setmode(GPIO.BOARD)
# 设置引脚为输出模式
GPIO.setup(R, GPIO.OUT)
GPIO.setup(G, GPIO.OUT)
GPIO.setup(B, GPIO.OUT)
# PWM 来制作呼吸灯效果,创建频率为 70HZ 的 PWM 实例
pwmR = GPIO.PWM(R, 70)
pwmG = GPIO.PWM(G, 70)
pwmB = GPIO.PWM(B, 70)
# 开始脉宽调制,参数范围为: (0.0 <= dc <= 100.0)
# 共阴时,方波的占空比 100 代表全亮,0 代表全暗
# 共阳时,方波的占空比 100 代表全暗,0 代表全亮
pwmR.start(50)
pwmG.start(50)
pwmB.start(50)
def open_led():
"""开启 LED"""
try:
count = 0
while True:
count = count + 1
if count > 1:
return
t = 0.4
# 红色灯全亮,绿灯,蓝灯全暗(红色)
set_change_duty_cycle(100, 0, 0, t)
# 绿色灯全亮,红灯,蓝灯全暗(绿色)
set_change_duty_cycle(0, 100, 0, t)
# 蓝色灯全亮,红灯,绿灯全暗(蓝色)
set_change_duty_cycle(0, 0, 100, t)
# 红灯,绿灯全亮,蓝灯全暗(黄色)
set_change_duty_cycle(100, 100, 0, t)
# 红灯,蓝灯全亮,绿灯全暗(洋红色)
set_change_duty_cycle(100, 0, 100, t)
# 绿灯,蓝灯全亮,红灯全暗(青色)
set_change_duty_cycle(0, 100, 100, t)
# 红灯,绿灯,蓝灯全亮(白色)
set_change_duty_cycle(100, 100, 100, t)
# 调整红绿蓝LED的各个颜色的亮度组合出各种颜色
for_set_change_duty_cycle()
except Exception as e:
print(e)
finally:
stop()
def set_change_duty_cycle(_r, _g, _b, _t):
"设置 RGB 亮度"
pwmR.ChangeDutyCycle(_r)
pwmG.ChangeDutyCycle(_g)
pwmB.ChangeDutyCycle(_b)
time.sleep(_t)
def set_single_change_duty_cycle(_pwm, _l, _t):
"""设置单 RGB 亮度"""
_pwm.ChangeDutyCycle(_l)
time.sleep(_t)
def for_set_change_duty_cycle():
"设置 RGB 亮度-跑马灯"
t = 0.01
pwmG.ChangeDutyCycle(0)
pwmB.ChangeDutyCycle(0)
for r in range(0, 101, 1): # 红全亮,绿、蓝全暗
set_single_change_duty_cycle(pwmR, r, t)
for r in range(0, 101, 1): # 红、绿、蓝全暗
set_single_change_duty_cycle(pwmR, 100 - r, t)
pwmR.ChangeDutyCycle(0)
pwmB.ChangeDutyCycle(0)
for g in range(0, 100, 1): # 绿全亮,红、蓝全暗
set_single_change_duty_cycle(pwmG, g, t)
for g in range(0, 100, 1): # 红、绿、蓝全暗
set_single_change_duty_cycle(pwmG, 100 - g, t)
pwmR.ChangeDutyCycle(0)
pwmG.ChangeDutyCycle(0)
for b in range(0, 101, 1): # 蓝全亮,红、绿全暗
set_single_change_duty_cycle(pwmB, b, t)
for b in range(0, 101, 1): # 红、绿、蓝全暗
set_single_change_duty_cycle(pwmB, 100 - b, t)
count, denominator = 0, 7
for n in range(0, 101, 10):
print(n)
count += 1
if count % denominator == 0: # 红全亮,绿、蓝全暗
for g in range(0, 101, 1):
set_change_duty_cycle(g, g, 100 - g, t)
for g in range(0, 101, 1):
set_single_change_duty_cycle(pwmG, 100 - g, t)
if count % denominator == 1: # 绿全亮,红、蓝全暗
for b in range(0, 101, 1):
set_change_duty_cycle(100 - b, b, b, t)
for b in range(0, 101, 1):
set_single_change_duty_cycle(pwmB, 100 - b, t)
if count % denominator == 2: # 蓝全亮,红、绿全暗
for r in range(0, 101, 1):
set_change_duty_cycle(r, 100 - r, r, t)
for r in range(0, 101, 1):
set_single_change_duty_cycle(pwmR, 100 - r, t)
if count % denominator == 3: # 红全亮
for g in range(0, 101, 1):
set_single_change_duty_cycle(pwmR, g, t)
if count % denominator == 4: # 绿全亮
for b in range(0, 101, 1):
set_single_change_duty_cycle(pwmG, b, t)
if count % denominator == 5: # 红、绿、蓝全暗
for r in range(0, 101, 1):
set_change_duty_cycle(100 - r, 100 - r, 100 - r, t)
if count % denominator == 6: # 红、绿、蓝全暗
set_change_duty_cycle(50, 50, 50, t)
for r in range(0, 61, 1): # 红、绿、蓝随机
set_change_duty_cycle(random.choice([0, 50, 0, 0, 100, 0, 100]), random.choice(
[100, 50, 0, 0, 100, 100, 0, 0]), random.choice([50, 50, 50, 0, 100, 0, 100]), t + 0.08)
for r in range(0, 101, 1): # 红、绿、蓝全暗
set_change_duty_cycle(100 - r, 100 - r, 100 - r, t)
for r in range(0, 101, 1): # 红、绿、蓝全暗
set_change_duty_cycle(100 - r, 100 - r, 100 - r, t)
def stop():
"""停止闪烁,并释放资源"""
pwmR.stop()
pwmG.stop()
pwmB.stop()
GPIO.cleanup() # 防止烧坏板子
if __name__ == "__main__":
open_led()

 
参考文档: