代码先锋网 代码片段及技术文章聚合

Jetson Nano 入坑之路 ---- (6)GPIO使用(C/C++)

技术标签: Jetson nano 入坑锦集  c++  开发语言  后端

JetsonGPIO(C++)

JetsonGPIO(C++) is a C++ port of the NVIDIA’s Jetson.GPIO Python library(https://github.com/NVIDIA/jetson-gpio).

Jetson TX1, TX2, AGX Xavier, and Nano development boards contain a 40 pin GPIO header, similar to the 40 pin header in the Raspberry Pi. These GPIOs can be controlled for digital input and output using this library. The library provides almost same APIs as the Jetson.GPIO Python library.

Installation

1. Clone the repository.

git clone https://github.com/pjueon/JetsonGPIO

2. Build and install the library.

Make build directory and change directory to it.

cd JetsonGPIO
mkdir build
cd build

The following commands will build the library and install it to /usr/local directory by default.

  • You can add -DCMAKE_INSTALL_PREFIX=/usr option to install it to /usr according to your preference.
  • You can add -DBUILD_EXAMPLES=ON option to build example codes in samples.
cmake ..
sudo make install

Setting User Permissions

In order to use the Jetson GPIO Library, the correct user permissions/groups must be set first. Or you have to run your program with root permission.

Create a new gpio user group. Then add your user to the newly created group.

sudo groupadd -f -r gpio
sudo usermod -a -G gpio your_user_name

A udev rules file 99-gpio.rules is installed. For the new rule to take place, you either need to reboot or reload the udev rules by running:

sudo udevadm control --reload-rules && sudo udevadm trigger

Linking the Library

Using CMake

Add this to your CMakeLists.txt

find_package(JetsonGPIO)

assuming you added a target called mytarget, then you can link it with:

target_link_libraries(mytarget JetsonGPIO::JetsonGPIO)

Without installation

If you don’t want to install the library you can add it as an external project with CMake’s FetchContent:

include(FetchContent)
FetchContent_Declare(
  JetsonGPIO 
  GIT_REPOSITORY https://github.com/pjueon/JetsonGPIO.git 
  GIT_TAG master
)
FetchContent_MakeAvailable(JetsonGPIO)

target_link_libraries(mytarget JetsonGPIO::JetsonGPIO)

The code will be automatically fetched at configure time and built alongside your project.

Note that with this method the file 99-gpio.rules will not be installed, so you will need to install it to /etc/udev/rules.d/ manually
or run your code with root permissions.

Manual Configuration (Without CMake)

The library header JetsonGPIO.h will be installed in /usr/local/include by default. If you installed the library to /usr, it will be installed in /usr/include.
When you link the library to your code, you should link pthread as well because the library uses std::thread.

The following simple example shows how to build your code with the library:

g++ -o your_program_name your_source_code.cpp -lJetsonGPIO -lpthread

Library API

The library provides almost same APIs as the the NVIDIA’s Jetson GPIO Python library.
The following discusses the use of each API:

1. Include the library

To include the JetsonGPIO use:

#include <JetsonGPIO.h>

All public APIs are declared in namespace “GPIO”. If you want to make your code shorter, you can use:

using namespace GPIO; // optional

2. Pin numbering

The Jetson GPIO library provides four ways of numbering the I/O pins. The first two correspond to the modes provided by the RPi.GPIO library, i.e BOARD and BCM which refer to the pin number of the 40 pin GPIO header and the Broadcom SoC GPIO numbers respectively. The remaining two modes, CVM and TEGRA_SOC use strings instead of numbers which correspond to signal names on the CVM/CVB connector and the Tegra SoC respectively.

To specify which mode you are using (mandatory), use the following function call:

GPIO::setmode(GPIO::BOARD);
// or
GPIO::setmode(GPIO::BCM);
// or
GPIO::setmode(GPIO::CVM);
// or
GPIO::setmode(GPIO::TEGRA_SOC);

To check which mode has been set, you can call:

GPIO::NumberingModes mode = GPIO::getmode();

This function returns an instance of enum class GPIO::NumberingModes. The mode must be one of GPIO::BOARD(GPIO::NumberingModes::BOARD), GPIO::BCM(GPIO::NumberingModes::BCM), GPIO::CVM(GPIO::NumberingModes::CVM), GPIO::TEGRA_SOC(GPIO::NumberingModes::TEGRA_SOC) or GPIO::NumberingModes::None.

3. Warnings

It is possible that the GPIO you are trying to use is already being used external to the current application. In such a condition, the Jetson GPIO library will warn you if the GPIO being used is configured to anything but the default direction (input). It will also warn you if you try cleaning up before setting up the mode and channels. To disable warnings, call:

GPIO::setwarnings(false);

4. Set up a channel

The GPIO channel must be set up before use as input or output. To configure
the channel as input, call:

// (where channel is based on the pin numbering mode discussed above)
GPIO::setup(channel, GPIO::IN); // channel must be int or std::string

To set up a channel as output, call:

GPIO::setup(channel, GPIO::OUT);

It is also possible to specify an initial value for the output channel:

GPIO::setup(channel, GPIO::OUT, GPIO::HIGH);

5. Input

To read the value of a channel, use:

int value = GPIO::input(channel);

This will return either GPIO::LOW(== 0) or GPIO::HIGH(== 1).

6. Output

To set the value of a pin configured as output, use:

GPIO::output(channel, state);

where state can be GPIO::LOW(== 0) or GPIO::HIGH(== 1).

7. Clean up

At the end of the program, it is good to clean up the channels so that all pins are set in their default state. To clean up all channels used, call:

GPIO::cleanup();

If you don’t want to clean all channels, it is also possible to clean up
individual channels:

GPIO::cleanup(chan1); // cleanup only chan1

8. Jetson Board Information and library version

To get information about the Jetson module, use/read:

std::string info = GPIO::JETSON_INFO;

To get the model name of your Jetson device, use/read:

std::string model = GPIO::model;

To get information about the library version, use/read:

std::string version = GPIO::VERSION;

This provides a string with the X.Y.Z version format.

9. Interrupts

Aside from busy-polling, the library provides three additional ways of monitoring an input event:

The wait_for_edge() function

This function blocks the calling thread until the provided edge(s) is detected. The function can be called as follows:

GPIO::wait_for_edge(channel, GPIO::RISING);

The second parameter specifies the edge to be detected and can be GPIO::RISING, GPIO::FALLING or GPIO::BOTH. If you only want to limit the wait to a specified amount of time, a timeout can be optionally set:

// timeout is in milliseconds__
// debounce_time set to 10ms
GPIO::WaitResult result = GPIO::wait_for_edge(channel, GPIO::RISING, 10, 500);

The function returns a GPIO::WaitResult object that contains the channel name for which the edge was detected.

To check if the event was detected or a timeout occurred, you can use .is_event_detected() method of the returned object or just simply cast it to bool type:

// returns the channel name for which the edge was detected ("None" if a timeout occurred)
std::string eventDetectedChannel = result.channel();

if(result.is_event_detected()){ /*...*/ }
// or 
if(result){ /*...*/ } // is equal to if(result.is_event_detected())

The event_detected() function

This function can be used to periodically check if an event occurred since the last call. The function can be set up and called as follows:

// set rising edge detection on the channel
GPIO::add_event_detect(channel, GPIO::RISING);
run_other_code();
if(GPIO::event_detected(channel))
    do_something();

As before, you can detect events for GPIO::RISING, GPIO::FALLING or GPIO::BOTH.

A callback function run when an edge is detected

This feature can be used to run a second thread for callback functions. Hence, the callback function can be run concurrent to your main program in response to an edge. This feature can be used as follows:

// define callback function
void callback_fn(const std::string& channel) {
    std::cout << "Callback called from channel " << channel << std::endl;
}

// add rising edge detection
GPIO::add_event_detect(channel, GPIO::RISING, callback_fn);

Any object that satisfies the following requirements can be used as callback functions.

  • Callable (argument type: const std::string&, return type: void)
  • Copy-constructible
  • Equality-comparable with same type (ex> func0 == func1)

Here is a user-defined type callback example:

// define callback object
class MyCallback
{
public:
    MyCallback(const std::string& name) : name(name) {}
    MyCallback(const MyCallback&) = default; // Copy-constructible

    void operator()(const std::string& channel) // Callable
    {
        std::cout << "A callback named " << name;
        std::cout << " called from channel " << channel << std::endl;
    }

    bool operator==(const MyCallback& other) const // Equality-comparable
    {
        return name == other.name;
    }

private:
    std::string name;
};

// create callback object
MyCallback my_callback("foo");
// add rising edge detection
GPIO::add_event_detect(channel, GPIO::RISING, my_callback);

More than one callback can also be added if required as follows:

void callback_one(const std::string& channel) {
    std::cout << "First Callback" << std::endl;
}

void callback_two(const std::string& channel) {
    std::cout << "Second Callback" << std::endl;
}

GPIO::add_event_detect(channel, GPIO::RISING);
GPIO::add_event_callback(channel, callback_one);
GPIO::add_event_callback(channel, callback_two);

The two callbacks in this case are run sequentially, not concurrently since there is only one event thread running all callback functions.

In order to prevent multiple calls to the callback functions by collapsing multiple events in to a single one, a debounce time can be optionally set:

// bouncetime set in milliseconds
GPIO::add_event_detect(channel, GPIO::RISING, callback_fn, 200);

If one of the callbacks are no longer required it may then be removed:

GPIO::remove_event_callback(channel, callback_two);

Similarly, if the edge detection is no longer required it can be removed as follows:

GPIO::remove_event_detect(channel);

10. Check function of GPIO channels

This feature allows you to check the function of the provided GPIO channel:

GPIO::Directions direction = GPIO::gpio_function(channel);

The function returns either GPIO::IN(GPIO::Directions::IN) or GPIO::OUT(GPIO::Directions::OUT) which are the instances of enum class GPIO::Directions.

11. PWM

See samples/simple_pwm.cpp for details on how to use PWM channels.

The JetsonGPIO library supports PWM only on pins with attached hardware PWM controllers. Unlike the RPi.GPIO library, the JetsonGPIO library does not implement Software emulated PWM. Jetson Nano supports 2 PWM channels, and Jetson AGX Xavier supports 3 PWM channels. Jetson TX1 and TX2 do not support any PWM channels.

The system pinmux must be configured to connect the hardware PWM controlller(s) to the relevant pins. If the pinmux is not configured, PWM signals will not reach the pins! The JetsonGPIO library does not dynamically modify the pinmux configuration to achieve this. Read the L4T documentation for details on how to configure the pinmux.

版权声明:本文为qq_25662827原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_25662827/article/details/122627727

智能推荐

Jetson nano 用C++控制GPIO口

之前一直用python库来控制jetson nano的GPIO,终于有了C++的库! 注:NVIDIA官方Jetson GPIO Python库到C ++的非官方移植 有关环境搭建和JetosnGPIO库的使用,请参考:...

Jetson Nano

使用正确的镜像源 Jetson Nano的架构不是arm64,所以很多换源的教程,提供的镜像源里面可能没有Nano可用的。所以sudo apt-get update的时候就会出现找不到的error。这篇文章指出清华的源是包含了aarch64架构的,就不会出现问题。 配置环境 这里参考这篇。 这里面讲了怎么装虚拟环境来管理。之前看过一个博客说直接anaconda是不好装的。所以用虚拟环境,也一定程度...

jetson nano

问题 system throttled due to over-current...

Jetson Nano安装pycuda(踩坑传)

文章目录 脚本自动安装 手动安装 验证pycuda是否安装成功 Resources 脚本自动安装 先使用如下脚本进行安装,如果成功则万事大吉,如果报错请继续往下看 我自己配置的时候遇到两种错误 执行完前两行后所有指令都无法使用:sudo, ls, pip… 运行错误(红色) 手动安装 请先确保nvcc -V正确输出 下载pycuda源码 解压文件并编译(这里等待的时间比较长) 如果出...

Jetson Nano 开放vnc 使用vnc 连接 Jstson Nano

Jetson Nano 开放vnc 使用vnc 连接 Jstson Nano Enable the VNC server to start each time you log in If you have a Jetson Nano 2GB Developer Kit (running LXDE) For all other Jetson developer kits (running GNOME...

猜你喜欢

Jetson nano使用-- ROS安装记录

文章目录 前言 一、Nano环境配置 1、检查当前系统的交换空间和内存 2、增加2G的使用空间 3、为使**永远有效 4、验证是否有效 二、更新系统并移除无用软件 1、移除LibreOffice 2、更新系统并还原 3、更新软件列表并进行软件更新 三、pip安装 1、安装pip 2、pip换源 四、ROS安装 1、 添加ROS国内源 2、添加** 3、安装 4、环境设置 5、依赖包安装 6、初始化...

Jetson Nano(四):GPIO的安装与初步使用

GPIO的Github链接: https://github.com/NVIDIA/jetson-gpio 参考: 1.Jetson Nano GPIO使用、四种模式以及串口解释 https://blog.csdn.net/cynophile/article/details/99310678 2. Jetson Nano系列教程3:GPIO http://ww...

基于Jetson Nano 的 GPIO 控制LED灯闪烁

基于Jetson Nano 的 GPIO 控制LED灯闪烁 将LED的正极接在Jetson Nano的第十一个引脚上,负极接在第三十九个引脚(GND)上,通过控制引脚输出高低电平,控制LED的亮灭,通过time库,中的.sleep()方法控制间隔的时间。 代码如下: 完成GPIO的控制后,需要释放GPIO资源。 效果视频: 基于Jetson nano GPIO 控制LED闪烁...

Jetson Nano下载C++ 版本的GPIO 并配置进qt项目

Jetson Nano官方版本的GPIO是python版的,不过有大佬开源了C++版本的。C++ GPIO项目地址 从Github上clone下来,安装即可。 在.pro文件中加入以下语句即可将GPIO引入项目内 GPIO的API详情查看仓库地址,同时可以参考Python版的API...

Nvida Jetson Nano 安装QT采坑记

Nvida Jetson Nano 安装QT采坑记 第一次接触Jetson Nano,该硬件的系统为Ubuntu 18系统 arm64架构,许多应用都是基于ubuntu amd架构,因此在上面安装qt不同于平时的ubuntu系统。 采坑:我将源更新成了国内的大学源,然后输入命令 但是报错出现 下列软件包未满足依赖关系, qt5-default 依赖 qtbase5-dev,但是它将不会被安装。 等...