入坑树莓派-02-LED灯控制
1.单色LED灯
点亮单色LED灯无需安装任何库,直接shell命令行就行。
这几个LED灯都连接在树莓派的GPIO(General-Purpose Input/Output)端口上:
端口明细如下:
通过翻阅扩展版的资料,我们了解到这几个灯连接在这几个端口上(即上图中NAME中的GPIO17,不是上图中的Pin17):
这样,我们就能通过控制这几个GPIO端口的电平高低来实现控制LED的亮和灭了。
控制GPIO的电平,用shell命令就能实现。
cd /sys/class/gpio/
echo 17 > export # 打开端口17
echo out > gpio17/direction # 将端口17设置为电平输出模式
echo 1 > gpio17/value # 将端口17设置为高电平
执行上述代码后,我们发现红色LED灯已经点亮了:
要想关掉也很简单,把端口17置为低电平即可(最后,如果17端口不用的话,可以直接关掉):
echo 0 > gpio17/value # 将端口17设置为低电平
echo 17 > unexport
同理,我们可以分别控制其他端口,来达到控制其他LED灯的目的。
用程序也能控制。
python版本:
import RPi.GPIO as GPIO
import time
# LED GPIO端口 17
LED_PIN = 17
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
# 设置端口为输出模式
GPIO.setup(LED_PIN, GPIO.OUT)
# 电平设置为高,点亮LED,1秒后关闭
GPIO.output(LED_PIN, GPIO.HIGH)
time.sleep(1)
GPIO.output(LED_PIN, GPIO.LOW)
C语言版本:
#include <bcm2835.h>
#include <stdio.h>
// gcc -o blink blink.c -lbcm2835
#define PIN_R 17 // 红色LED灯GPIO端口
#define PIN_Y 27 // 黄
#define PIN_G 22 // 绿
#define PIN_B 5 // 蓝
int main(int argc, char **argv)
{
if (!bcm2835_init())
return 1;
bcm2835_gpio_fsel(PIN_R, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_fsel(PIN_Y, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_fsel(PIN_G, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_fsel(PIN_B, BCM2835_GPIO_FSEL_OUTP);
while (1)
{
bcm2835_gpio_write(PIN_R, HIGH); // 开灯
bcm2835_delay(50);
bcm2835_gpio_write(PIN_R, LOW); // 关灯
bcm2835_gpio_write(PIN_Y, HIGH);
bcm2835_delay(50);
bcm2835_gpio_write(PIN_Y, LOW);
bcm2835_gpio_write(PIN_G, HIGH);
bcm2835_delay(50);
bcm2835_gpio_write(PIN_G, LOW);
bcm2835_gpio_write(PIN_B, HIGH);
bcm2835_delay(50);
bcm2835_gpio_write(PIN_B, LOW);
}
bcm2835_close();
return 0;
}
注意:C语言需要安装函数库文件,从这里下载编译安装即可:
tar czvf bcm2835-1.73.tar.gz
cd bcm2835-1.73
./configure
make -j
make install
*树莓派的SOC是博通(Broadcom)的,因此需安装博通官方提供的函数库。
2.全彩LED灯
接下来我们控制这几个灯:
这几个灯是有型号的,叫:WS2812,控制它们需要安装一个特殊的函数库rpi_ws281x,使用下面的命令安装他们:
pip install rpi_ws281x
然后运行示例程序即可看到跑马灯的效果:
import time
from rpi_ws281x import Adafruit_NeoPixel, Color
# LED 灯条配置
LED_COUNT = 6 # 灯珠数量
LED_PIN = 12 # GPIO引脚
LED_FREQ_HZ = 800000 # LED信号频率(通常都是800KHz)
LED_DMA = 10 # 用于产生信号的DMA信道
LED_BRIGHTNESS = 2 # 亮度:0最低,255最高
LED_INVERT = False # 是否反转信号
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS)
while True:
strip.begin()
# 顺序点亮,蓝色渐变
for i in range(0, LED_COUNT):
strip.setPixelColor(i, Color(0,0,255))
strip.setPixelColor(i-1, Color(0,0,200))
strip.setPixelColor(i-2, Color(0,0,150))
strip.setPixelColor(i-3, Color(0,0,100))
strip.setPixelColor(i-4, Color(0,0,50))
strip.setPixelColor(i-5, Color(0,0,0))
strip.show()
time.sleep(0.05)
#逆序,绿色
for i in range(0, LED_COUNT):
strip.setPixelColor(LED_COUNT-i, Color(0,255,0))
strip.show()
time.sleep(0.05)
#再逆序,红色
for i in range(0,LED_COUNT):
strip.setPixelColor(i, Color(255,0,0))
strip.show()
time.sleep(0.05)
3.呼吸灯
呼吸灯是这个:
控制这个灯,比前面的几个麻烦些。
首先,它需要在树莓派上开启I2C总线(使用raspi-config命令):
然后需要安装两个库:
# 安装
apt-get install i2c-tools
apt-get install python-smbus
# 赋权
usermod -aG i2c root
执行下面的命令就可以看到连接在I2C总线的元件地址了:
可以看到有两个地址,其中0x48就是我们要点亮的LED地址了,0x3c是OLD屏幕,我们将在下一篇文章中用到。
然后运行示例程序即可看到效果:
import smbus
import time
addr = 0x48 #LED的I2C总线地址
cmd = 0x40
bus = smbus.SMBus(1)
bright = 0 # 亮度:0~255
while True:
bus.write_byte_data(addr, cmd, bright)
bright += 1
if bright == 255:
bright = 0
time.sleep(0.003)
C语言版本的代码:
#include <bcm2835.h>
#include <unistd.h>
// gcc -o breathled breathled.c -lbcm2835
int main(int argc, char **argv)
{
if (!bcm2835_init())
return -1;
bcm2835_i2c_begin();
bcm2835_i2c_setSlaveAddress(0x48); // 通信地址
bcm2835_i2c_set_baudrate(10000); // 波特率
char busbuf[2] = {0, 0};
unsigned char bright = 0;
unsigned char direct = 1;
while(1)
{
busbuf[0] = 0x40; // LED灯的地址
busbuf[1] = bright; // 灯的亮度
bcm2835_i2c_write(busbuf, 2);
bcm2835_delay(5);
if (direct)
++bright;
else
--bright;
if (bright == 0 || bright == 255)
direct = direct ? 0 : 1;
}
bcm2835_i2c_end();
bcm2835_close();
return 0;
}
补充知识:I2C和smbus
其实,控制这个呼吸灯之所以复杂,是因为它用的是模拟信号,而树莓派的GPIO只能输出电信号,将电信号转换为模拟信号需要一个芯片,我们用的是扩展板中PCF8591芯片,上述代码其实就是通过I2C总线将树莓派的电信号传递给PCF8591芯片,然后由其将数字信号转换为模拟信号,以点亮LED灯。
附:PCF8591芯片位置