Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gpiozero does not work on Linux Kernel 6.6.20 #1131

Open
danny-andersen opened this issue Mar 21, 2024 · 16 comments
Open

gpiozero does not work on Linux Kernel 6.6.20 #1131

danny-andersen opened this issue Mar 21, 2024 · 16 comments

Comments

@danny-andersen
Copy link

I have a Python project that worked fine on a Raspberry Pi Zero 2W, using Button() and LightSensor() when on Raspbian Bookworm and Linux kernel v6.1.0. I recently (March 16th 2024) apt upgrade to kernel v6.6.20 and now the same python code fails with the following stack trace:

ctx.switch = Button(pin=18, pull_up=True, hold_time=0.1)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/devices.py", line 108, in call
self = super().call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/input_devices.py", line 412, in init
super().init(
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/mixins.py", line 417, in init
super().init(*args, **kwargs)
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/input_devices.py", line 168, in init
self.pin.when_changed = self._pin_changed
^^^^^^^^^^^^^^^^^^^^^
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/pins/init.py", line 471, in
lambda self, value: self._set_when_changed(value),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/pins/pi.py", line 639, in _set_when_changed
self._enable_event_detect()
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/pins/rpigpio.py", line 220, in _enable_event_detect
GPIO.add_event_detect(
RuntimeError: Failed to add edge detection

dmesg also has an entry:
[ 187.151266] export_store: invalid GPIO 18

This was after a fresh reboot.

uname -a output:
Linux conservatory-cam 6.6.20+rpt-rpi-v7 #1 SMP Raspbian 1:6.6.20-1+rpt1 (2024-03-07) armv7l GNU/Linux

cat /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 12 (bookworm)"
NAME="Raspbian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=raspbian
ID_LIKE=debian

@lurch
Copy link
Contributor

lurch commented Mar 21, 2024

Can you paste your full code please?

@lurch
Copy link
Contributor

lurch commented Mar 21, 2024

Ahhh, it looks like this might be related to https://sourceforge.net/p/raspberry-gpio-python/tickets/210/

Can you please do sudo apt install python3-lgpio and then force usage of the lgpio library by doing export GPIOZERO_PIN_FACTORY=lgpio before running your program?

@lurch
Copy link
Contributor

lurch commented Mar 21, 2024

See also raspberrypi/linux#6037 for more details of why RPi.GPIO no longer works with the 6.6 Linux kernel.

@danny-andersen
Copy link
Author

Now fails with two lgpio errors:
AttributeError: module 'lgpio' has no attribute 'SET_PULL_NONE'
AttributeError: module 'lgpio' has no attribute 'SET_BIAS_DISABLE'

Test code with full stack trace:
Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

from gpiozero import Button
button = Button(18)
Traceback (most recent call last):
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/pins/lgpio.py", line 31, in
lgpio.SET_PULL_NONE
AttributeError: module 'lgpio' has no attribute 'SET_PULL_NONE'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "", line 1, in
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/devices.py", line 108, in call
self = super().call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/input_devices.py", line 412, in init
super().init(
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/mixins.py", line 417, in init
super().init(*args, **kwargs)
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/input_devices.py", line 162, in init
super().init(
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/mixins.py", line 243, in init
super().init(*args, **kwargs)
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/input_devices.py", line 79, in init
super().init(pin, pin_factory=pin_factory)
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/devices.py", line 544, in init
super().init(pin_factory=pin_factory)
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/devices.py", line 245, in init
Device.ensure_pin_factory()
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/devices.py", line 270, in ensure_pin_factory
Device.pin_factory = Device._default_pin_factory()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/devices.py", line 314, in _default_pin_factory
return ep.load()()
^^^^^^^^^
File "/usr/lib/python3.11/importlib/metadata/init.py", line 202, in load
module = import_module(match.group('module'))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/importlib/init.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "", line 1206, in _gcd_import
File "", line 1178, in _find_and_load
File "", line 1149, in _find_and_load_unlocked
File "", line 690, in _load_unlocked
File "", line 940, in exec_module
File "", line 241, in _call_with_frames_removed
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/pins/lgpio.py", line 33, in
lgpio.SET_PULL_NONE = lgpio.SET_BIAS_DISABLE
^^^^^^^^^^^^^^^^^^^^^^
AttributeError: module 'lgpio' has no attribute 'SET_BIAS_DISABLE'

Pip versions:
Package Version


certifi 2024.2.2
charset-normalizer 3.3.2
colorzero 2.0
crcmod 1.7
gpiozero 2.0.1
idna 3.6
jsonpickle 3.0.2
lgpio 0.0.0.2
pigpio 1.78
pip 24.0
requests 2.31.0
RPi.GPIO 0.7.1
setuptools 66.1.1
urllib3 2.2.0

Also:
python3-lgpio is already the newest version (0.2.2-1~rpt1).

@lurch
Copy link
Contributor

lurch commented Mar 22, 2024

Can you try using the system-installed python3, instead of using a venv? See further discussion in #1038

@danny-andersen
Copy link
Author

So I think this was due to the very old version of lgpio (0.0.0.2) that is in the pip library. I downloaded the latest version (0.2.2.0) from https://github.com/Gadgetoid/PY_LGPIO and installed it and it works fine.

@danny-andersen
Copy link
Author

But I do get a GPIO busy error when it first starts up but the program stll runs and I/O pins work OK (input and output):
Exception in thread Thread-2 (fill):
Traceback (most recent call last):
File "/usr/lib/python3.11/threading.py", line 1038, in _bootstrap_inner
self.run()
File "/usr/lib/python3.11/threading.py", line 975, in run
self._target(*self._args, **self._kwargs)
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/mixins.py", line 579, in fill
value = self.parent._read()
^^^^^^^^^^^^^^^^^^^
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/input_devices.py", line 699, in _read
self.pin.function = 'input'
^^^^^^^^^^^^^^^^^
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/pins/init.py", line 303, in
lambda self, value: self._set_function(value),
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/gpiozero/pins/lgpio.py", line 145, in _set_function
{
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/lgpio.py", line 758, in gpio_claim_input
return _u2i(_lgpio._gpio_claim_input(handle&0xffff, lFlags, gpio))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/danny/camera_with_switch/lib/python3.11/site-packages/lgpio.py", line 461, in _u2i
raise error(error_text(v))
lgpio.error: 'GPIO busy'

@bsimmo
Copy link

bsimmo commented Mar 23, 2024

That means an other program is running and using it, close/kill other Python/Thonny etc.

@danny-andersen
Copy link
Author

I kinda gathered that 😄. Get it after a clean reboot - the python starts up as a service and it gets the same exception thrown. Appears to be when the library starts it's threadpool but doesn't impact any I/O operation or event detection. No other services or program is using GPIO, so a bit of a mystery.

@matyasf
Copy link

matyasf commented Mar 24, 2024

So whats the workaround? I switched from RPI.GPIO to this library hoping my code would work, but it does not. My log:

/home/aaa/CODE/pi-radio/venv/lib/python3.11/site-packages/gpiozero/devices.py:300: PinFactoryFallback: Falling back from lgpio: No module named 'lgpio'
  warnings.warn(
/home/aaa/CODE/pi-radio/venv/lib/python3.11/site-packages/gpiozero/devices.py:300: PinFactoryFallback: Falling back from rpigpio: No module named 'RPi'
  warnings.warn(
/home/aaa/CODE/pi-radio/venv/lib/python3.11/site-packages/gpiozero/devices.py:300: PinFactoryFallback: Falling back from pigpio: No module named 'pigpio'
  warnings.warn(
/home/aaa/CODE/pi-radio/venv/lib/python3.11/site-packages/gpiozero/devices.py:297: NativePinFactoryFallback: Falling back to the experimental pin factory NativeFactory because no other pin factory could be loaded. For best results, install RPi.GPIO or pigpio. See https://gpiozero.readthedocs.io/en/stable/api_pins.html for more information.
  warnings.warn(NativePinFactoryFallback(native_fallback_message))

Traceback (most recent call last):
  File "/home/aaa/CODE/pi-radio/venv/lib/python3.11/site-packages/gpiozero/pins/native.py", line 237, in export
    result = self._exports[pin]
             ~~~~~~~~~~~~~^^^^^
KeyError: 20

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/aaa/CODE/pi-radio/venv/lib/python3.11/site-packages/gpiozero/pins/native.py", line 247, in export
    result = os.open(self.path_value(pin),
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/sys/class/gpio/gpio20/value'

I guess the native pin factory does not work either?

@bsimmo
Copy link

bsimmo commented Mar 25, 2024 via email

@matyasf
Copy link

matyasf commented Mar 25, 2024

hm I dont understand, the error says that I have the NativePinFactory running, whats the problem with that?

But I guess, I'll abandon using this library, I just need manual GPIO control, and this seems like a classroom project hardcoded with tons of stuff I dont need.

Anyone knows the most performant GPIO library that actually works with the latest Pi update? Whats out:

  • Rpi.gpio -- broke a few days ago.
  • wiringpi -- not supported since 2019.
  • this one -- its native implementation doesnt seem to work and I just need the low level stuff anyway.
  • pigpio -- looks good, again a bit bloated for me. I just need to turn pins on/off, not running some daemons and remote debugging :(.
  • lgpio -- doesnt seem to have a proper upload on pypi, no release since 2020. Also might not work with virtualenv?

tbh I dont understand why the pi foundation thought it would be OK to break the few easy to use libraries overnight without warning.

@bsimmo
Copy link

bsimmo commented Mar 25, 2024 via email

@danny-andersen
Copy link
Author

That means an other program is running and using it, close/kill other Python/Thonny etc.

My mistake, I had forgotten that I was forking by using Process, and it was that was generating the GPIO busy, even though the Process wasnt using any GPIO and it appears to be the way lgpio library starts up. Switched it to a Thread() to run in-process an it disappeared; the process was doing an upload of mp4 files, which are IO bound and so it is OK to run as a Thread rather than a Process().

@TPXP
Copy link

TPXP commented Mar 30, 2024

Hello, I faced a similar issue after upgrading my Linux kernel. Here's how I fixed it on my side :

  • Install lgpio binary following the official setup instructions: https://abyz.me.uk/lg/download.html
  • (if using a venv) Install the lgpio module through pip - it should be able to locate the binary and happily link against it now that you installed it: pip install lgpio
  • Set the environment variable GPIOZERO_PIN_FACTORY=lgpio to force gpiozero to use lgpio
  • If running as an unprivileged user (gpio in my case), tell lgpio where to write its temporary files by setting the environment variable LG_WD=/tmp - see Consider different/configurable name and location for .lgd-nfyx pipes joan2937/lg#12
  • If running as an unprivileged user, you may also need to update your udev rules. Here are mines (disclaimer: they are probably imperfect):
SUBSYSTEM=="gpiomem", KERNEL=="gpiomem", GROUP="gpio", MODE="0660"
SUBSYSTEM=="gpio", KERNEL=="gpiochip*", GROUP="gpio", MODE="0660"
SUBSYSTEM=="gpio", KERNEL=="gpiochip*", ACTION=="add", PROGRAM="/bin/sh -c 'chown root:gpio /sys/class/gpio/export /sys/class/gpio/unexport ; chmod 220 /sys/class/gpio/export /sys/class/gpio/unexport'"
SUBSYSTEM=="gpio", KERNEL=="gpio*", ACTION=="add", PROGRAM="/bin/sh -c 'chown root:gpio /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value ; chmod 660 /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value'"

If you get some import errors from lgpio.py:

AttributeError: module 'lgpio' has no attribute 'SET_PULL_NONE'
AttributeError: module 'lgpio' has no attribute 'SET_BIAS_DISABLE'

It means your gpiozero module is probably out of date. Upgrade it and try again:

pip install --upgrade gpiozero

Hopefully that helps! 😄

@lurch
Copy link
Contributor

lurch commented Apr 10, 2024

According to raspberrypi/linux#6037 (comment) lgpio now works inside virtualenvs 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants