4. GPIO 输出控制实战:用 Python 控制树莓派点亮 LED 与呼吸灯

这一章我们终于要动手了。说实话,我每次带新人入门嵌入式,第一件事就是让他们点亮一颗 LED。为什么?因为这是最直观的反馈——代码写对了,灯就亮;写错了,灯不亮。没有比这更实在的调试手段了。

咱们这一章的目标很明确:用 Python 控制树莓派的 GPIO 引脚,先让 LED 亮起来,再让它呼吸起来。你想想看,一个呼吸灯效果,其实就涵盖了 PWM 的核心原理。

4.1 硬件准备与电路连接

先看看我们需要什么。别小看这些物料,我在项目里吃过亏——有一次就是因为用了劣质面包板,接触不良,查了整整一下午的 bug。

元件 规格 数量 备注
树莓派 3B+/4B/Zero 2W 1 GPIO 引脚需完好
LED 5mm,颜色任意 1 推荐红色或蓝色
电阻 220Ω ~ 330Ω 1 限流用,不可省略
杜邦线 母对母 2 长度 10-20cm
面包板 半尺寸 1 方便搭建

连接方式很简单:LED 长脚(阳极)通过电阻接到树莓派的 GPIO 引脚,短脚(阴极)接到 GND。我个人习惯用 GPIO 18(物理引脚 12),因为这个引脚支持硬件 PWM,后面做呼吸灯会方便很多。

⚠️ 重要提醒: 千万别把 LED 直接接到 3.3V 或 5V 上!没有限流电阻的话,LED 瞬间就会烧掉。我曾经见过一个学员,一上电 LED 就冒烟了——电阻的钱不能省。

4.2 软件环境准备

树莓派上做 Python GPIO 控制,主流方案有两个:RPi.GPIO 和 gpiozero。我个人更推荐 gpiozero,因为它封装得更高级,代码写起来更简洁。但 RPi.GPIO 更底层,适合理解原理。这一章我们两个都用,你感受一下区别。

先安装库:

# 更新系统
sudo apt update
sudo apt upgrade -y

# 安装 RPi.GPIO(通常系统自带)
sudo apt install python3-rpi.gpio -y

# 安装 gpiozero
sudo apt install python3-gpiozero -y
💡 小技巧: 如果你用的是树莓派 5,注意 RPi.GPIO 可能不兼容。这时候可以用 gpiozero 或者 rpi-lgpio 替代。我去年做项目时就踩过这个坑,树莓派 5 刚出来时 RPi.GPIO 还没适配。

4.3 点亮 LED:最简单的 GPIO 输出

先来一个最基础的——让 LED 常亮。这其实就是把 GPIO 引脚拉高,输出 3.3V 电平。

用 RPi.GPIO 实现:

import RPi.GPIO as GPIO
import time

# 设置引脚编号模式为 BCM
GPIO.setmode(GPIO.BCM)

# 定义 LED 引脚
LED_PIN = 18

# 设置引脚为输出模式
GPIO.setup(LED_PIN, GPIO.OUT)

# 输出高电平,点亮 LED
GPIO.output(LED_PIN, GPIO.HIGH)

# 保持 5 秒
time.sleep(5)

# 关闭 LED
GPIO.output(LED_PIN, GPIO.LOW)

# 清理 GPIO 资源
GPIO.cleanup()

用 gpiozero 实现:

from gpiozero import LED
from time import sleep

# 创建 LED 对象,指定引脚
led = LED(18)

# 点亮
led.on()
sleep(5)

# 熄灭
led.off()

看到了吗?gpiozero 的代码量少了一半。但 RPi.GPIO 让你更清楚地看到每一步在做什么——设置模式、配置引脚、输出电平。我个人建议初学者先用 RPi.GPIO 跑一遍,理解底层逻辑,再用 gpiozero 提高效率。

4.4 闪烁 LED:理解时间控制

闪烁其实就是亮灭交替,中间加延时。这个看似简单,但延时精度在实际项目中很关键。

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
LED_PIN = 18
GPIO.setup(LED_PIN, GPIO.OUT)

try:
    while True:
        GPIO.output(LED_PIN, GPIO.HIGH)
        time.sleep(0.5)   # 亮 0.5 秒
        GPIO.output(LED_PIN, GPIO.LOW)
        time.sleep(0.5)   # 灭 0.5 秒
except KeyboardInterrupt:
    pass
finally:
    GPIO.cleanup()
🔑 关键点: time.sleep() 是阻塞的,也就是说在延时期间程序做不了其他事。如果你需要同时处理多个任务(比如一边闪灯一边读传感器),就得用多线程或异步。这个我们后面章节会讲。

4.5 呼吸灯效果:PWM 原理与实现

呼吸灯,说白了就是让 LED 从暗到亮、再从亮到暗,循环往复。这靠单纯的开关做不到,需要调节亮度。怎么调?用 PWM(脉冲宽度调制)。

PWM 的原理很简单:在一个周期内,让引脚快速地在高电平和低电平之间切换。高电平占的时间比例(占空比)决定了 LED 的亮度。占空比 0% 就是全灭,100% 就是全亮,50% 就是半亮。

我画了一张图,帮你理解 PWM 的核心逻辑:

PWM 呼吸灯原理图 占空比 10% 低电平(灭) 占空比 50% 高电平(亮) 低电平(灭) 占空比 90% 高电平(亮) 一个 PWM 周期(固定频率)

树莓派的硬件 PWM 在 GPIO 12、13、18、19 上。我们用 GPIO 18,因为它正好支持硬件 PWM,频率和占空比控制都很精准。

用 RPi.GPIO 实现呼吸灯:

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)

# 创建 PWM 实例,频率 1000Hz
pwm = GPIO.PWM(18, 1000)
pwm.start(0)  # 初始占空比 0%

try:
    while True:
        # 从暗到亮
        for duty in range(0, 101, 1):
            pwm.ChangeDutyCycle(duty)
            time.sleep(0.01)
        # 从亮到暗
        for duty in range(100, -1, -1):
            pwm.ChangeDutyCycle(duty)
            time.sleep(0.01)
except KeyboardInterrupt:
    pass
finally:
    pwm.stop()
    GPIO.cleanup()

用 gpiozero 实现更简洁:

from gpiozero import PWMLED
from time import sleep

led = PWMLED(18)

while True:
    # 从暗到亮,步进 0.01
    for brightness in range(0, 101, 1):
        led.value = brightness / 100.0
        sleep(0.01)
    # 从亮到暗
    for brightness in range(100, -1, -1):
        led.value = brightness / 100.0
        sleep(0.01)
💡 调参建议: time.sleep(0.01) 控制呼吸速度。数值越小,呼吸越快。我一般用 0.005 到 0.02 之间,效果比较自然。另外,频率 1000Hz 是人眼感觉不到闪烁的下限,如果你觉得有频闪,可以提高到 2000Hz。

4.6 常见问题与避坑指南

做这个实验,我见过的问题比成功的案例还多。挑几个典型的说说:

  • LED 不亮: 先检查接线,特别是电阻有没有接对位置。然后用万用表测 GPIO 引脚电压,看是不是 3.3V。如果电压正常,换一颗 LED 试试——LED 也有坏的。
  • 呼吸灯闪烁不均匀: 大概率是 time.sleep() 的值太大或太小。我建议从 0.01 开始调,步进 1% 或 0.01 的亮度变化。
  • 程序报错 "RuntimeError: No access to /dev/mem": 权限问题。用 sudo 运行脚本,或者把用户加入 gpio 组。
  • GPIO.cleanup() 没执行: 程序异常退出时,GPIO 引脚可能保持高电平。下次运行前手动拉低,或者重启树莓派。
⚠️ 我曾经踩过的坑: 有一次我写了一个呼吸灯程序,跑了一整夜做演示。第二天发现 LED 不亮了,查了半天发现是 GPIO 引脚烧了。原因是频率太高(10kHz)加上占空比长时间 100%,引脚过载。所以建议频率不要超过 5kHz,占空比也不要长时间固定在 100%。

4.7 本章小结

这一章我们做了三件事:点亮 LED、让 LED 闪烁、实现呼吸灯效果。你其实已经掌握了 GPIO 输出的核心操作——数字输出和 PWM 输出。数字输出就是简单的 0 和 1,PWM 输出则是用高速开关模拟模拟量。

呼吸灯看起来是个小实验,但它背后的 PWM 原理在电机控制、舵机驱动、电源调压中都会用到。你想想看,一个呼吸灯搞明白了,后面做直流电机调速也就是改几行代码的事。