Prerequisites
| Condition | Description |
|---|---|
| System | Debian12 or Ubuntu24 |
| Python bindings | sudo apt install python3-libgpiod |
| Demo pin | Pin 31 (GPIO2_B0 = gpiochip2 line 8) |
Quick Verification
python3 -c "import gpiod; print(gpiod.__version__)"A version number should be printed normally. If you get ModuleNotFoundError:
sudo apt install python3-libgpiodDo NOT install via pip
pip install gpiod installs the v2 version, which is incompatible with the system's libgpiod v1. Please use apt to install python3-libgpiod.
API Overview
gpiod.Chip('gpiochipN') -> Open controller
|
chip.get_line(offset) -> Get a single line
chip.get_lines([...]) -> Get multiple lines
|
line.request(...) -> Request usage (specify direction/event type)
|
line.get_value() -> Read
line.set_value(val) -> Write
line.event_wait() / event_read() -> Event monitoring
|
line.release() -> Release line
chip.close() -> Close controller2
3
4
5
6
7
8
9
10
11
12
13
request parameter quick reference
| type parameter | Description |
|---|---|
gpiod.LINE_REQ_DIR_IN | Input |
gpiod.LINE_REQ_DIR_OUT | Output |
gpiod.LINE_REQ_EV_RISING_EDGE | Monitor rising edge |
gpiod.LINE_REQ_EV_FALLING_EDGE | Monitor falling edge |
gpiod.LINE_REQ_EV_BOTH_EDGES | Monitor both edges |
| flags parameter | Description |
|---|---|
gpiod.LINE_REQ_FLAG_BIAS_PULL_UP | Internal pull-up |
gpiod.LINE_REQ_FLAG_BIAS_PULL_DOWN | Internal pull-down |
gpiod.LINE_REQ_FLAG_OPEN_DRAIN | Open-drain output |
Output Control (LED Blinking)
Create file gpio_output.py:
#!/usr/bin/env python3
import gpiod
import time
chip = gpiod.Chip("gpiochip2")
line = chip.get_line(8) # GPIO2_B0 = Pin 31
# Request as output, initial level is 0
line.request(consumer="gpio-output-demo", type=gpiod.LINE_REQ_DIR_OUT, default_val=0)
print("Start blinking Pin 31 (GPIO2_B0)...")
try:
for i in range(5):
line.set_value(1)
print(" HIGH")
time.sleep(0.5)
line.set_value(0)
print(" LOW")
time.sleep(0.5)
finally:
line.release()
chip.close()
print("Done")2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Run:
sudo python3 gpio_output.pyRun output
Start blinking Pin 31 (GPIO2_B0)...
HIGH
LOW
HIGH
LOW
HIGH
LOW
HIGH
LOW
HIGH
LOW
Done2
3
4
5
6
7
8
9
10
11
12
If Pin 31 has an external LED connected (with a 330 ohm current-limiting resistor in series to GND), you can see the LED blinking.
Input Reading
Create file gpio_input.py:
#!/usr/bin/env python3
import gpiod
import time
chip = gpiod.Chip("gpiochip2")
line = chip.get_line(8) # GPIO2_B0 = Pin 31
# Request as input, enable internal pull-up
line.request(
consumer="gpio-input-demo",
type=gpiod.LINE_REQ_DIR_IN,
flags=gpiod.LINE_REQ_FLAG_BIAS_PULL_UP,
)
print("Reading Pin 31 (GPIO2_B0) level, 10 times...")
try:
for i in range(10):
val = line.get_value()
level = "HIGH" if val else "LOW"
print(f" [{i+1}] Level: {level}")
time.sleep(1)
finally:
line.release()
chip.close()2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Run:
sudo python3 gpio_input.pyWith internal pull-up configured, the pin reads HIGH when floating, and LOW when connected to GND.
Edge Event Detection (Interrupts)
Create file gpio_event.py:
#!/usr/bin/env python3
import gpiod
chip = gpiod.Chip("gpiochip2")
line = chip.get_line(8) # GPIO2_B0 = Pin 31
# Request both-edge event monitoring, enable internal pull-up
line.request(
consumer="gpio-event-demo",
type=gpiod.LINE_REQ_EV_BOTH_EDGES,
flags=gpiod.LINE_REQ_FLAG_BIAS_PULL_UP,
)
print("Waiting for Pin 31 (GPIO2_B0) edge events, press Ctrl+C to exit...")
try:
while True:
# Wait for event, 5 second timeout
if line.event_wait(sec=5):
event = line.event_read()
edge = "RISING " if event.type == gpiod.LineEvent.RISING_EDGE else "FALLING"
print(f" {edge} @ {event.sec}.{event.nsec:09d}")
else:
print(" Timeout, continuing to wait...")
except KeyboardInterrupt:
print("\nExiting")
finally:
line.release()
chip.close()2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Run:
sudo python3 gpio_event.pyConnect Pin 31 to GND and then release it, and the terminal will print edge events with timestamps.
Operating Multiple Lines Simultaneously
Create file gpio_multi.py:
#!/usr/bin/env python3
import gpiod
import time
chip = gpiod.Chip("gpiochip2")
# Batch get: Pin 31 (line 8) and Pin 29 (line 16)
lines = chip.get_lines([8, 16])
# Batch request as output
lines.request(consumer="gpio-multi-demo", type=gpiod.LINE_REQ_DIR_OUT, default_vals=[0, 0])
print("Alternately blinking Pin 31 and Pin 29...")
try:
for i in range(10):
if i % 2 == 0:
lines.set_values([1, 0])
else:
lines.set_values([0, 1])
time.sleep(0.3)
finally:
lines.release()
chip.close()
print("Done")2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Run:
sudo python3 gpio_multi.pyCommon Issues
Permission denied
GPIO operations require root privileges:
sudo python3 your_script.pyOr add the user to the gpio group (requires re-login):
sudo usermod -aG gpio $USERModuleNotFoundError: No module named 'gpiod'
sudo apt install python3-libgpiodNote the package name is python3-libgpiod, not python3-gpiod.
Device or resource busy
The pin is occupied by another program or kernel driver. Troubleshooting:
gpioinfo gpiochip2 | grep "line 8"If it shows [used], you need to first stop the program occupying the pin, or disable the corresponding peripheral in the device tree.
event_wait keeps timing out?
Confirm the hardware wiring is correct. You can first verify with the command-line tool:
sudo gpiomon gpiochip2 8If the command-line tool also cannot receive events, it indicates a hardware issue (loose wiring, pin occupied, etc.).
References
- libgpiod Python bindings source code: https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/bindings/python
- libgpiod official repository: https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/