0

I’m writing a GPIO Python module from scratch. I’ve managed to write code to (in theory, I haven’t tested it on my Pi yet) turn pins on and off, and to read from pins, but for my project (and probably future ones) I’d like to be able to control GPIO devices. I do intend to run this as root because as it is I am writing to /sys/class/gpio. I know that /sys/class/pwm exists, but I have no clue how to use it. I found this answer, but the documentation that it pointed me to didn’t say anything about sysfs. I also found this answer but it didn’t make any sense to me. It also pointed to a web domain which had expired. I tried reading the gpiozero source code to try and implement this in raw python but I found nothing of use. Or if anyone can point to an asyncio compatible GPIO library which can do this, that would be good too because the whole reason I was making my own is to make an asyncio version. I’m running Raspberry Pi OS legacy (because it wasn’t legacy when I first installed it).

My existing code (should you want to build on it) is this:

import asyncio
import sys

if __debug__: # just a disclaimer
    print("asyncio_gpio_control: warning: NONE OF THIS IS TESTED", file=sys.stderr)
    print("To suppress this message, run python with the -O option") # to not be PyGame with non-suppressable messages on import

pins = ["" for i in range(40)] # to keep track of what was in direction files before I overwrite it
pinDirections = pins # to keep track of pin directory

# arduino constants
HIGH = 1
LOW = 0
INPUT = 0
INPUT_PULLUP = NotInplemented
OUTPUT = 1

BASE_GPIO_PATH = '/sys/class/gpio/' # this may not be correct

async def write_to_file(filename: str, data: bytes): # underlying framework
    cmd = ['echo', data.decode(), '>', filename]
    proc = await asyncio.create_subprocess_exec(*cmd)
    r = await proc.wait()
    if r != 0:
        raise OSError(f"Command {cmd} returned non-zero exit code {r}")
async def read_frm_file(filename: str):
    cmd = ['cat', filename]
    proc = await asynio.create_subprocess_exec(*cmd)
    data = await proc.stdout.read().decode('ascii')
    await proc.wait()
    return data
async def setOutput(pin: int):
    pins[pin] = await read_frm_file(BASE_GPIO_PATH + 'gpio' + int(pin) + '/direction')
    await write_to_file(BASE_GPIO_PATH + 'gpio' + int(pin) + '/direction', 'out')
    pinDirections[pin] = 'out'
async def setInput(pin: int):
    #print("warning: asyncio_gpio_control currently cannot verify support for input pins", file=sys.stderr)
    pins[pin] = await read_frm_file(BASE_GPIO_PATH + 'gpio' + int(pin) + '/direction')
    await write_to_file(BASE_GPIO_PATH + 'gpio' + int(pin) + '/direction', 'in')
    pinDirection[pin] = 'in'
async def digitalWrite(pin: int, value): # to put a value to a pin
    if type(value) == type(0):
        _value = str(value)
    elif type(value) == type(''):
        _value = value
    else:
        raise TypeError(f"value must be int or string, not {type(value)}.")
    await write_to_file(BASE_GPIO_PATH + 'gpio' + int(pin) + '/direction', value)
async def digitalRead(pin: int): # to read a value from a pin
    return (async read_frm_file(BASE_GPIO_PATH + 'gpio' + int(pin) + '/direction'))
async def pinMode(pin: int, direction): # just an arduino-named wrapper for setInput() and setOutput()
    if type(direction) == type(''):
        dir = 0 if direction in ('0', 'in', 'inp', 'input') else 1
    elif type(direction) == type(0):
        dir = direction
    else:
        raise TypeError(f"direction must be int or string, not {type(direction)}.")
    if dir == 0:
        setInput(pin)
    elif dir == 1:
        setOutput(pin)
    else:
        raise ValueError(f"If direction is int, it must be 0 or 1, not {direction}"

### put PWM functions here

I’m new to the stack exchange, but not the Raspberry Pi or Linux or Python.

7
  • This question is similar to: How can I use dtoverlay=pwm. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem.
    – Milliways
    Commented Jul 16 at 7:04
  • See also raspberrypi.stackexchange.com/a/145068/8697
    – Milliways
    Commented Jul 16 at 7:11
  • 1
    Do not use the GPIO sysfs interface - is it deprecated and has been removed in recent Pi kernels. Use the GPIO character device interface, so the libgpiod Python bindings (pip install gpiod) or gpiozero (which can lgpio to drive the character device interface). Using async writes to sysfs is mostly pointless as they are virtual files in kernel memory. The async machinery adds more overhead than just performing the operation with the character device interface, which is also faster than the sysfs. IMHO the only place async makes sense for GPIO is when waiting for edge events. Commented Jul 16 at 12:02
  • @KentGibson I didn’t know that sysfs was deprecated, but that explains why there were no files in /sys/class/gpio/ on my Debian 12 Pi. Is it still okay to use sysfs to control things like the ACT and PWR LEDs? Commented Jul 17 at 23:19
  • The deprecated GPIO sysfs interface is no longer compiled into the kernel by default so unless the distro explicitly adds it to their kernel build it will no longer be there. That does not change the other sysfs interfaces, such as the PWM or LED - those are still there, e.g. /sys/class/leds/ACT is still present on my Pi4 . Commented Jul 18 at 0:42

0

Your Answer

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

Browse other questions tagged or ask your own question.