Skip to main content
update gpiod V2
Source Link
Milliways
  • 61.5k
  • 32
  • 108
  • 212

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).


gpiod V2 can be installed with pip in a Python venv and is much improved (but NOT backward compatible with V1).

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).

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 includes additional functionality).


gpiod V2 can be installed with pip in a Python venv and is much improved (but NOT backward compatible with V1).

updated for Pi5
Source Link
Milliways
  • 61.5k
  • 32
  • 108
  • 212

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()
#! /usr/bin/env python3
"""
p_gpio is a Python module for the RaspberryPi
Using gpiod Python Interface

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

VERSION='0.1'

# chip = gpiod.Chip('gpiochip0')  # most Pi have gpiochip0
# I believe Pi5 uses 'gpiochip4'
# The following should work for all models
chip = gpiod.find_line('ID_SDA').owner()  # find chip with ID_SDA

gpiomap = {}

#  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
  
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()

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()
Update text
Source Link
Milliways
  • 61.5k
  • 32
  • 108
  • 212

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.

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

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.

Source Link
Milliways
  • 61.5k
  • 32
  • 108
  • 212
Loading