Python GPIO 开发
python-periphery 简介
python-periphery 是一个用于在 Linux 系统上通过 Python 进行硬件外设(GPIO、SPI、I2C 等)开发的库。
主要特点
- 基于 Linux 内核接口:使用标准的 Linux 字符设备接口(如
/dev/gpiochip0) - 跨平台兼容性:适用于各种 Linux 单板计算机(Raspberry Pi、BeagleBone、Radxa 等)
- 纯 Python 实现:不需要编译 C 扩展,易于安装和部署
- 支持多种外设:GPIO、SPI、I2C、MMIO、Serial、PWM 等
支持的外设类型
| 外设类型 | 说明 |
|---|---|
| GPIO | 通用输入输出 |
| SPI | 串行外设接口 |
| I2C | I²C 总线通信 |
| MMIO | 内存映射 I/O |
| Serial | 串口通信 |
| PWM | 脉宽调制 |
安装 python-periphery
安装 pip3
首先确保系统已安装 pip3:
sudo apt update
sudo apt install python3-pip -y
安装 python-periphery 库
由于 Python 3.13+ 的 PEP 668 保护机制,需要使用 --break-system-packages 参数:
pip3 install python-periphery --break-system-packages
验证安装:
python3 -c "from periphery import GPIO; print('Installation successful!')"
提示:对于嵌入式开发板,使用
--break-system-packages参数是安全的。如果您更倾向于使用虚拟环境,可以参考 Python 虚拟环境 文档。
GPIO 读取
重要提示:Pin3 和 Pin5 默认配置为 I2C9 接口(SDA 和 SCL),如果需要作为 GPIO 使用,请确保没有其他设备占用这些引脚。
硬件准备
- 主板
- 杜邦线
软件准备
测试代码
以下代码使用 python-periphery 库来读取 Pin3 (GPIO36) 引脚的高低电平。
创建文件 gpio_input.py:
from periphery import GPIO
import time
def read_gpio_input():
# Configure GPIO input (modify pin number according to actual hardware)
# Pin3 corresponds to GPIO36 (pin 36 of /dev/gpiochip4)
try:
# Initialize GPIO in input mode
gpio_in = GPIO("/dev/gpiochip4", 36, "in")
print("Starting GPIO input reading (press Ctrl+C to exit)")
while True:
# Read pin value
value = gpio_in.read()
print(f"GPIO input value: {value} (True=High, False=Low)")
time.sleep(1) # Read once per second
except KeyboardInterrupt:
print("\nProgram exited")
except Exception as e:
print(f"Error occurred: {e}")
finally:
# Ensure resources are released
try:
gpio_in.close()
except:
pass
if __name__ == "__main__":
read_gpio_input()
测试步骤
- 将 Pin3 (GPIO36) 引脚接 GND 或 3.3V 引脚
- 将代码保存为
gpio_input.py - 使用以下命令运行测试代码:
python3 gpio_input.py
实验现象
终端会输出 False 或 True 信息:
False代表低电平(引脚接 GND)True代表高电平(引脚接 3.3V)
示例输出:
Starting GPIO input reading (press Ctrl+C to exit)
GPIO input value: False (True=High, False=Low)
GPIO input value: False (True=High, False=Low)
GPIO input value: True (True=High, False=Low)
GPIO 输出
硬件准备
- 主板
- 杜邦线
软件准备
测试代码
以下代码使用 python-periphery 库来控制 Pin3 (GPIO36) 引脚输出高低电平,然后通过 Pin5 (GPIO37) 引脚读取 Pin3 引脚的高低电平。
创建文件 gpio_output.py:
from periphery import GPIO
import time
def gpio_output_with_feedback():
# GPIO Configuration (modify pin numbers based on your hardware)
# Pin3/GPIO36 (output) → maps to pin 36 of /dev/gpiochip4
# Pin5/GPIO37 (input) → maps to pin 37 of /dev/gpiochip4
OUTPUT_PIN_CHIP = "/dev/gpiochip4"
OUTPUT_PIN_NUMBER = 36 # Pin3/GPIO36 (output pin, controlled by the script)
INPUT_PIN_NUMBER = 37 # Pin5/GPIO37 (input pin, reads output state)
# Initialize GPIO objects as None first (for safe release later)
gpio_out = None
gpio_in = None
try:
# Initialize Pin3/GPIO36 as OUTPUT mode
gpio_out = GPIO(OUTPUT_PIN_CHIP, OUTPUT_PIN_NUMBER, "out")
# Initialize Pin5/GPIO37 as INPUT mode
gpio_in = GPIO(OUTPUT_PIN_CHIP, INPUT_PIN_NUMBER, "in")
# Print test initialization info
print("=== GPIO Output-Input Feedback Test Started ===")
print(f"Controlled Pin (GPIO36): {OUTPUT_PIN_CHIP} - Pin {OUTPUT_PIN_NUMBER} (OUTPUT)")
print(f"Monitoring Pin (GPIO37): {OUTPUT_PIN_CHIP} - Pin {INPUT_PIN_NUMBER} (INPUT)")
print("Test Behavior: GPIO36 toggles HIGH/LOW every 1s; GPIO37 verifies GPIO36's state")
print("Press Ctrl+C to stop the test\n")
# Main loop: Toggle GPIO36 and read GPIO37 feedback
while True:
# 1. Set GPIO36 to HIGH level
gpio_out.write(True)
time.sleep(0.1) # Short delay for signal stabilization (avoid read lag)
gpio37_reading = gpio_in.read()
print(f"GPIO36 Output: HIGH (True) | GPIO37 Reading: {gpio37_reading}")
# Keep GPIO36 HIGH for 1 second
time.sleep(1)
# 2. Set GPIO36 to LOW level
gpio_out.write(False)
time.sleep(0.1) # Short delay for signal stabilization
gpio37_reading = gpio_in.read()
print(f"GPIO36 Output: LOW (False) | GPIO37 Reading: {gpio37_reading}")
# Keep GPIO36 LOW for 1 second
time.sleep(1)
# Handle user-initiated exit (Ctrl+C)
except KeyboardInterrupt:
print("\n\nTest stopped by user (Ctrl+C)")
# Handle other unexpected errors (e.g., GPIO access failure)
except Exception as e:
print(f"\nError during test: {str(e)}")
# Ensure GPIO resources are released even if an error occurs
finally:
print("\nReleasing GPIO resources...")
# Safely close GPIO36 (set to LOW first to avoid residual high level)
if gpio_out:
try:
gpio_out.write(False)
gpio_out.close()
print(f"Successfully closed GPIO36 (Pin {OUTPUT_PIN_NUMBER})")
except Exception as close_err:
print(f"Failed to close GPIO36 (Pin {OUTPUT_PIN_NUMBER}): {str(close_err)}")
# Safely close GPIO37
if gpio_in:
try:
gpio_in.close()
print(f"Successfully closed GPIO37 (Pin {INPUT_PIN_NUMBER})")
except Exception as close_err:
print(f"Failed to close GPIO37 (Pin {INPUT_PIN_NUMBER}): {str(close_err)}")
print("Resource release complete.")
# Run the test when the script is executed directly
if __name__ == "__main__":
gpio_output_with_feedback()
测试步骤
- 将 Pin3 (GPIO36) 引脚和 Pin5 (GPIO37) 引脚进行短接
- 将代码保存为
gpio_output.py - 使用以下命令运行测试代码:
sudo python3 gpio_output.py
注意:GPIO 输出可能需要 root 权限,因此使用
sudo运行。
实验现象
终端会输出 False 或 True 信息:
False代表低电平True代表高电平
示例输出:
=== GPIO Output-Input Feedback Test Started ===
Controlled Pin (GPIO36): /dev/gpiochip4 - Pin 36 (OUTPUT)
Monitoring Pin (GPIO37): /dev/gpiochip4 - Pin 37 (INPUT)
Test Behavior: GPIO36 toggles HIGH/LOW every 1s; GPIO37 verifies GPIO36's state
Press Ctrl+C to stop the test
GPIO36 Output: HIGH (True) | GPIO37 Reading: True
GPIO36 Output: LOW (False) | GPIO37 Reading: False
GPIO36 Output: HIGH (True) | GPIO37 Reading: True
GPIO36 Output: LOW (False) | GPIO37 Reading: False
GPIO 引脚映射说明
在 python-periphery 中,GPIO 引脚需要指定两个参数:
- GPIO 芯片设备:Quectel Pi H1 主要使用
/dev/gpiochip4 - 引脚编号:物理引脚对应的 GPIO 编号
40Pin 引脚映射示例
| 物理引脚标识 | 引脚名称 | GPIO 编号 | GPIO 芯片 | 引脚编号 | 默认功能 |
|---|---|---|---|---|---|
| Pin3 | NFC_I2C_SDA | GPIO36 | /dev/gpiochip4 | 36 | I2C09_SDA |
| Pin5 | NFC_I2C_SCL | GPIO37 | /dev/gpiochip4 | 37 | I2C09_SCL |
| Pin7 | CAM2_RST | GPIO77 | /dev/gpiochip4 | 77 | GPIO |
| Pin11 | GPIO_16 | GPIO16 | /dev/gpiochip4 | 16 | GPIO/SPI/UART/I2C |
| Pin13 | GPIO_17 | GPIO17 | /dev/gpiochip4 | 17 | GPIO/SPI/UART/I2C |
查看可用 GPIO
使用 gpioinfo 命令查看所有可用的 GPIO 芯片和引脚:
# 安装 gpiod 工具
sudo apt install gpiod -y
# 查看所有 GPIO 信息
gpioinfo
# 查看特定芯片
gpioinfo /dev/gpiochip4
常见问题
权限问题
如果遇到权限错误,可以:
- 使用
sudo运行脚本 - 将用户添加到
gpio用户组:
sudo usermod -a -G gpio $USER
- 注销并重新登录使权限生效
引脚占用问题
如果遇到 [Errno 16] Device or resource busy 或 [Errno 1] Operation not permitted 错误:
检查引脚状态:
# 查看所有 GPIO 引脚状态
gpioinfo | grep "consumer="
# 查看特定芯片的引脚占用情况
gpioinfo /dev/gpiochip4 | grep -E "(line|consumer)"
常见原因:
- 引脚被其他进程占用(如 I2C、SPI 等)
- 引脚已被系统功能使用
- 其他 GPIO 程序正在运行
解决方法:
- 选择未被占用的引脚(gpioinfo 中显示为
input且无consumer的引脚) - 如果需要使用被占用的引脚,需要禁用相应的功能
引脚编号错误
如果遇到 [Errno 22] Invalid argument 错误:
原因:
- 引脚编号不存在或不可用
- 使用了错误的 GPIO 芯片设备
解决方法:
- 使用
gpioinfo查看实际可用的引脚编号 - 确认使用正确的 GPIO 芯片(Quectel Pi H1 主要使用
/dev/gpiochip4)
调试技巧
查看可用的 GPIO 芯片:
ls -l /dev/gpiochip*
查看 GPIO 芯片详细信息:
gpioinfo
测试特定引脚:
# 使用 gpioget 读取引脚值
sudo gpioget /dev/gpiochip4 36
# 使用 gpioset 设置引脚值
sudo gpioset /dev/gpiochip4 36=1 # 设置为高电平
sudo gpioset /dev/gpiochip4 36=0 # 设置为低电平