How to control GPIO via C or Python 3

Although it worked when I just read lines (direct voltage reads whether a gpio line was 1 or 0), it was doing something weird like not releasing the line correctly (system interrupts occur but then don’t go away):

def run(self) -> None:
        """Monitors the GPIO line for tap events and processes them.

        Continuously checks a specific GPIO line for voltage changes. If a change is detected,
        interprets it as a tap event and triggers the tap handling process.
        """
        # TODO: Create chip/pin mapping in gpio_config
        chip_path = '/dev/gpiochip1'
        line_offset = 26

        with gpiod.request_lines(
            path=chip_path,
            consumer='watch-touch-sensor-line',
            config={
                line_offset:
                    gpiod.LineSettings(
                        edge_detection=Edge.RISING,
                        bias=Bias.PULL_DOWN,
                        debounce_period=timedelta(seconds=0.5)
                )
            }
        ) as line:
            while True:
                # Block until rising edge event happens
                if line.read_edge_events():
                    self.handle_tap()

This will work the first run, but then as soon as it reads once, it then can’t read again. In fact, if I rerun the program, the gpiod.request_lines throws an error like resource is busy or something like that. Only once I reboot will the process run once again (but always only once). I figured the reboot removes the system interrupt that occurs when gpiod.request_lines or line.read_edge_events() is called. What can I do to fix this, or at least debug to gain more insight?

Have you updated the kernel to the latest?

I will attempt it again for the Dec. 3rd update, but assuming that wasn’t already fixed from the Dec. 2nd update, I have the following kernel/distro:

Linux raspbian-bookworm-aml-s905x-cc 6.1.64-11810-g69b1ffe8ef6c #1 SMP PREEMPT_DYNAMIC Sat Dec  2 01:00:10 EST 2023 aarch64 GNU/Linux

We fixed it in 6.1.66.

1 Like

yet another thing to get around.

Error I am getting is: “gpioset: error setting the GPIO line values Permission Denied”

How do I work around this issue?

The user you are using to run the commands has no permissions to write to the /dev/gpiochipX character devices. Either run your program as root or run sudo or apply proper permissions/groups to your running user.

I dropped the Easy GPIO Python Library and just coded the pin commands as needed.

GPIO0_D3set = “gpioset 0 27=1”
GPIO0_D3reset = “gpioset 0 27=0”

system( f"{GPIO0_D3set}" )

1 Like

Hi, it’s been three weeks since I received your Alta AML-A311D-CC. I installed the 2023-10-10-raspbian-bookworm-arm64-full+arm64 OS on it. However, I’m still struggling to understand how to simply turn on a led using the GPIO ports.
I want to accomplish this using Python, but I can’t find any documentation about the gpiod module. Additionally, I’m unsure how to bind the ports and determine which one is which.
thank’s in advence

Did you do this thing, post 1, Libre Computer Wiring Tool?

Did it work?

If yes then:

from os import system

certs.FanOff = “gpioset 0 0=0” #J1 pin 32
certs.FanOn = “gpioset 0 0=1”

                    if ( temperature >= certs.FanTriggerPoint ):
                        system( f"{certs.FanOn}" )
                        fan_enabled = True
                    else:
                        system( f"{certs.FanOff}" )
                        fan_enabled = False

else:
let us know it did not work and what issue you have.

1 Like

thank’s a lot I check that and y keep you informed for now it works

Hello, so I finally managed to control my robot, although not in an optimal manner. However, it’s sufficient for my project. Here is the code : (I still have a question to ask I put it below the code)

#!/usr/bin/env python3
import subprocess, time

'''
---------------------
--->display doc<---
---------------------
'''

x = subprocess.check_output('lgpio headers', shell=True, text=True)
y = subprocess.check_output('lgpio header 7J1', shell=True, text=True)

print(y)
print("from chip 7J1 but there is other chip detected : \n" + x)

'''
-------------------------------
--->Variable definition<---
-------------------------------
'''

leftFWD = "8" #outpup pin for the engine
rightFWD = "7"
leftRWD = "11"
rightRWD = "10"

'''
--------------------------------
--->fonctions definition<---
--------------------------------
'''

def FX_Mouvement(Movement):
	'''
	this function execute the desierd movement
	Stop = stop every engine
	FWD = go forwad
	RWD = go backward
	Left = turn left
	Right = turn right
	'''
	
	match Movement:
		case "Stop":
			subprocess.run("sudo lgpio set " + leftFWD + "=0", shell=True)
			subprocess.run("sudo lgpio set " + rightFWD + "=0", shell=True)
			subprocess.run("sudo lgpio set " + leftRWD + "=0", shell=True)
			subprocess.run("sudo lgpio set " + rightRWD + "=0", shell=True)
			
		case "FWD":
			subprocess.run("sudo lgpio set " + leftFWD + "=1", shell=True)
			subprocess.run("sudo lgpio set " + rightFWD + "=1", shell=True)
			subprocess.run("sudo lgpio set " + leftRWD + "=0", shell=True)
			subprocess.run("sudo lgpio set " + rightRWD + "=0", shell=True)
			
		case "RWD":
			subprocess.run("sudo lgpio set " + leftFWD + "=0", shell=True)
			subprocess.run("sudo lgpio set " + rightFWD + "=0", shell=True)
			subprocess.run("sudo lgpio set " + leftRWD + "=1", shell=True)
			subprocess.run("sudo lgpio set " + rightRWD + "=1", shell=True)
			
		case "Left":
			subprocess.run("sudo lgpio set " + leftFWD + "=1", shell=True)
			subprocess.run("sudo lgpio set " + rightFWD + "=0", shell=True)
			subprocess.run("sudo lgpio set " + leftRWD + "=1", shell=True)
			subprocess.run("sudo lgpio set " + rightRWD + "=0", shell=True)
			
		case "Right":
			subprocess.run("sudo lgpio set " + leftFWD + "=0", shell=True)
			subprocess.run("sudo lgpio set " + rightFWD + "=1", shell=True)
			subprocess.run("sudo lgpio set " + leftRWD + "=0", shell=True)
			subprocess.run("sudo lgpio set " + rightRWD + "=1", shell=True)
			
		
'''
-----------------
--->Quick test<---
-----------------
'''

for i in range(1):
	'''
	test
	'''
	print('|||---------------------fw ---------------------|||')
	FX_Mouvement("FWD")
	time.sleep(0.5)

	print('|||---------------------bw ---------------------|||')
	FX_Mouvement("RWD")
	time.sleep(0.5)

	print('|||---------------------L  ---------------------|||')
	FX_Mouvement("Left")
	time.sleep(0.5)

	print('|||---------------------R  ---------------------|||')
	FX_Mouvement("Right")
	time.sleep(0.5)

	
	print('|||---------------------stp---------------------|||')
	FX_Mouvement("Stop")
	time.sleep(0.3)

	
	print('endprocess')


Now, I would like to read some information that is outputted from the sensors into GPIO ports. For example, I would like to evaluate distance using an ultrasonic sensor connected to an ADC. However, I’m unsure how to detect if there is current flowing into the GPIO ports using the libgpioreg library…

Are you using a raw Ultrasonic sensor and pulsing it with +/-12V or are you using something like a SRO4 module?

Did you do a search using your IDE for a Python SRO4 library?

lgpio should not be called via a program. It’s for command line testing of the GPIOs.

You should get the gpio chip and line from the lgpio tool and use python’s libgpiod bindings to directly control the GPIOs.

GPIOs are digital IOs that require 3.3V, not analog. Do not run anything that drives current to a GPIO and/or is not 3.3V.

1 Like

I’m planning to use some SR04 and one SEN0032, and one SEN0101, yes I would like tu use them with python. Because I need the data of these sensor to give them to my AI.

So the 7J1 chip is not the one that is meant to contrôl the GPIO pins?

For the libgpiod, I did not understand where to find a documentation that work’s with your OS.

I dont know if I understand correctly your last point. Did you mean that I can not read any info on the gpio or my ADC must send 3.3V?

If using an SR04 then why not use a Python library to do the Ultrasonic thing?

1 Like

SR04 is a 5V device so you cannot directly hook it to a 3.3V GPIO. You need to have a level shifter to safely use it. In terms of use, SR04 uses GPIO interrupts to measure pulse duration to determine distance. It’s best to compile a kernel driver that will return distance via the IIO subsystem.

1 Like

thank’s a lot for helping me, I will use the python library if I succed to overide the externally managed environement that I’m on. It’s just that for now I’m stuck at understanding how to read information but it looks like it’s because of the voltage as @librecomputer said

Thank you I’m happy to hear that I can read some info on my GPIO ports !! I will start to try what you said. 3.3V I saw that i could use a resistor divider, I might do that but is there a tolerance with the GPIO ports if I with 3.333…V could it break the board with time?

V=IR. The voltage difference affects the amount of current flowing. If it is over the current sinkable by the GPIO design (usually 1 or 2mA), it will cause issues.