0

I am trying to run a program using GPIO from a normal user. I checked that /dev/gpiomem has the correct permission (root:gpio 0660) and that my user is member of group gpio.

The following works correctly:

import RPi.GPIO as GPIO
from time import sleep

try:
    pin = 21
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(pin, GPIO.IN)

    while True:
        pin_value = GPIO.input(pin)
        print("Pin {} has value {}".format(pin, pin_value))
        sleep(1)
finally:
    GPIO.cleanup()

When I press a button attached to pin 21 it does indeed show 1, and 0 otherwise. I run this as a standard user, so I guess it uses /dev/gpiomem (and indeed it failed before I fixed its permissions).

However, if I try to set an event on such pin

import RPi.GPIO as GPIO
from time import sleep

try:
    pin = 21
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(pin, GPIO.IN)

    GPIO.add_event_detect(pin, GPIO.RISING)
    GPIO.add_event_callback(pin, lambda _: print("Pin {} was pressed".format(pin)))

    while True:
        pass
finally:
    GPIO.cleanup()

it raises the following exception:

Traceback (most recent call last):
  File "tst.py", line 9, in <module>
    GPIO.add_event_detect(pin, GPIO.RISING)
RuntimeError: Failed to add edge detection

Everything works fine using root, but I want to run this program as a standard user. Kernel is 4.14.37 and RPi.GPIO is 0.6.3. I am using a RPi 2.

It seems that adding an event on a pin still requires being root. Am I right? Am I doing anything wrong? How else could I detect a pin rising as a standard user?

  • 1
    Dunno but as a guess it could be using the /sys/gpio interface to poll rising/falling events... – goldilocks Apr 28 '18 at 13:24
  • Polling is not an option. I can check if an edge is detected only once every couple seconds, I would most certainly miss it if I used polling. – Claudio Apr 29 '18 at 9:18
2

I'm not sure what is going wrong. My Python knowledge is sketchy.

I'd dump the lambda and try the following (which works for me).

#!/usr/bin/env python

import RPi.GPIO as GPIO
import time

def callback(pin): 
   print("Pin {} was pressed".format(pin))

try:
    pin = 21
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(pin, GPIO.IN)

    GPIO.add_event_detect(pin, GPIO.RISING, callback)

    while True:
        time.sleep(60)
finally:
    GPIO.cleanup()
  • This is completely equivalent, and, besides, the exception is raised before I even define the lambda. Moreover, that code works as root. – Claudio Apr 29 '18 at 9:15
  • @Claudio The code I posted works as the pi user. – joan Apr 29 '18 at 9:44
0

Unfortunately, to interface with the GPIO pins, it is required that you use sudo. This is because it is a component that directly controls the Pi's electronics, and it is usually safer to only allow administrators to use those components, especially because they want to make it idiotproof in case it is used as a public computer.

So, the only way your program can work is like this: sudo python filename.py

Of course, you could use an extra component or a microcontroller to send the information wirelessly, but that would be annoying, so unless you want to do that, I would just use sudo.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.