树莓派5操作GPIO
在树莓派上操作GPIO
lgpio 库详解与使用指南
lgpio
是一个用于 Linux 系统的 GPIO(通用输入输出)控制库,专门为树莓派等单板计算机设计。它提供了高性能的 GPIO 操作接口,支持:
- GPIO 读写操作
- PWM 信号生成
- 舵机控制
- 中断处理
- 硬件定时器
lgpio 安装方法
在树莓派上安装
# 更新系统
sudo apt update
sudo apt upgrade
# 安装 lgpio
sudo apt install python3-lgpio
# 或者使用 pip 安装
pip3 install lgpio
验证安装
import lgpio
print(lgpio.__version__)
核心功能
1. GPIO 设备管理
import lgpio
# 打开 GPIO 设备
handle = lgpio.gpiochip_open(0) # 0 表示第一个 GPIO 控制器
# 关闭 GPIO 设备
lgpio.gpiochip_close(handle)
2. GPIO 配置
# 设置为输出模式
lgpio.gpio_claim_output(handle, gpio_pin, initial_value)
# 设置为输入模式
lgpio.gpio_claim_input(handle, gpio_pin)
# 设置为输入模式并启用上拉电阻
lgpio.gpio_claim_input(handle, gpio_pin, lgpio.PULL_UP)
3. GPIO 读写操作
# 写入 GPIO(输出模式)
lgpio.gpio_write(handle, gpio_pin, value) # value: 0 或 1
# 读取 GPIO(输入模式)
value = lgpio.gpio_read(handle, gpio_pin) # 返回 0 或 1
实际应用示例
示例 1:LED 控制
import lgpio
import time
class LEDController:
def __init__(self, led_pin=18):
self.led_pin = led_pin
self.handle = None
def init_led(self):
"""初始化 LED GPIO"""
try:
# 打开 GPIO 设备
self.handle = lgpio.gpiochip_open(0)
if self.handle < 0:
print("无法打开 GPIO 设备")
return False
# 设置 LED 引脚为输出模式
lgpio.gpio_claim_output(self.handle, self.led_pin, 0)
print(f"LED 初始化成功,引脚: {self.led_pin}")
return True
except Exception as e:
print(f"LED 初始化失败: {e}")
return False
def turn_on(self):
"""点亮 LED"""
if self.handle is not None:
lgpio.gpio_write(self.handle, self.led_pin, 1)
print("LED 已点亮")
def turn_off(self):
"""熄灭 LED"""
if self.handle is not None:
lgpio.gpio_write(self.handle, self.led_pin, 0)
print("LED 已熄灭")
def blink(self, times=5, interval=0.5):
"""LED 闪烁"""
for i in range(times):
self.turn_on()
time.sleep(interval)
self.turn_off()
time.sleep(interval)
def cleanup(self):
"""清理资源"""
if self.handle is not None:
lgpio.gpiochip_close(self.handle)
self.handle = None
print("LED 资源已清理")
# 使用示例
if __name__ == "__main__":
led = LEDController(led_pin=18)
try:
if led.init_led():
led.blink(3, 1.0) # 闪烁 3 次,间隔 1 秒
finally:
led.cleanup()
示例 2:按钮输入检测
import lgpio
import time
class ButtonController:
def __init__(self, button_pin=23):
self.button_pin = button_pin
self.handle = None
self.last_state = None
def init_button(self):
"""初始化按钮 GPIO"""
try:
self.handle = lgpio.gpiochip_open(0)
if self.handle < 0:
return False
# 设置为输入模式,启用上拉电阻
lgpio.gpio_claim_input(self.handle, self.button_pin, lgpio.PULL_UP)
print(f"按钮初始化成功,引脚: {self.button_pin}")
return True
except Exception as e:
print(f"按钮初始化失败: {e}")
return False
def read_button(self):
"""读取按钮状态"""
if self.handle is not None:
# 读取按钮状态(上拉电阻,按下为 0,松开为 1)
state = lgpio.gpio_read(self.handle, self.button_pin)
return state == 0 # 返回 True 表示按下
def wait_for_press(self, timeout=None):
"""等待按钮按下"""
start_time = time.time()
while True:
if self.read_button():
return True
if timeout and (time.time() - start_time) > timeout:
return False
time.sleep(0.01) # 10ms 检测间隔
def cleanup(self):
"""清理资源"""
if self.handle is not None:
lgpio.gpiochip_close(self.handle)
self.handle = None
# 使用示例
if __name__ == "__main__":
button = ButtonController(button_pin=23)
try:
if button.init_button():
print("按下按钮...")
if button.wait_for_press(timeout=10):
print("按钮已按下!")
else:
print("等待超时")
finally:
button.cleanup()
示例 3:舵机控制
import lgpio
import time
class ServoController:
def __init__(self, servo_pin=18):
self.servo_pin = servo_pin
self.handle = None
def init_servo(self):
"""初始化舵机"""
try:
self.handle = lgpio.gpiochip_open(0)
if self.handle < 0:
return False
# 设置舵机引脚为输出模式
lgpio.gpio_claim_output(self.handle, self.servo_pin, 0)
print(f"舵机初始化成功,引脚: {self.servo_pin}")
return True
except Exception as e:
print(f"舵机初始化失败: {e}")
return False
def set_angle(self, angle):
"""设置舵机角度 (0-180度)"""
if self.handle is None:
print("舵机未初始化")
return False
try:
# 计算脉冲宽度(微秒)
min_pulse = 500 # 0.5ms
max_pulse = 2500 # 2.5ms
pulse_width = min_pulse + (angle / 180.0) * (max_pulse - min_pulse)
# 使用 lgpio.tx_servo 控制舵机
lgpio.tx_servo(self.handle, self.servo_pin, int(pulse_width))
# 等待舵机转动
time.sleep(0.5)
# 停止 PWM 信号
lgpio.tx_servo(self.handle, self.servo_pin, 0)
print(f"舵机已转到 {angle} 度")
return True
except Exception as e:
print(f"设置舵机角度失败: {e}")
return False
def cleanup(self):
"""清理资源"""
if self.handle is not None:
lgpio.tx_servo(self.handle, self.servo_pin, 0)
lgpio.gpiochip_close(self.handle)
self.handle = None
print("舵机资源已清理")
# 使用示例
if __name__ == "__main__":
servo = ServoController(servo_pin=18)
try:
if servo.init_servo():
# 舵机转动演示
angles = [0, 45, 90, 135, 180, 90, 0]
for angle in angles:
servo.set_angle(angle)
time.sleep(1)
finally:
servo.cleanup()
高级功能
PWM 控制
# 设置 PWM 频率和占空比
lgpio.tx_pwm(handle, gpio_pin, frequency, duty_cycle)
# 停止 PWM
lgpio.tx_pwm(handle, gpio_pin, 0, 0)
中断处理
# 设置 GPIO 中断回调
lgpio.callback(handle, gpio_pin, lgpio.RISING_EDGE, callback_function)
硬件定时器
# 创建硬件定时器
timer = lgpio.timer_start(frequency, callback_function)
注意事项
- 权限要求:需要 root 权限或 gpio 组权限
- 引脚冲突:避免使用系统保留的引脚
- 资源管理:及时清理 GPIO 资源
- 错误处理:添加适当的异常处理
- 性能考虑:避免过于频繁的 GPIO 操作
常见问题解决
权限问题
# 将用户添加到 gpio 组
sudo usermod -a -G gpio $USER
# 重新登录后生效
引脚被占用
# 查看 GPIO 使用情况
gpioinfo
# 释放被占用的引脚
sudo gpio unexportall
性能优化
- 使用适当的检测间隔
- 避免在循环中进行不必要的 GPIO 操作
- 考虑使用中断而不是轮询
总结
lgpio 是一个功能强大、性能优异的 GPIO 控制库,特别适合树莓派等单板计算机的硬件控制项目。通过合理使用其提供的功能,可以实现各种复杂的硬件控制应用。
GPIO 库对比:lgpio vs gpiozero vs RPi.GPIO
概述对比
特性 | lgpio | gpiozero | RPi.GPIO |
---|---|---|---|
开发语言 | C (Python 绑定) | Python | C (Python 绑定) |
性能 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
易用性 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
功能完整性 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
文档质量 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
社区支持 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
详细功能对比
1. 基础 GPIO 操作
lgpio
import lgpio
# 打开设备
handle = lgpio.gpiochip_open(0)
# 配置引脚
lgpio.gpio_claim_output(handle, 18, 0)
lgpio.gpio_claim_input(handle, 23, lgpio.PULL_UP)
# 读写操作
lgpio.gpio_write(handle, 18, 1)
value = lgpio.gpio_read(handle, 23)
# 清理
lgpio.gpiochip_close(handle)
gpiozero
from gpiozero import LED, Button
# 创建对象(自动配置)
led = LED(18)
button = Button(23, pull_up=True)
# 操作
led.on()
led.off()
led.toggle()
# 状态检测
if button.is_pressed:
print("按钮被按下")
# 自动清理
led.close()
button.close()
RPi.GPIO
import RPi.GPIO as GPIO
# 设置模式
GPIO.setmode(GPIO.BCM)
# 配置引脚
GPIO.setup(18, GPIO.OUT)
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# 操作
GPIO.output(18, GPIO.HIGH)
value = GPIO.input(23)
# 清理
GPIO.cleanup()
2. PWM 控制对比
lgpio
# 硬件 PWM,性能最佳
lgpio.tx_pwm(handle, 18, 1000, 50) # 1kHz, 50% 占空比
lgpio.tx_servo(handle, 18, 1500) # 舵机控制
gpiozero
from gpiozero import PWMLED, Servo
# 软件 PWM
led = PWMLED(18)
led.pulse() # 自动脉冲
servo = Servo(18)
servo.mid() # 中间位置
RPi.GPIO
# 软件 PWM
pwm = GPIO.PWM(18, 1000) # 1kHz
pwm.start(50) # 50% 占空比
pwm.stop()
3. 中断处理对比
lgpio
def callback_function(gpio, level, tick):
print(f"GPIO {gpio} 状态变化: {level}")
# 设置中断
lgpio.callback(handle, 23, lgpio.RISING_EDGE, callback_function)
gpiozero
from gpiozero import Button
def button_pressed():
print("按钮被按下")
button = Button(23)
button.when_pressed = button_pressed
RPi.GPIO
def callback_function(channel):
print(f"GPIO {channel} 中断触发")
GPIO.add_event_detect(23, GPIO.RISING, callback=callback_function)
性能对比
延迟测试结果
操作类型 | lgpio | gpiozero | RPi.GPIO |
---|---|---|---|
GPIO 写入延迟 | ~1μs | ~50μs | ~10μs |
GPIO 读取延迟 | ~1μs | ~50μs | ~10μs |
PWM 精度 | 硬件级 | 软件级 | 软件级 |
中断响应 | ~5μs | ~100μs | ~20μs |
资源占用
指标 | lgpio | gpiozero | RPi.GPIO |
---|---|---|---|
CPU 占用 | 最低 | 中等 | 低 |
内存占用 | 最低 | 中等 | 低 |
启动时间 | 快 | 快 | 快 |
代码复杂度对比
LED 控制
- lgpio(最复杂)
import lgpio
import time
handle = lgpio.gpiochip_open(0)
lgpio.gpio_claim_output(handle, 18, 0)
try:
while True:
lgpio.gpio_write(handle, 18, 1)
time.sleep(1)
lgpio.gpio_write(handle, 18, 0)
time.sleep(1)
finally:
lgpio.gpiochip_close(handle)
- gpiozero(最简单)
from gpiozero import LED
import time
led = LED(18)
try:
led.blink()
time.sleep(10)
finally:
led.close()
- RPi.GPIO(中等)
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)
try:
while True:
GPIO.output(18, GPIO.HIGH)
time.sleep(1)
GPIO.output(18, GPIO.LOW)
time.sleep(1)
finally:
GPIO.cleanup()
安装和配置对比
- lgpio
# 安装
sudo apt install python3-lgpio
# 权限配置
sudo usermod -a -G gpio $USER
# 验证
python3 -c "import lgpio; print('安装成功')"
- gpiozero
# 安装
sudo apt install python3-gpiozero
# 权限配置(通常自动配置)
# 无需额外配置
# 验证
python3 -c "from gpiozero import LED; print('安装成功')"
- RPi.GPIO
# 安装
sudo apt install python3-rpi-lgpio
sudo apt install python3-rpi.gpio
# 权限配置
sudo usermod -a -G gpio $USER
# 验证
python3 -c "import RPi.GPIO; print('安装成功')"
迁移指南
从 RPi.GPIO 迁移到 lgpio
# 旧代码 (RPi.GPIO)
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)
GPIO.output(18, GPIO.HIGH)
# 新代码 (lgpio)
import lgpio
handle = lgpio.gpiochip_open(0)
lgpio.gpio_claim_output(handle, 18, 1)
lgpio.gpio_write(handle, 18, 1)
从 gpiozero 迁移到 lgpio
# 旧代码 (gpiozero)
from gpiozero import LED
led = LED(18)
led.on()
# 新代码 (lgpio)
import lgpio
handle = lgpio.gpiochip_open(0)
lgpio.gpio_claim_output(handle, 18, 0)
lgpio.gpio_write(handle, 18, 1)
遇到的问题
- 树莓派 5 报告
RuntimeError: Cannot determine SOC peripheral base address
在树莓派上可以理解 RPI.GPIO 是作为一个前端组件,简化了对 GPIO 的操作,但其还需要后端的支持,在树莓派 5 上需要 lpgio 的支持,可以通过以下指令安装,安装完成后,可以继续使用 RPI.GPIO.
sudo apt install python3-rpi-lgpio