0

I should make it clear that I do not have a Pi5 (all the authorised resellers in Australia are out of stock - and I can't even preorder - my normal supplier got a few in late November, but they sold out in minutes) so I have been unable to test.

There has been lots of documentation on the Pi5 and some discussion but it appears that the existing GPIO libraries will not work on Pi5.

Joan posted "pigpio does not work on the Pi 5, I do not think it can be made to work (but hope to be proved wrong). lgpio will work."

6by9 posted "libgpio is the correct answer for any variant of Pi now. There should be no need to directly bash registers through gpiomem holes at all".

lgpio accesses GPIO through the gpiochip device and libgpiod provides some command line tools. When I first tested these (a few years ago) the access was very restrictive but I believe this may have been somewhat relaxed.

gpiozero now uses the lgpio library by default.

raspi-gpio fails on Pi5 but pinctrl I have written a version of my gpioreadall which uses pinctrl.

I already use kernel drivers for SPI & i2c which are quite functional.

I have successfully tested my pi-gpio & pi_gpio libraries on Bookworm.

The main thing that is missing is hardware PWM. There has been a pwm dtoverlay (since at least Stretch) but is largely undocumented and the dtoverlay description states "4) Currently the clock must have been enabled and configured by other means" which is less than helpful. I have since found https://docs.kernel.org/driver-api/pwm.html#using-pwms-with-the-sysfs-interface; I had thought this was deprecated (like the GPIO sysfs interface) but have been assured by a Raspberry Pi Engineer that it is supported. I have written and tested c code (on Pi4 Bookworm) and am writing Python code.

2
  • Maybe you should edit (or delete) this... you're correct of course; it's not a question. On the subject pf Pi5 availability: the Pi Hut (a UK-domiciled co) may be the best source for any hardware, but you'll wait a long time to get anything delivered.
    – Seamus
    Commented Nov 29, 2023 at 4:54
  • Its libgpiod, not libgpio. 6by9 misnamed it in that quote just to add to the confusion. There is actually a libgpio out there - github.com/Linutronix/libgpio - that uses sysfs, and that most certainly isn't what you want to be using. Commented Apr 4 at 2:07

2 Answers 2

0

In Bookworm (and latest Bullseye) the kernel device driver for GPIO has been updated so GPIO settings are persistent and it is now possible to specify pulls.
This means libgpiod behaves similarly to sysfs (and most tools accessing registers).

There is kernel documentation and a python module gpiod but it is difficult to follow (unless you are a kernel developer) and no User Documentation.

There are a few examples e.g. https://www.tomshardware.com/how-to/control-raspberry-pi-5-gpio-with-python-3

The current libgpiod is old (v1.6.3 in Bookworm and even older in Bullseye) the v2 code is significantly different but it unclear if or when this may be included in Raspberry Pi OS.

I decided to test the gpiod module and write a wrapper which uses the same functions as my pi_gpio library.

This obviously excludes I²C, SPI or Hardware PWM but I have code implementing these using kernel drivers which will be included in a final library as will Information functions.

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-04-04
import gpiod

VERSION='0.2'

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()
4
  • The libgpiod v2 documentation. Not quite up to date, but the differences are minor. And there are more examples in the libgpiod source tree, for C and all the other language bindings, including python. If you need examples that aren't already covered there then let us know and we'll add some. Of course that is for v2, which you are reluctant to use as it isn't packaged in Raspberry Pi OS yet, but I can't help you with that. And you couldn't pay me to write examples for v1. Commented Jan 5 at 16:03
  • The Toms Hardware example is no longer functional with the most recent version of gpiod. You will need to install an older version of gpiod for it to work.
    – utdream
    Commented Mar 28 at 21:44
  • What the basis for the claim that lgpio is faster than gpiod? Given they both use the same kernel interface you would expect them to be about the same, and there isn't a lot of fat in gpiod, so I'm curious as to where this purported speed advantage comes from. Commented May 2 at 2:36
  • Provide a link to your pi-gpio library. Commented May 2 at 3:40
0

The Raspberry Pi Model 5 was introduced at the end of 2023. It only works with Raspberry Pi Bookworm OS or later

However, the biggest impact for most developers is that the RPi.GPIO input/output library does not work on the Raspberry Pi model 5. This is because the RPi Model 5 now has a seperate chip caled RP1 for controlling the GPIO header. This means that hundreds of thousands of programs or maybe even millions of programs need to be modified to use one of the newer libraries such as gpiod or lgpio.

My own product also Raspberry Pi Internet Radio is such a program and would have meant a lot of work to convert all the GPIO routines to say GPIOD which does run on the RPi Model 5. So I decided to write a simple interface called GPIOconverter which converts RPi GPIO calls to one of the newer GPIO interfaces. GPIOD was advocated as the best way forward however I found that, at the time, GPIOD was poorly documented and I could not find any examples of how to handle interrupts. I eventually settled on using python3-lgpio for the GPIOconverter software. The architecture of the interface is shown below:

OUTPUT: User Program --> GPIO calls --> GPIOconverter --> LGPIO

INPUT: LGPIO events --> GPIOconverter --> User Program

The GPIOconverter software is currently available available on GitHub GPIO converter on GitHub

or download it from the following Web site. GPIOconverter from Bob Rathbone

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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