This code has been updated and tested on a Pi5 and allows existing code to run with minimal change, but if writing new code use gpiod
or lgpio
(which is faster and includes additional functionality).
#! /usr/bin/env python3
"""
p_gpio is a Python module for the RaspberryPi
Using gpiod Python Interface
This is a wrapper which uses the same functions as pi_gpio library.
OVERVIEW
*GPIO*
setup_gpio - Set gpio as an input or an output
input_gpio - Returns the GPIO level__plibrary
output_gpio - Output to a GPIO channel
input_28 - Returns value of GPIO 0-27
output_28 - Sets value of GPIO 0-27
gpio_function - The current GPIO mode
get_pullupdn - The current GPIO pull/up down
"""
# 2024-0104-04
import gpiod
VERSION='0.1'
# chip = gpiod.Chip('gpiochip0') # most Pi have gpiochip0
# I believe Pi5 uses 'gpiochip4'2'
# The following should work for all models
chip = gpiod.find_line('ID_SDA').owner() # find chip with ID_SDA
gpiomap = {} # This is a dictionary to avoid repeated chip.get_line(gpio) calls
# GPIO
# NOTE all gpio use Broadcom BCM numbers
INPUT=0
OUTPUT=1
# LINE_REQ_DIR_AS_IS = 1
# LINE_REQ_DIR_IN = 2
# LINE_REQ_DIR_OUT = 3
# LINE_REQ_EV_BOTH_EDGES = 6
# LINE_REQ_EV_FALLING_EDGE = 4
# LINE_REQ_EV_RISING_EDGE = 5
# LINE_REQ_FLAG_ACTIVE_LOW = 4
# LINE_REQ_FLAG_BIAS_DISABLE = 8
# LINE_REQ_FLAG_BIAS_PULL_DOWN = 16
# LINE_REQ_FLAG_BIAS_PULL_UP = 32
# LINE_REQ_FLAG_OPEN_DRAIN = 1
# LINE_REQ_FLAG_OPEN_SOURCE = 2
# ACTIVE_HIGH = 1
# ACTIVE_LOW = 2
# BIAS_AS_IS = 1
# BIAS_DISABLE = 2
# BIAS_PULL_DOWN = 4
# BIAS_PULL_UP = 3
# DIRECTION_INPUT = 1
# DIRECTION_OUTPUT = 2
def setup_gpio(gpio, direction, pud):
# def setup_gpio(gpio, direction, pud=0): # optional pud
"""
Set gpio as an input or an output
direction: 0=IN, 1=OUT
pud: 0=None 1=Up 2=Down
"""
line = chip.get_line(gpio)
gpiomap[gpio] = line
if direction:
line.request(consumer="p_gpio", type=gpiod.LINE_REQ_DIR_OUT)
else:
f = gpiod.LINE_REQ_FLAG_BIAS_DISABLE
if pud==1:
f = gpiod.LINE_REQ_FLAG_BIAS_PULL_UP
if pud==2:
f = gpiod.LINE_REQ_FLAG_BIAS_PULL_DOWN
line.request("p_gpio", gpiod.LINE_REQ_DIR_IN, f)
print('pud= ', pud, 'bias= ', line.bias())
def input_gpio(gpio):
"""
Input from a GPIO channel.
Returns HIGH=1=True or LOW=0=False
"""
return gpiomap[gpio].get_value()
def output_gpio(gpio, value):
"""
Output to a GPIO channel.
value - 0/1 or False/True or LOW/HIGH
"""
gpiomap[gpio].set_value(value)
def gpio_function(gpio):
"""
Returns the current GPIO direction
Only works if gpio in use
Returns 0,1 (IN, OUT)
"""
if gpio in gpiomap:
return gpiomap[gpio].direction() - 1
return 0
def get_pullupdn(gpio):
"""
Return the current GPIO pull
Only works if gpio in use
Returns
0:None/Unknown
1:Up
2:Down
"""
if gpio in gpiomap:
return gpiomap[gpio].bias()-2
return 0
# Dummy functions
def setup():
pass
def cleanup():
pass
#-------------
import time
def main():
global chip
SigOUT = 12
SigIN = 13
LOOPS = 20000
setup_gpio(SigOUT, 1, 0)
# setup_gpio(SigIN, 0, 0)
# setup_gpio(SigIN, 0, 1)
setup_gpio(SigIN, 0, 2)
t0 = time.time()
for i in range(LOOPS):
output_gpio(SigOUT, 1)
output_gpio(SigOUT, 0)
t1 = time.time()
print("gpiod Python\t{:>10.0f} toggles per second".format((1.0 * LOOPS) / (t1 - t0)))
output_gpio(SigOUT, 1)
print("{}".format(input_gpio(SigIN)))
print('SigIN function= ', gpio_function(SigIN))
print('SigOUT function= ', gpio_function(SigOUT))
print('pud= ', get_pullupdn(SigIN))
print('pud= ', get_pullupdn(4))
if __name__ == '__main__':
main()