Using the GPIOs on your ZED Box Mini and Mini Carrier Board
The ZED Box Mini and Mini Carrier Board expose 2 GPIOs (General Purpose Input/Output) that can be used for various purposes, such as controlling external devices or reading sensor data.
The GPIO pins are accessible via the GPIO
header located on the back side of the ZED Box Mini and Mini Carrier Board.
A full description of the pinout is available in the Connectivity Guide.
- #03 - GPIO_11 [CMOS-3.3V]
- #04 - GPIO_12 [CMOS-3.3V]
GPIO_11
and GPIO_12
can be used as general-purpose I/O pins. They are 3.3V compliant and can be configured as either inputs or outputs.
Setup the device #
📌 Note: If you purchased the ZED Box Mini or the Mini Carrier Board before October 2025, please upgrade your device by using the flash script available in the Flash to Reset/Upgrade section of the documentation. This is required to enable the
GPIO_11
andGPIO_12
pins.
Install the required software #
To control the GPIO pins, you need to install the latest version of the libgpiod library from source, including its C++ and Python bindings. The version provided in the Ubuntu 22.04 repositories is outdated and does not include the necessary development files for building or running recent examples.
mkdir -p ~/libgpiod
cd ~/libgpiod
# Download the latest stable version of libgpiod (replace x.y.z with the actual, i.e 2.2.2)
wget https://mirrors.edge.kernel.org/pub/software/libs/libgpiod/libgpiod-x.y.z.tar.xz
tar -xvf ./libgpiod-x.y.z.tar.xz
cd ./libgpiod-x.y.z/
./configure --enable-bindings-cxx --enable-bindings-python --enable-tools
make -j6
sudo make install
Add user to the gpio group #
Add the current user to the gpio
group to access the GPIO pins without using sudo
:
sudo usermod -aG gpio $USER
Using the GPIO pins as input #
When using the GPIO pins as inputs, you must connect either a pull-up or pull-down resistor to ensure reliable signal detection. A 470 Ω resistor has been validated for this purpose.
Pull-down resistor: Use a pull-down resistor to detect when the pin is connected to VCC (logic high).
Pull-up resistor: Use a pull-up resistor to detect when the pin is connected to GND (logic low).
📌 Note: Without a pull-up or pull-down resistor, the input pin retains the set state (latch), without returning to the defaults state when the input voltage is removed. This can lead to unreliable readings.
Command Line Interface (CLI) #
The libgpiod
package includes command-line tools to interact with GPIO pins. The following examples demonstrate how to set and read the GPIO pins using these tools.
Set a pin HIGH, then wait for the user to press ENTER:
GPIO_11
(PQ.06):gpioset --mode=wait gpiochip0 106=1
GPIO_12
(PN.01):gpioset --mode=wait gpiochip0 85=1
Set a pin LOW, then wait for the user to press ENTER:
GPIO_11
(PQ.06):gpioset --mode=wait gpiochip0 106=0
GPIO_12
(PN.01):gpioset --mode=wait gpiochip0 85=0
Remove --mode=wait
to execute the command without waiting for user input. This is useful for floating pins.
Read the GPIO level:
GPIO_11
(PQ.06):gpioget gpiochip0 106
GPIO_12
(PN.01):gpioget gpiochip0 85
Read two values at the same time:
gpioget gpiochip0 106 85
If you added a Pull-Down resistor to the GPIO pin, you can use the VCC_3V3
pin (pin #07) of the GPIO
header to stimulate the GPIO pins during the reading and verify their functionality in real-time.
If you added a Pull-Up resistor to the GPIO pin, you can use one GND
pin (pin #2 or pin #8) of the GPIO
header to stimulate the GPIO pins during the reading and verify their functionality in real-time.
You can find the full documentation of each CLI command on the official guide.
Python example #
The following Python script demonstrates how to control and read the GPIO pins using the gpiod
library. It toggles the state of GPIO_11
and GPIO_12
every second for 10 seconds, then reads their values for another 10 seconds.
If you added a Pull-Down resistor to the GPIO pin, you can use the VCC_3V3
pin (pin #07) of the GPIO
header to stimulate the GPIO pins during the reading phase and verify their functionality in real-time.
If you added a Pull-Up resistor to the GPIO pin, you can use one GND
pin (pin #2 or pin #8) of the GPIO
header to stimulate the GPIO pins during the reading phase and verify their functionality in real-time.
import time
import gpiod
from gpiod.line import Direction, Value
# Get information about the GPIO chip
with gpiod.Chip("/dev/gpiochip0") as chip:
info = chip.get_info()
print(f"GPIO Chip: {info.name} [{info.label}] - {info.num_lines} lines")
# Define GPIO lines
line11 = 106 # GPIO_11
line12 = 85 # GPIO_12
# Set the lines as OUTPUT and set initial values to HIGH
request_out = gpiod.request_lines(
"/dev/gpiochip0",
consumer="example",
config={
line11: gpiod.LineSettings(direction=Direction.OUTPUT, output_value=Value.ACTIVE),
line12: gpiod.LineSettings(direction=Direction.OUTPUT, output_value=Value.ACTIVE)
}
)
# Toggle GPIO_11 and GPIO_12 values for 10 seconds
total=10
for i in range(total):
if i%2 == 1:
output11=Value.ACTIVE
output12=Value.INACTIVE
else:
output11=Value.INACTIVE
output12=Value.ACTIVE
print(f"[{i+1}/{total} Set Value - GPIO_11: {output11} / GPIO_12: {output12}", end ='\r')
# Set GPIO_11 LOW
request_out.set_value(line11, output11)
# Set GPIO_12 HIGH
request_out.set_value(line12, output12)
# Wait 1 second
time.sleep(1)
print()
# Set both lines to LOW before releasing them
request_out.set_values(
values={
line11: Value.INACTIVE,
line12: Value.INACTIVE
}
)
# Release the lines
request_out.release()
# Set the lines as INPUT
request_in = gpiod.request_lines(
"/dev/gpiochip0",
consumer="example",
config={
line11: gpiod.LineSettings(direction=Direction.INPUT),
line12: gpiod.LineSettings(direction=Direction.INPUT)
}
)
# Read GPIO_11 and GPIO_12 values for 10 seconds
duration=10.0
start = time.time()
exit = False
while (exit==False):
now = time.time()
elapsed = now-start
if(elapsed>10):
exit = True
# Read GPIO11
value11 = request_in.get_value(line11)
# Read GPIO12
value12 = request_in.get_value(line12)
# Print the current values with remaining time
remaining = int(duration-elapsed)
print(f"Read Value - GPIO_11: {value11} / GPIO_12: {value12} - to end: {remaining} sec", end ='\r')
print()
The output will look like this:
$ python3 test_gpio.py
GPIO Chip: gpiochip0 [tegra234-gpio] - 164 lines
[10/10 Set Value - GPIO_11: Value.ACTIVE / GPIO_12: Value.INACTIVE
Read Value - GPIO_11: Value.INACTIVE / GPIO_12: Value.INACTIVE - to end: 0 sec
The first line shows the GPIO chip information, the second line shows the status of the toggling operation, and the last line shows the read values of the GPIO pins. The information will update in place while the script is running.
You can find the full documentation of the Python binding API in the official guide.
C++ example #
The following C++ program demonstrates how to control GPIO_11
and GPIO_12
using the gpiod
library. It toggles the state of GPIO_11
and GPIO_12
every second for 10 seconds, then reads their values for another 10 seconds.
If you added a Pull-Down resistor to the GPIO pin, you can use the VCC_3V3
pin (pin #07) of the GPIO
header to stimulate the GPIO pins during the reading phase and verify their functionality in real-time.
If you added a Pull-Up resistor to the GPIO pin, you can use one GND
pin (pin #2 or pin #8) of the GPIO
header to stimulate the GPIO pins during the reading phase and verify their functionality in real-time.
#include <iostream>
#include <string>
#include <gpiod.hpp>
#include <thread>
#include <chrono>
// Function to toggle single GPIO line value
gpiod::line::value toggle_value(::gpiod::line::value v);
// Function to toggle multiple GPIO line values
void toggle_values(gpiod::line::values &values);
// Function to print GPIO line offsets and their corresponding values
void print_values(gpiod::line::offsets const &offsets, gpiod::line::values const &values);
// Main function to demonstrate GPIO line manipulation
int main(void) {
// Set the GPIO chip system path
const std::filesystem::path chip_path("/dev/gpiochip0");
// Define the GPIO line offsets to be used
const ::gpiod::line::offsets line_offsets = {
106, // GPIO_11
85 // GPIO_12
};
// Retrieve a GPIO chip by its path and print its name and label
gpiod::chip chip(chip_path);
auto info = chip.get_info();
std::cout << "GPIO chip: " << info.name() << " [" << info.label() << "] ("
<< info.num_lines() << " lines)" << ::std::endl;
// Initialize GPIO line values
gpiod::line::values values = {
gpiod::line::value::ACTIVE, // GPIO_11
gpiod::line::value::INACTIVE // GPIO_12
};
// Create a request to toggle multiple GPIO lines
auto request =
chip.prepare_request()
.set_consumer("test_gpio")
.add_line_settings(
line_offsets,
::gpiod::line_settings().set_direction(
::gpiod::line::direction::OUTPUT))
.set_output_values(values)
.do_request();
// Toggle the GPIO lines for ten seconds
const int duration = 10;
for (int i = 0; i < duration; i++) {
std::cout << "\r[" << (i + 1) << "/" << duration << "] Set Value: ";
print_values(line_offsets, values);
std::this_thread::sleep_for(std::chrono::seconds(1));
toggle_values(values);
request.set_values(line_offsets, values);
}
std::cout << std::endl;
// Reconfigure the GPIO lines as inputs
request.reconfigure_lines(gpiod::line_config().add_line_settings(
line_offsets,
gpiod::line_settings()
.set_direction(::gpiod::line::direction::INPUT)));
// Read and print the GPIO line values for ten seconds
auto start = std::chrono::steady_clock::now();
int64_t elapsed=0;
do {
// Read the current values of the GPIO lines
auto read_values = request.get_values(line_offsets);
// Print the read values
std::cout << "\rRead Value: ";
print_values(line_offsets, read_values);
std::this_thread::sleep_for(std::chrono::milliseconds(10));
// Update elapsed time (sec)
elapsed = (std::chrono::steady_clock::now() - start).count() / 1'000'000'000;
std::cout << " - " << elapsed << " sec " << std::flush;
} while (elapsed < std::chrono::seconds(duration).count());
std::cout << std::endl;
return EXIT_SUCCESS;
}
gpiod::line::value toggle_value(::gpiod::line::value v)
{
return (v == gpiod::line::value::ACTIVE) ?
gpiod::line::value::INACTIVE :
gpiod::line::value::ACTIVE;
}
void toggle_values(gpiod::line::values &values)
{
for (size_t i = 0; i < values.size(); i++)
values[i] = toggle_value(values[i]);
}
void print_values(gpiod::line::offsets const &offsets,
gpiod::line::values const &values)
{
for (size_t i = 0; i < offsets.size(); i++)
std::cout << (offsets[i]==106?"GPIO_11":"GPIO_12") << ": " << values[i] << " " << std::flush;
}
Build and Run #
Create a file named test_gpio.cpp
and copy the C++ code above into it. Then, compile the program using the following command:
g++ -o test_gpio test_gpio.cpp -lgpiodcxx -lgpiod
Finally, you can run the example:
./test_gpio
The output will look like this:
$ ./test_gpio
GPIO chip: gpiochip0 [tegra234-gpio] (164 lines)
[10/10] Set Value: GPIO_11: INACTIVE GPIO_12: ACTIVE
Read Value: GPIO_11: INACTIVE GPIO_12: INACTIVE - 10 sec
The first line shows the GPIO chip information, the second line shows the status of the toggling operation, and the last line shows the read values of the GPIO pins. The information will update in place while the script is running.
Other examples and more complex use cases can be found in the libgpiod Source Code repository.
You can find the full documentation of the C++ binding API in the official guide.
If you have any questions or need assistance with GPIO programming, please visit the StereoLabs Forums to connect with the community and get support from our experts.