Using GPIO#
Todo
Add information about software image used for this demo.
GPIO stands for General-Purpose Input/Output. It’s a set of programmable pins that you can use to connect and control various electronic components.
You can set each pin to either read signals (input) from things like buttons and sensors or send signals (output) to things like LEDs and motors. This lets you interact with and control the physical world using code!
A great resource for understanding pin numbering can be found at pinout.beagley.ai
Warning
BeagleY-AI GPIOs are 3.3V tolerant, using higher voltages WILL DAMAGE the processor!
Pin Numbering#
You will see pins referenced in several ways. While this is confusing at first, in reality, we can pick our favorite way and stick to it.
The two main ways of referring to GPIOs is by their number, so GPIO 2, 3, 4 etc. as seen in the diagram below. This corresponds to the SoC naming convention. For broad compatibility, BeagleY-AI re-uses the Broadcom GPIO numbering scheme used by RaspberryPi.
The second (and arguably easier) way we will use for this tutorial is to use the actual pin header number (shown in dark grey)
So, for the rest of the tutorial, if we refer to hat-08-gpio we mean the 8th pin of the GPIO header. Which, if you referenced the image below, can see refers to GPIO 14 (UART TX)
If you are curious about the “real” GPIO numbers on the Texas Instruments AM67A SoC, you can look at the board schematics.
Required Hardware#
For the simple blink demo, all that is needed is an LED, a Resistor (we use 2.2K here) and 2 wires.
Similarly, a button is used for the GPIO read example, but you can also just connect that pin to 3.3V or GND with a wire to simulate a button press.
Todo
Add fritzing diagram and chapter on Pin Binding here
GPIO Write#
At it’s most basic, we can set a GPIO using the gpioset command.
To set HAT Pin 8 (GPIO14) to ON:
gpioset $(gpiofind GPIO14)=1
To set HAT Pin 8 (GPIO14) to OFF:
gpioset $(gpiofind GPIO14)=0
Blink an LED#
Let’s create a script called blinky.sh,
Create the file,
touch blinky.sh
Open the file using
nano
editor,
nano blinky.sh
Copy paste the code below to
blinky.sh
file,
#!/bin/bash
while :
do
gpioset $(gpiofind GPIO14)=1
sleep 1
gpioset $(gpiofind GPIO14)=0
sleep 1
done
Close the editor by pressing
Ctrl + O
followed byEnter
to save the file and then press toCtrl + X
exitNow execute the
blinky.sh
script by typing:
bash blinky.sh
You can exit the
blinky.sh
program by pressingCTRL + C
on your keyboard.
Understanding the code#
#!/bin/bash
while :
do
gpioset $(gpiofind GPIO14)=1 ①
sleep 1 ②
gpioset $(gpiofind GPIO14)=0 ③
sleep 1 ④
done
The script is an infinite while
loop in which we do the following:
① set the HAT Pin 8 (GPIO14) as 1 (HIGH)
② Wait 1 Second
③ set the HAT Pin 8 (GPIO14) as 0 (LOW)
④ Wait 1 Second
Blink an LED using Python#
Using python you can blink an LED.
The libgpiod
should already be installed in the default image, in case it’s not installed then
install it by using the command below.
sudo apt-get install python3-libgpiod
Below is the Python code to blink an LED connected to GPIO14.
import gpiod
import time
gpio14 = gpiod.find_line('GPIO14')
gpio14.request(consumer='beagle', type=gpiod.LINE_REQ_DIR_OUT, default_val=0)
while True:
gpio14.set_value(1)
time.sleep(1)
gpio14.set_value(0)
time.sleep(1)
To open the Python REPL, type python
in the terminal like below. Copy the above code and paste it into the terminal.
After running the code, the LED connected to GPIO14 will start blinking.
debian@BeagleBone:~$ python
Python 3.11.2 (main, May 2 2024, 11:59:08) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
Alternatively, you can create a Python script to achieve the same effect. Create a new file named blinky.py
and
open it using the nano
editor with the following command, copy and paste the above code to the file.
nano blinky.py
Press CTRL+O
& ENTER
to save the blinky.py
script and then CTRL+X
to exit.
To run the blinky.py
script execute the command below,
python blinky.py
After running the code you can see the LED connected to GPIO14
or HAT Pin 08
blinking.
Understanding the code#
import gpiod ①
import time ②
gpio14 = gpiod.find_line('GPIO14') ③
gpio14.request(consumer='beagle', type=gpiod.LINE_REQ_DIR_OUT, default_val=0) ④
while True: ⑤
gpio14.set_value(1) ⑥
time.sleep(1) ⑦
gpio14.set_value(0) ⑧
time.sleep(1) ⑨
① Importing gpiod
module
② Importing time
module
③ Linking GPIO14 pin object to gpio14 variable for better accessibility
④ Set GPIO14 as OUTPUT pin
⑤ Create infinite while
loop
⑥ Set the GPIO14 as 1 (HIGH)
⑦ Wait 1 Second
⑧ Set the GPIO14 as 0 (LOW)
⑨ Wait 1 Second
Combining the Two#
Now, logically, let’s make an LED match the state of the button.
Let’s create a script called blinkyButton.sh:
Create the file,
touch blinkyButton.sh
Open the file using
nano
editor,
nano blinkyButton.sh
Copy paste the code below to
blinkyButton.sh
file,
#!/bin/bash
while :
do
if (( $(gpioget --bias=pull-up $(gpiofind GPIO18)) == 0))
then
gpioset $(gpiofind GPIO14)=1
else
gpioset $(gpiofind GPIO14)=0
fi
done
Close the editor by pressing
Ctrl + O
followed byEnter
to save the file and then press toCtrl + X
exitNow execute the
blinkyButton.sh
script by typing:
bash blinkyButton.sh
This means when we see HAT Pin 12 (GPIO18) go LOW, we know the button is pressed, so we set HAT Pin 8 (GPIO14) (our LED) to ON, otherwise, we turn it OFF.
You can exit the
blinkyButton.sh
program by pressingCtrl + C
on your keyboard.
Understanding Internal Pull Resistors#
Pull-up and pull-down resistors are used in digital circuits to ensure that inputs to logic settle at expected levels.
Internal pull-up resistors
connects the pin to a high voltage level (e.g., 3.3V) to ensure the pin input reads as a logic high (1) when no active device is pulling it low.Internal pull-down resistors
connects the pin to ground (GND) to ensure the input reads as a logic low (0) when no active device is pulling it high.
These resistors prevent floating inputs and undefined states.
By default, all GPIOs on the HAT Header are configured as Inputs with Pull-up Resistors Enabled.
This is important for something like a button, as without it, once a button is released, it goes in an “undefined” state!
To configure Pull-ups on a per-pin basis, we can use pass the following arguments within gpioget or gpioset:
-B, --bias=[as-is|disable|pull-down|pull-up] (defaults to 'as-is')
- The “Bias” argument has the following options:
as-is - This leaves the bias as-is… quite self explanatory
disable - This state is also known as High-Z (high impedance) where the Pin is left Floating without any bias resistor
pull-down - In this state, the pin is pulled DOWN by the internal 50KΩ resistor
pull-up - In this state, the pin is pulled UP by the internal 50KΩ resistor
For example, a command to read an input with the Bias intentionally disabled would look like this:
gpioget --bias=disable $(gpiofind GPIO14)
Pull resistors are a foundational block of digital circuits and understanding when to (and not to) use them is important.
This article from SparkFun Electronics is a good basic primer - Link
Troubleshooting#
My script won’t run!
Make sure you gave the script execute permissions first and that you’re executing it with a ./
before
To make it executable:
chmod +X scriptName.sh
To run it:
./scriptName.sh
Bonus - Turn all GPIOs ON/OFF#
Copy and paste this with the button on the right to turn all pins ON.
gpioset $(gpiofind GPIO14)=1 ;\ gpioset $(gpiofind GPIO15)=1 ;\ gpioset $(gpiofind GPIO17)=1 ;\ gpioset $(gpiofind GPIO18)=1 ;\ gpioset $(gpiofind GPIO27)=1 ;\ gpioset $(gpiofind GPIO22)=1 ;\ gpioset $(gpiofind GPIO23)=1 ;\ gpioset $(gpiofind GPIO24)=1 ;\ gpioset $(gpiofind GPIO10)=1 ;\ gpioset $(gpiofind GPIO9)=1 ;\ gpioset $(gpiofind GPIO25)=1 ;\ gpioset $(gpiofind GPIO11)=1 ;\ gpioset $(gpiofind GPIO8)=1 ;\ gpioset $(gpiofind GPIO7)=1 ;\ gpioset $(gpiofind GPIO1)=1 ;\ gpioset $(gpiofind GPIO6)=1 ;\ gpioset $(gpiofind GPIO12)=1 ;\ gpioset $(gpiofind GPIO13)=1 ;\ gpioset $(gpiofind GPIO19)=1 ;\ gpioset $(gpiofind GPIO16)=1 ;\ gpioset $(gpiofind GPIO26)=1 ;\ gpioset $(gpiofind GPIO21)=1
Similarly, copy and paste this to turn all pins OFF.
gpioset $(gpiofind GPIO14)=0 ;\ gpioset $(gpiofind GPIO15)=0 ;\ gpioset $(gpiofind GPIO17)=0 ;\ gpioset $(gpiofind GPIO18)=0 ;\ gpioset $(gpiofind GPIO27)=0 ;\ gpioset $(gpiofind GPIO22)=0 ;\ gpioset $(gpiofind GPIO23)=0 ;\ gpioset $(gpiofind GPIO24)=0 ;\ gpioset $(gpiofind GPIO10)=0 ;\ gpioset $(gpiofind GPIO9)=0 ;\ gpioset $(gpiofind GPIO25)=0 ;\ gpioset $(gpiofind GPIO11)=0 ;\ gpioset $(gpiofind GPIO8)=0 ;\ gpioset $(gpiofind GPIO7)=0 ;\ gpioset $(gpiofind GPIO1)=0 ;\ gpioset $(gpiofind GPIO6)=0 ;\ gpioset $(gpiofind GPIO12)=0 ;\ gpioset $(gpiofind GPIO13)=0 ;\ gpioset $(gpiofind GPIO19)=0 ;\ gpioset $(gpiofind GPIO16)=0 ;\ gpioset $(gpiofind GPIO26)=0 ;\ gpioset $(gpiofind GPIO21)=0