Jetson.GPIO 使用教程

系列文章目录


前言

        Jetson TX1、TX2、AGX Xavier 和 Nano 开发板包含一个 40 针 GPIO 针座,类似于 Raspberry Pi 中的 40 针针座。这些 GPIO 可使用 Jetson GPIO 库软件包中提供的 Python 库进行数字输入和输出控制。该库的 API 与 Raspberry Pi 的 RPi.GPIO 库相同,目的是提供一种简单的方法,将 Raspberry Pi 上运行的应用程序转移到 Jetson 板上。

        本文将介绍 Jetson GPIO 库软件包的内容、如何配置系统和运行所提供的示例应用程序,以及库的 API。


一、软件包组件

        除本文外,Jetson GPIO 库软件包还包含以下内容:

        lib/python/ 子目录包含实现所有库功能的 Python 模块。gpio.py 模块是将导入应用程序的主要组件,并提供所需的 API。gpio_event.py 和 gpio_pin_data.py 模块由 gpio.py 模块使用,不得直接导入应用程序。

        samples/ 子目录包含示例应用程序,有助于熟悉库 API 和开始应用程序。simple_input.py 和 simple_output.py 应用程序分别展示了如何对 GPIO 引脚进行读写操作,而 button_led.py、button_event.py 和 button_interrupt.py 则分别展示了如何使用忙等待、阻塞等待和中断回调来按下按钮以闪烁 LED。

二、安装

        以下是在系统中安装 Jetson.GPIO python 模块的方法。如需示例应用程序,请克隆此软件源到您的系统。

2.1 使用 pip

        使用 pip 安装此库是最简单的方法:

sudo pip install Jetson.GPIO

2.2 手动下载

        您可以克隆此 git 仓库,也可以下载存档文件并解压。您可以将程序库文件放置在系统中任意位置。您可以通过手动设置PYTHONPATH 直接使用此目录中的库,也可以使用 setup.py 安装:

sudo python3 setup.py install

三、设置用户权限

        要使用 Jetson GPIO 库,首先必须设置正确的用户权限/组。

        创建一个新的 gpio 用户组。然后将用户添加到新创建的组中。

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

        将 99-gpio.rules 文件复制到 rules.d 目录,安装自定义的 udev 规则。

        如果您已经下载了 Jetson.GPIO.Rule 的源代码,请将其复制到 rules.d 目录中:

sudo cp lib/python/Jetson/GPIO/99-gpio.rules /etc/udev/rules.d/

        如果您从软件包中安装了 Jetson.GPIO,例如使用 pip 将其安装到虚拟环境中:

sudo cp venv/lib/pythonNN/site-packages/Jetson/GPIO/99-gpio.rules /etc/udev/rules.d/

        要执行新规则,需要重新启动或运行 udev 规则重新加载:

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

四、运行示例脚本

        根据需要设置权限后,就可以使用 samples/ 目录中提供的示例应用程序。下面将介绍每个应用程序的操作:

        simple_input.py: 该应用程序使用 BCM 引脚编号模式,读取 40 引脚接头第 12 引脚的值并将其打印到屏幕上。

        simple_out.py: 此应用程序使用 Raspberry Pi 的 BCM 管脚编号模式,每隔 2 秒在 BCM 第 18 管脚(或针座上的电路板第 12 管脚)上交替输出高低值。

        button_led.py: 此应用程序使用 BOARD 引脚编号。它需要一个连接 18 针和接地的按钮、一个连接 18 针和 3V3 的上拉电阻以及一个连接 12 针的 LED 和限流电阻。程序会读取按钮状态,并在每次按下按钮时使 LED 亮起 1 秒钟。

        button_event.py: 该程序使用 BOARD 引脚编号。它需要一个连接到 18 针和 GND 的按钮、一个连接按钮和 3V3 的上拉电阻以及一个连接到 12 针的 LED 和限流电阻。该应用程序执行与 button_led.py 相同的功能,但对按钮按下事件执行阻塞等待,而不是持续检查引脚的值,以减少 CPU 占用。

        button_interrupt.py: 该应用程序使用 BOARD 引脚编号。它需要一个连接到第 18 针和接地引脚的按钮、一个将按钮连接到 3V3 的上拉电阻、一个连接到第 12 针的 LED 和限流电阻,以及一个连接到第 13 针的第二个 LED 和限流电阻。该应用会持续缓慢闪烁第一个 LED 灯,只有在按下按钮时才会快速闪烁第二个 LED 灯五次。

        若要运行这些示例应用程序,请将 Jetson.GPIO 添加到PYTHONPATH:

python3 <name_of_application_to_run>

        如果 Jetson.GPIO 没有添加到PYTHONPATH,也可以使用 run_sample.sh 脚本运行这些示例程序。在 samples/ 目录下,可使用以下命令完成此操作:

./run_sample.sh <name_of_application_to_run>

        还可以通过以下方式查看脚本的使用情况:

./run_sample.sh -h
./run_sample.sh --help

五、完整的库 API


        Jetson GPIO 库提供 RPi.GPIO 库提供的所有公共 API。下面将讨论每个 API 的使用:

5.1 导入库

        要导入 Jetson.GPIO 模块,请使用

import Jetson.GPIO as GPIO

        这样,您就可以在应用程序的其余部分中将该模块称为 GPIO。对于使用 RPi 库的现有代码,也可以使用 RPi.GPIO 而不是 Jetson.GPIO 来导入模块。

5.2 引脚编号

        Jetson GPIO 库提供四种 I/O 引脚编号方式。前两种与 RPi.GPIO 库提供的模式相对应,即 BOARD 和 BCM,分别指 40 引脚 GPIO 接头的引脚编号和 Broadcom SoC GPIO 编号。其余两种模式,即 CVM 和 TEGRA_SOC 使用字符串而非数字,分别对应 CVM/CVB 连接器和 Tegra SoC 上的信号名称。

        要指定使用哪种模式(必选),请使用以下函数调用:        

GPIO.setmode(GPIO.BOARD)
# or
GPIO.setmode(GPIO.BCM)
# or
GPIO.setmode(GPIO.CVM)
# or
GPIO.setmode(GPIO.TEGRA_SOC)

        要查看已设置的模式,可以使用:

mode = GPIO.getmode()

        模式必须为 GPIO.BOARD、GPIO.BCM、GPIO.CVM、GPIO.TEGRA_SOC 或 None。

5.3 警告

        您尝试使用的 GPIO 有可能已在当前应用程序的外部使用。在这种情况下,如果正在使用的 GPIO 被配置为默认方向(输入)以外的任何其他方向,Jetson GPIO 库将向您发出警告。如果在设置模式和通道前尝试清理,也会发出警告。要禁用警告,请调用

GPIO.setwarnings(False)

        此外,Jetson.GPIO 使用警告模块发出警告。因此,您可以使用 Python 标准库 - 警告来控制警告消息。

5.4 设置通道

        在将 GPIO 通道用作输入或输出之前,必须对其进行设置。要将通道配置为输入,请调用

# (where channel is based on the pin numbering mode discussed above)
GPIO.setup(channel, GPIO.IN)

        要将通道设置为输出,请使用:

GPIO.setup(channel, GPIO.OUT)

        还可以指定输出通道的初始值:

GPIO.setup(channel, GPIO.OUT, initial=GPIO.HIGH)

        将通道设置为输出时,也可以同时设置多个通道:

# add as many as channels as needed. You can also use tuples: (18,12,13)
channels = [18, 12, 13]
GPIO.setup(channels, GPIO.OUT)

5.5 输入

        要读取通道的数值,请使用

GPIO.input(channel)

        这将返回 GPIO.LOW 或 GPIO.HIGH。

5.6 输出

        要设置配置为输出的引脚的值,请使用

GPIO.output(channel, state)

        其中状态可以是 GPIO.LOW 或 GPIO.HIGH。

        您也可以输出到通道列表或通道元组:

channels = [18, 12, 13] # or use tuples
GPIO.output(channels, GPIO.HIGH) # or GPIO.LOW
# set first channel to LOW and rest to HIGH
GPIO.output(channels, (GPIO.LOW, GPIO.HIGH, GPIO.HIGH))

5.7 清理

        程序结束时,最好清理一下通道,以便将所有引脚设置为默认状态。要清理所有使用过的通道,请调用

GPIO.cleanup()

        如果不想清理所有通道,也可以清理单个通道或通道列表或通道元组:

GPIO.cleanup(chan1) # cleanup only chan1
GPIO.cleanup([chan1, chan2]) # cleanup only chan1 and chan2
GPIO.cleanup((chan1, chan2))  # does the same operation as previous statement

5.8 Jetson 板信息和库版本

        要获取有关 Jetson 模块的信息,请使用/阅读        

GPIO.JETSON_INFO

        这提供了一个 Python 字典,其中包含以下键值: P1_REVISION、RAM、REVISION、TYPE、MANUFACTURER 和 PROCESSOR。字典中的所有值都是字符串,只有 P1_REVISION 是整数。

        要获取有关库版本的信息,请使用/read:

GPIO.VERSION

        这将提供一个包含 X.Y.Z 版本格式的字符串。

5.9 中断

        除忙轮询外,程序库还提供了三种监测输入事件的方法:

        wait_for_edge() 函数
        该函数会阻塞调用线程,直到检测到所提供的边沿。该函数的调用方法如下:

GPIO.wait_for_edge(channel, GPIO.RISING)

        第二个参数指定要检测的边沿,可以是 GPIO.RISING、GPIO.FALLING 或 GPIO.BOTH。如果只想将等待时间限制在指定时间内,可以选择设置超时:

# timeout is in seconds
GPIO.wait_for_edge(channel, GPIO.RISING, timeout=500)

        函数返回检测到边沿的通道,如果发生超时则返回 "无"。

        event_detected() 函数
        该函数可用于定期检查上次调用后是否发生了事件。该函数的设置和调用方法如下:

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

        和以前一样,您可以检测 GPIO.RISING、GPIO.FALLING 或 GPIO.BOTH 的事件。

        检测到边沿时运行回调函数
        该功能可用于为回调函数运行第二个线程。因此,回调函数可与主程序同时运行,以响应边缘。该功能的使用方法如下:

# define callback function
def callback_fn(channel):
    print("Callback called from channel %s" % channel)

# add rising edge detection
GPIO.add_event_detect(channel, GPIO.RISING, callback=callback_fn)

        如有需要,还可添加多个回调,具体如下:

def callback_one(channel):
    print("First Callback")

def callback_two(channel):
    print("Second Callback")

GPIO.add_event_detect(channel, GPIO.RISING)
GPIO.add_event_callback(channel, callback_one)
GPIO.add_event_callback(channel, callback_two)

        在这种情况下,两个回调函数是顺序运行的,而不是并发运行的,因为只有一个线程在运行所有的回调函数。

        为了防止多次调用回调函数,将多个事件合并为一个事件,可以选择设置一个延时:

# bouncetime set in milliseconds
GPIO.add_event_detect(channel, GPIO.RISING, callback=callback_fn,
bouncetime=200)

        后台运行的线程将空闲等待事件,直到超时为止,超时时间可选择设置如下。默认轮询超时为 0.2 秒。当轮询超时时,线程将被唤醒并检查线程状态。如果线程处于运行状态,它将回到空闲状态等待另一个事件,否则,线程将退出(事件检测移除)。这个过程将一直持续到线程处于退出状态。

# polltime set in seconds
GPIO.add_event_detect(channel, GPIO.RISING, callback=callback_fn,
polltime=1)

        如果不再需要边缘检测,可按如下方法将其删除:

GPIO.remove_event_detect(channel)

        可以设置超时选项来等待事件检测被移除,否则默认为 0.5 秒。建议删除超时时间至少为轮询时间的两倍。

GPIO.remove_event_detect(channel, timeout=0.5)

5.10 检查 GPIO 通道的功能

        此功能可让您检查所提供 GPIO 通道的功能:

GPIO.gpio_function(channel)

        函数返回 GPIO.IN 或 GPIO.OUT。

5.11 PWM

        有关如何使用 PWM 通道的详细信息,请参见 samples/simple_pwm.py。

        Jetson.GPIO 库仅支持带有附加硬件 PWM 控制器的引脚上的 PWM。与 RPi.GPIO 库不同,Jetson.GPIO 库不实现软件模拟 PWM。Jetson Nano 支持 2 个 PWM 通道,Jetson AGX Xavier 支持 3 个 PWM 通道。Jetson TX1 和 TX2 不支持任何 PWM 通道。

        系统 pinmux 必须配置为将硬件 PWM 控制器连接到相关引脚。如果未配置 pinmux,PWM 信号将无法到达引脚!为此,Jetson.GPIO 库不会动态修改 pinmux 配置。有关如何配置 pinmux 的详细信息,请阅读 L4T 文档。

六、在 docker 容器中使用 Jetson GPIO 库

        下面介绍如何在 docker 容器中使用 Jetson GPIO 库。

6.1 构建 docker 映像

        samples/docker/Dockerfile 是 Jetson GPIO 库的示例 Dockerfile。下面的命令将从中构建一个名为 testimg 的 docker 镜像。

sudo docker image build -f samples/docker/Dockerfile -t testimg .

6.2 运行容器

6.2.1 基本选项

        要访问 GPIO 引脚,必须将 /dev 映射到容器中。因此,你需要在 docker 容器运行命令中添加这些选项。

--device /dev/gpiochip0 \

        如果要使用容器中的 GPU,还需要添加这些选项:

--runtime=nvidia --gpus all

6.2.2 以私有模式运行容器

        默认情况下,程序库通过检查 /proc/device-tree/compatible 和 /proc/device-tree/chosen 来确定 jetson 模式。这些路径只能在隐私模式下映射到容器中。

        下面的示例将在私有模式下从容器运行 /bin/bash。

sudo docker container run -it --rm \
--runtime=nvidia --gpus all \
--privileged \
-v /proc/device-tree/compatible:/proc/device-tree/compatible \
-v /proc/device-tree/chosen:/proc/device-tree/chosen \
--device /dev/gpiochip0 \
testimg /bin/bash

6.2.3 以非私有模式运行容器

        如果不想在私有模式下运行容器,可以通过环境变量 JETSON_MODEL_NAME 直接向库提供自己的 jetson 模型名:

# ex> -e JETSON_MODEL_NAME=JETSON_NANO
-e JETSON_MODEL_NAME=[PUT_YOUR_JETSON_MODEL_NAME_HERE]

        您可以在主机上或预编译模式下运行 samples/jetson_model.py,获取该变量的正确值。

# run on the host or in previlleged mode
sudo python3 samples/jetson_model.py

        下面的示例将以非特权模式从容器运行 /bin/bash。        

sudo docker container run -it --rm \
--runtime=nvidia --gpus all \
--device /dev/gpiochip0 \
-e JETSON_MODEL_NAME=[PUT_YOUR_JETSON_MODEL_NAME_HERE] \
testimg /bin/bash

七、获取 L4T 文档

        L4T 文档可在以下位置获取:

  • Jetson 下载中心;搜索 "L4T 文档 "包。
  • docs.nvidia.com。

        在文档中,可搜索相关话题,如

  • 硬件设置。
  • 配置 40 针扩展接头。
  • Jetson-IO。
  • 平台适配和调试
  • Pinmux 更改

相关推荐

  1. Elasticsearch-Kibana使用教程

    2024-06-16 07:04:03       28 阅读
  2. mc使用教程

    2024-06-16 07:04:03       34 阅读
  3. conda使用教程

    2024-06-16 07:04:03       34 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-16 07:04:03       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-16 07:04:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-16 07:04:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-16 07:04:03       18 阅读

热门阅读

  1. 19C之前恢复drop 掉的PDB 创建另一个实例

    2024-06-16 07:04:03       8 阅读
  2. 从零开始!如何安装和配置Jupyter Notebook

    2024-06-16 07:04:03       6 阅读
  3. 网站开发常规安全规范(持续更新)

    2024-06-16 07:04:03       7 阅读
  4. 大数据开发语言Scala入门

    2024-06-16 07:04:03       9 阅读
  5. 71、最长上升子序列II

    2024-06-16 07:04:03       9 阅读
  6. HTML5应用程序缓存:构建离线可用的Web应用

    2024-06-16 07:04:03       8 阅读
  7. 数据仓库数据集成开源工具

    2024-06-16 07:04:03       9 阅读
  8. 神经网络-文本-图像-音频-视频基础知识

    2024-06-16 07:04:03       10 阅读
  9. flinksql BUG : flink hologres-cdc source FINISHED

    2024-06-16 07:04:03       10 阅读
  10. python命名空间详解

    2024-06-16 07:04:03       9 阅读
  11. 搭建Python虚拟环境(三):Conda

    2024-06-16 07:04:03       10 阅读
  12. vuex是什么?如何使用?使用他的功能场景?

    2024-06-16 07:04:03       9 阅读