You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RPi4+CentOS7环境下RPi.GPIO边缘检测失败求助

在RPi4 CentOS7上解决RPi.GPIO边缘检测失败问题

问题背景

在RPi4上运行CentOS7(内核版本5.4.206-v8.1.el7),使用RPi.GPIO-0.7.1-py3.9配置GPIO边缘检测时,无论选择哪个引脚都会抛出错误:

RPi.GPIO.add_event_detect(self.pin, RPi.GPIO.BOTH, self._on_event) RuntimeError: Failed to add edge detection

即使使用sudo运行也无法解决。已调整/dev/gpiomem权限为:

crw-rw----. 1 root gpio 246, 0 Jan 1 1970 /dev/gpiomem

GPIO输出模式(如点亮LED)可正常工作,但边缘检测始终失败。

通过strace追踪代码,发现关键错误日志:

faccessat(AT_FDCWD, "/sys/class/gpio/gpio6", F_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/sys/class/gpio/export", O_WRONLY) = -1 EACCES (Permission denied)

额外信息:

  • 原以为RPi.GPIO已基于GPIO字符设备而非sysfs,但对实现细节存疑
  • /sys/class/gpio目录下存在export、gpiochip446、gpiochip454、unexport,疑惑为何要创建/sys/class/gpio/gpio6而非基于控制器基址计算
  • 使用bcm2835库的event.c示例可正常检测按键,但因技术原因必须使用RPi.GPIO

解决步骤

1. 明确RPi.GPIO的边缘检测依赖

RPi.GPIO-0.7.1版本的边缘检测仍依赖sysfs接口,而非仅使用/dev/gpiomem。输出模式可以通过/dev/gpiomem正常工作,但边缘检测需要操作/sys/class/gpio下的文件,这是权限问题的核心原因。

2. 修复sysfs GPIO权限

方法一:临时调整权限(重启后失效)

直接修改/sys/class/gpio/export和/sys/class/gpio/unexport的权限,让普通用户可写:

sudo chmod 666 /sys/class/gpio/export /sys/class/gpio/unexport

修改后重新运行Python代码(无需sudo),边缘检测即可正常工作。

方法二:永久配置权限(通过udev规则)

创建udev规则文件/etc/udev/rules.d/99-gpio.rules:

SUBSYSTEM=="gpio", ACTION=="add", RUN+="/bin/chmod 666 /sys/class/gpio/export /sys/class/gpio/unexport"
SUBSYSTEM=="gpio", KERNEL=="gpio*", ACTION=="add", RUN+="/bin/chmod 666 /sys/class/gpio/%k/value /sys/class/gpio/%k/edge"

保存后重新加载udev规则:

sudo udevadm control --reload-rules
sudo udevadm trigger

该配置会在系统重启后自动生效,无需每次手动修改权限。

3. 关于引脚编号的说明

RPi.GPIO使用BCM编号时,会直接将引脚号(如6)映射到sysfs的gpio6,但RPi4的CentOS7内核中GPIO控制器存在基址偏移。不过RPi.GPIO-0.7.1版本会自动处理编号映射,只要修复sysfs权限让export操作成功,就能自动创建对应的gpio目录,无需手动计算基址偏移后的编号。

4. 验证修复

运行测试代码:

import RPi.GPIO as GPIO

X=6

# Set pin X in GPIO mode
GPIO.setmode(GPIO.BCM)
GPIO.setup(X, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# Define a callback function to detect edge events
def my_callback(channel):
    print(f"Edge event detected on pin {X}")

# Set the callback function
GPIO.add_event_detect(X, GPIO.RISING, callback=my_callback)

# Main loop
try:
    while True:
        pass

# Exit gracefully
except KeyboardInterrupt:
    GPIO.cleanup()

此时边缘检测应该能正常触发回调函数。


内容的提问来源于stack exchange,提问作者user20980603

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 14:16:23