JETSON-NANO-DEV-KIT

来自Waveshare Wiki
跳转至: 导航搜索
{{{name2}}}
{{{name3}}}
功能简介
特性 小型AI计算机
GPU 128- Core NVIDIA Maxwell™
CPU 64-bit Quad-core ARM A57 (1.43GHz)
内存 4GB 64-bit LPDDR4 25.6GB/s
' 无特性,不解释
接口

产品介绍

备注

如果您购买的是微雪提供的带核心板的Nano套件,出厂的时候我们已经预先烧好了JetPack4.6镜像在emmc上,且已经设置了SD卡识别。如果需要修改SD卡启动,请查看使用手册修改启动路径即可。
如果您对出厂镜像版本有特殊要求,请联系微雪店铺客服沟通确认。

简介

JETSON-NANO-DEV-KIT 是微雪电子基于 Jetson Nano Module 核心板设计的,提供了与 Jetson Nano Developer Kit (B01) 几乎一模一样的外设接口、大小及厚度,核心板升级更方便。可借助其运行核心板,从而实现图像分类、目标检测、分割、语音处理等功能,并应用到各种人工智能项目当中。

  • JETSON-NANO-DEV-KIT与B01官方套件相比,Nano 核心板取消TF卡槽,增加了16GB eMMC存储芯片,读写稳定。
  • 取消DC供电口的排针开关,连接使用DC电源,不需要先使用跳线帽将J48接口短接,直接将DC电源插入到圆形电源接口即可。
  • 微雪的JETSON-NANO-DEV-KIT除了支持U盘启动,还在扩展板上集成TF卡槽,支持TF启动,读写稳定,和B01官方核心板带TF卡槽相比使用起来几乎一样。

Jetson Nano Module 参数

GPU NVIDIA Maxwell™ 架构,配有 128 个 NVIDIA CUDA® 核心 0.5 TFLOPS (FP16)
CPU 四核 ARM® Cortex®-A57 MPCore 处理器
内存 4 GB 64 位 LPDDR4
1600 MHz – 25.6 GB/s
存储 16 GB eMMC 5.1 闪存
视频编码 250 MP/s

1x 4K @ 30 (HEVC)
2x 1080p @ 60 (HEVC)
4x 1080p @ 30 (HEVC)

视频解码 500 MP/s

1x 4K @ 60 (HEVC)
2x 4K @ 30 (HEVC)
4x 1080p @ 60 (HEVC)
8x 1080p @ 30 (HEVC)

摄像头 12 通道(3x4 或 4x2)MIPI CSI-2 D-PHY 1.1 (18 Gbps)
联网 Wi-Fi 需要外部芯片

10/100/1000 BASE-T 以太网

显示 eDP 1.4 | DSI (1 x2) 2 同步
UPHY 1 个 x1/2/4 PCIE、1 个 USB 3.0、3 个 USB 2.0
IO 3 个 UART、2 个 SPI、2 个 I2S、4 个 I2C、多个 GPIO

JETSON-IO-BASE-A底板 资源

JETSON-IO-BASE-A-details-intro.jpg
  1. 模组卡座
    插入Jetson Nano核心板
  2. SD卡扩展卡槽
    可以接入SD卡做SD卡扩展。
  3. M.2 Key E接口
    可接入AC8265无线网卡
  4. 1.25mm 风扇接口
  5. PoE管脚
    不含PoE模块
  6. 40PIN GPIO扩展接口
    兼容树莓派引脚,方便就树莓派外设(需要程序支持)
  7. 2.54mm 风扇接口
  8. Micro USB接口
    可用于5V电源输入或者USB数据传输
  9. 千兆以太网端口
    10/100/1000Base-T 自适应,接入 PoE 模块可支持 PoE 供电
  10. 4路USB 3.0接口
  11. HDMI高清接口
  12. DisplayPort接口
  13. DC电源接口
    可用于5V电源输入
  14. 2路MIPI CSI摄像头接口

尺寸图

JETSON-IO-BASE-A-details-size.jpg


使用说明

安装系统

系统环境搭建及EMMC系统烧录

  • 烧录系统需要用到Ubuntu 18.04主机或虚拟机,使用SDK Manager工具烧录。
  • 本教程系统环境使用的是VMware 16虚拟机安装Ubuntu 18.04系统,仅供学习使用。
  • 如果您有Ubuntu虚拟机或者主机但不是18.04的且能接受格式化SD卡或U盘的,请参考系统环境搭建方法二。

方法一:使用SDK Manager工具

  1. 下载SDK Manager烧录工具,打开浏览器输入网址,点击下载SDK Manager。
    https://developer.nvidia.com/zh-cn/embedded/jetpack

    NVIDIA注册水印-1.png
    需要注册一个账号,登录以后我们才能成功下载,不知道如何注册的可以参考英伟达账号注册

  2. 下载完成后,我们进入下载路径Downloads进行安装,终端输入:
    sudo dpkg -i sdkmanager_1.6.1-8175_amd64.deb(根据自己的版本输入)

    安装sdk水印-1.png

  3. 安装完成后,系统可能会报错找不到依赖文件,输入以下命令解决此问题。
    sudo apt --fix-broken install
  4. 打开Ubuntu电脑终端,运行SDK Manager打开软件。
  5. 点击LOGIN,登录NVIDIA账号,会在浏览器弹出链接,输入前面注册邮箱和密码登录进去。
    LOGIN水印-1.png
  6. 此时我们就成功登录SDK Manager
    LOGIN-success水印.png

EMMC安装镜像

    器材准备
    1. Jetson Nano 主板。
    2. Ubuntu18.04 虚拟机(或电脑主机)。
    3. 5V 4A电源适配器。
    4. 跳线帽(或杜邦线)。
    5. USB 数据线(Micro USB接口,可传输数据)。
    硬件配置(进入recovery 模式)
    1. 用跳帽或者杜邦线短接FC REC和GND引脚,位置如下图,位于核心板底下。
    2. 连接DC电源到圆形供电口, 稍等片刻。
    3. 用USB线(注意要是数据线)连接Jetson Nano的Micro USB接口到Ubuntu主机。
      Jetson-nano-Force recovery2-水印.png
    系统烧录
    1. 开Ubuntu电脑终端,运行SDK Manager打开软件。
    2. 使用虚拟机需要把设备设置为连接到虚拟机上。
      虚拟机识别水印.png
    3. 登录账号,如果Jetson Nano 有被正常识别到,SDK Manager会检测并提示选项。
      选择开发板水印.png
    4. 在JetPack选项中,以JetPack4.6系统为例,取消勾选Host Machine,点击CONTINUE。
      去掉host水印.png
    5. 选择Jetson OS, 并将Jetson SDK Components的选项去掉。勾选协议,点击CONTINUE。
      取消勾选sdk水印.png
      注意:二者都勾选会导致下载失败。
    6. HW Imager保存的路径默认就好,选择Create,就会自动创建路径。
      Jetson-create水印.png
    7. 从JetPack4.6.1版本开始,用SDK Manager烧系统的时候会弹出preconfig的窗口,这里按照下图选择。Preconfig水印.png
    8. 注意:上图中的 7. OME Configuration里的Pre-config选项是提前设置用户名和密码,Runtime是在Jetson Nano的开机配置过程中设置用户名和密码。
    9. 输入虚拟机密码,等待下载,烧录完成即可。
      Jetson-emmc-flash-success水印.png
    10. 烧录完成之后,去掉底板的跳帽,接入显示器,重新上电,按照提示进行开机配置(如果是设置的pre-config, 上电后直接进入系统)。

方法二:直接下载资源包

以下资源包下载以Jetpack4.6.2为例,其他Jetpack版本的资源包下载方法请参考FAQ里的资源包下载方法

安装系统

  1. unbuntu虚拟机或者主机打开终端,新建文件夹
    sudo mkdir sources_nano
    cd sources_nano 
  2. 下载路径
    https://developer.nvidia.com/embedded/l4t/r32_release_v7.2/t210/jetson-210_linux_r32.7.2_aarch64.tbz2
    https://developer.nvidia.com/embedded/l4t/r32_release_v7.2/t210/tegra_linux_sample-root-filesystem_r32.7.2_aarch64.tbz2

    将资源包移到文件夹,并解压(实际操作的时候,请尽量用tab按键自动补齐指令)

    sudo mv ~/Downloads/Jetson-210_Linux_R32.7.2_aarch64.tbz2 ~/sources_nano/            
    sudo mv ~/Downloads/Tegra_Linux_Sample-Root-Filesystem-R32.7.2_aarch64.tbz2 ~/sources_nano/  
  3. 解压资源
    sudo tar -xjf Jetson-210_Linux_R32.7.2_aarch64.tbz2
    cd Linux_for_Tegra/rootfs/       
    sudo tar -xjf ../../Tegra_Linux_Sample-Root-Filesystem_R32.7.2_aarch64.tbz2
    cd ../
    sudo ./apply_binaries.sh  (若出现报错按提示操作,再重新输入该指令)    

EMMC安装镜像

    器材准备
    1. Jetson Nano 主板。
    2. Ubuntu虚拟机(或电脑主机)。
    3. 5V 4A电源适配器。
    4. 跳线帽(或杜邦线)。
    5. USB 数据线(Micro USB接口,可传输数据)。
    硬件配置(进入recovery 模式)
    1. 用跳帽或者杜邦线短接FC REC和GND引脚,位置如下图,位于核心板底下。
    2. 连接DC电源到圆形供电口, 稍等片刻。
    3. 用USB线(注意要是数据线)连接Jetson Nano的Micro USB接口到Ubuntu主机。
      Jetson-nano-Force recovery2-水印.png
    系统烧录
    1. 烧录系统,Jetson Nano 需进入recovery模式,连接到Ubuntu电脑。
      cd ~/sources_nano/Linux_for_Tegra
      sudo ./flash.sh jetson-nano-emmc mmcblk0p1
    2. 烧录完成之后,去掉底板的跳帽,接入显示器,重新上电,按照提示进行开机配置(如果是设置的pre-config, 上电后直接进入系统)。

U盘启动和TF卡启动原理

  • U盘启动或TF卡启动都是先启动核心板里的EMMC上的系统,再由核心板的系统引导到U盘上启动或TF卡上启动。
  • 核心板里的系统可以使用虚拟机中的SDK Manager来烧录系统;TF卡系统可以使用Win32DiskImager来烧录系统;U盘里的系统使用虚拟机烧录。
  • 在进行准备U盘启动或者TF卡启动时,先确保成功烧录EMMC系统。

U盘启动(复制eMMC上系统)

器材准备

  1. Jetson Nano 主板。
  2. USB接口的U盘的或者移动硬盘 (建议使用USB3.0)。
  3. 5V 4A电源适配器。

系统安装

  1. 将U盘接入Jetson Nano,查看U盘的设备号,例如sda,打开Jetson Nano终端输入
    ls /dev/sd*
  2. 格式化U盘。
    sudo mkfs.ext4 /dev/sda

    只剩下sda,如下图:
    Device number.jpg

  3. 修改启动路径
    sudo vi /boot/extlinux/extlinux.conf
    找到语句APPEND ${cbootargs} quiet root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 console=ttyS0,115200n8 console=tty0,将mmcblk0p1修改为sda保存
  4. 挂载U盘
    sudo mount /dev/sda /mnt
  5. 复制系统到U盘(该过程没有信息打印请耐心等待)
    sudo cp -ax / /mnt
  6. 复制完成后卸载U盘(不是拔掉U盘)
    sudo umount /mnt/
  7. 重启系统
    sudo reboot

TF卡启动

方法一:直接复制eMMC上系统

注意:该操作会格式化TF卡

    器材准备
    1. Jetson Nano 主板。
    2. 5V 4A电源适配器。
    烧录引导程序
    1. 在虚拟机安装安装dtc软件
      sudo apt-get install device-tree-compiler
    2. 进入HW Imager内核路径下,反编译dts源文件
      若使用的SDK Manager软件请使用以下命令:
      cd ~/nvidia/nvidia_sdk/JetPack_4.6_Linux_JETSON_NANO_TARGETS/Linux_for_Tegra/kernel/dtb (针对不同jetpack,修改对应路径)
      dtc -I dtb -O dts -o tegra210-p3448-0002-p3449-0000-b00.dts tegra210-p3448-0002-p3449-0000-b00.dtb
      若使用的资源包请使用以下命令:
      cd sources_nano/Linux_for_Tegra/kernel/dtb
      dtc -I dtb -O dts -o tegra210-p3448-0002-p3449-0000-b00.dts tegra210-p3448-0002-p3449-0000-b00.dtb
      
    3. 修改设备树
      sudo vim tegra210-p3448-0002-p3449-0000-b00.dts
    4. 找到sdhci@700b0400部分,将status = "disable"改成okay,下面添加TF信息。
      cd-gpios = <0x5b 0xc2 0x0>;
      sd-uhs-sdr104;
      sd-uhs-sdr50;
      sd-uhs-sdr25;
      sd-uhs-sdr12;
                  
      no-mmc;
      uhs-mask = <0xc>;

      Nano-tf-dts水印.png

    5. 编译dtb文件
      dtc -I dts -O dtb -o tegra210-p3448-0002-p3449-0000-b00.dtb tegra210-p3448-0002-p3449-0000-b00.dts
    6. 烧录系统,Jetson Nano 需进入recovery模式,连接到Ubuntu电脑。
      若使用的SDK Manager软件请使用以下命令:
      cd ~/nvidia/nvidia_sdk/JetPack_4.6_Linux_JETSON_NANO_TARGETS/Linux_for_Tegra
      sudo ./flash.sh jetson-nano-emmc mmcblk0p1
      若使用的资源包请使用以下命令:
      cd sources_nano/Linux_for_Tegra
      sudo ./flash.sh jetson-nano-emmc mmcblk0p1
      
    7. 检查SD卡是否被识别:
      sudo ls /dev/mmcblk*
    8. 如果有识别到mmcblk1p1 设备,说明SD卡被正常识别了。
      SD卡识别水印.png
    9. 格式化SD卡
      sudo mkfs.ext4 /dev/mmcblk1

      如果出现以下提示已有文件系统
      File system.jpg
      先卸载SD卡:

      sudo umount /media/(这里按下Tab键自动补全)

      再次使用格式化命令格式化SD卡。
      格式化成功后输入:

      sudo ls /dev/mmcblk* 

      只有mmcblk1,如下图:
      Config1.jpg

    10. 修改启动路径
      sudo vi /boot/extlinux/extlinux.conf
      找到语句APPEND ${cbootargs} quiet root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 console=ttyS0,115200n8 console=tty0,将mmcblk0p1修改为mmcblk1保存
    11. 挂载SD卡
      sudo mount /dev/mmcblk1 /mnt
    12. 复制系统到SD卡(该过程没有信息打印请耐心等待)
      sudo cp -ax / /mnt
    13. 复制完成后卸载SD卡(不是拔掉SD卡)
      sudo umount /mnt/
    14. 重启系统
      sudo reboot

方法二:SD卡另外有镜像

    器材准备
    1. Jetson Nano 主板。
    2. 5V 4A电源适配器。
    烧录引导程序
    1. 在虚拟机安装安装dtc软件
      sudo apt-get install device-tree-compiler
    2. 进入HW Imager内核路径下,反编译dts源文件 (针对不同jetpack,修改对应路径)
      cd ~/nvidia/nvidia_sdk/JetPack_4.6_Linux_JETSON_NANO_TARGETS/Linux_for_Tegra/kernel/dtb
      dtc -I dtb -O dts -o tegra210-p3448-0002-p3449-0000-b00.dts tegra210-p3448-0002-p3449-0000-b00.dtb
    3. 修改设备树
      sudo vim tegra210-p3448-0002-p3449-0000-b00.dts
    4. 找到sdhci@700b0400部分,将status = "disable"改成okay,下面添加TF信息。
      cd-gpios = <0x5b 0xc2 0x0>;
      sd-uhs-sdr104;
      sd-uhs-sdr50;
      sd-uhs-sdr25;
      sd-uhs-sdr12;
                  
      no-mmc;
      uhs-mask = <0xc>;

      Nano-tf-dts水印.png

    5. 编译dtb文件
      dtc -I dts -O dtb -o tegra210-p3448-0002-p3449-0000-b00.dtb tegra210-p3448-0002-p3449-0000-b00.dts
    6. 烧录系统,Jetson Nano 需进入recovery模式,连接到Ubuntu电脑。
      cd ~/nvidia/nvidia_sdk/JetPack_4.6_Linux_JETSON_NANO_TARGETS/Linux_for_Tegra
      sudo ./flash.sh jetson-nano-emmc mmcblk0p1
    7. 断开USB线和跳帽,Jetson Nano开机配置
    8. 检查SD卡是否被识别:
      sudo ls /dev/mmcblk*
    9. 如果有识别到mmcblk1p1 设备,说明SD卡被正常识别了。 SD卡识别水印.png
    10. 修改从SD卡启动系统 (可选)
      sudo vi /boot/extlinux/extlinux.conf
      • 找到语句APPEND ${cbootargs} quiet root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 console=ttyS0,115200n8 console=tty0,将mmclk0p1 改成mmcblk1p1, 保存,然后重启系统即可。
      • 如果使用的是我们提供的镜像,重启系统后用户名为:jetson,密码为:jetson,如果是用户自己安装的镜像,则是用户设置的用户名和密码。

      注意:如果SD卡内存是64G的,在进入系统后,打开终端,输入df -h ,查看磁盘大小,若空间大小不正常,请参考FAQ里的扩容镜像。
      内存水印.png

系统登录

本地登录

  • 使用微雪提供的镜像,用户名和用户密码如下
    用户名:waveshare
    用户密码:waveshare

远程登录

准备工作

  • 用一根网线一端连接Jetson Nano,另一端连接路由器的LAN端口。
  • 确保Jetson Nano与你的电脑出于一个路由器下或同一网段。

获取Jetson Nano的IP地址

  • 方法一:登录路由器查找Jetson Nano的IP地址。
  • 方法二:你可以通过一些局域网IP扫描工具,这里以Advanced IP Scanner为例程
    1. 运行Advanced IP Scanner
    2. 点击Scan按钮,扫描当前局域网内的IP地址
    3. 找到所有Manufacturer中有NVIDIA字样的IP地址并记录
      NVIDIA-ip水印.png
    4. 将设备上电,并确保设备连接上网络后
    5. 重新点击Scan按钮,扫描当前局域网内的IP地址
    6. 排除掉所有先前记录的Manufacturer中有NVIDIA字样的IP地址,剩下的就是你的NVIDIA的IP地址了
  • 方法三:屏幕IP查询
    1. Jetson Nano连接上网线或者装上无线网卡连接WIFI,在终端输入ifconfig ,查看Jetson Nano的IP地址。
    2. 有线网络.png

使用MobaXterm登录

终端窗口
  1. 下载MobaXterm远程登录软件,解压即可使用。
  2. 打开MobaXterm远程登录软件,选择Session,选择ssh。
  3. 在Remote host输入我们前面查询到的IP地址192.168.15.102(根据自己的实际IP来填写),填写完成后,点击ok。
    登录水印.png
  4. 点击Accept,微雪提供镜像登录名:waveshare,回车输入登录密码:waveshare(在输入密码时,屏幕没有变化属于正常现象,点击回车确认即可)
    Aceept-1水印.png

NoMachine登录

  • 相比SSH和VNC大家对Nomachine可能了解不是很多,Nomachine是一款免费的远程桌面软件。
  • NoMachine基本覆盖了所有主流大操作系统,包括Windows,Mac,Linux,iOS,Android和Raspberry等等。
Jetson Nano上安装
  1. 下载、解压Jetson Nano的NoMachine安装包
  2. 解压完成后,使用U盘或者文件传输方式将.deb文件复制到Jetson Nano中
  3. 使用指令来安装
    sudo dpkg -i nomachine_7.10.1_1_arm64.deb
Windows电脑上安装
  • 下载NoMachine安装包,打开安装,等待进度条结束,点击Finish,最后还需要重启下电脑
    Nomachine-安装水印.gif
连接Jetson Nano
  1. 打开NoMachine,在Search输入Jetson Nano的IP地址。例如:192.168.15.100
    Nomachine-1水印.png
  2. 点击Connect to new host 192.168.15.100,输人Jetson Nano登录名和登录密码,点击login
    Nomachine-login水印.png
  3. 加载完成后,会出现一些软件介绍界面,我们直接点击ok就可以了
    Nomachine-ok水印.png
  4. 此时我们就成功登录Jetson Nano
    Nomachine-success水印.png

VNC登录

  • 在没有显示屏的情况下,想要进入Jetson Nano的桌面,此时就需要使用远程桌面登陆。(建议使用显示屏,VNC有一定延时)

配置VNC服务器

  • Jetson Nano使用vino来作为默认的VNC服务器,但是默认的设置需要进行一些修改。
  1. 配置VNC Server
    gsettings set org.gnome.Vino require-encryption false
    gsettings set org.gnome.Vino prompt-enabled false
    gsettings set org.gnome.Vino authentication-methods "['vnc']"
    gsettings set org.gnome.Vino lock-screen-on-disconnect false
    gsettings set org.gnome.Vino vnc-password $(echo -n "mypassword"|base64)
    • 需要注意的是,不要用sudo来运行上面的命令,mypassword就是连接VNC的密码。
  2. 设置桌面开机自启,在.config路径下新建一个自启文件
     mkdir -p .config/autostart
    sudo vim ~/.config/autostart/vino-server.desktop

    添加以下内容:

    [Desktop Entry]
    Type=Application
    Name=Vino VNC server
    Exec=/usr/lib/vino/vino-server
    NoDisplay=true
  3. 查看当前用的是什么管理器
    cat /etc/X11/default-display-manager
  4. 编辑文件
    sudo vim /etc/gdm3/custom.conf
  5. 把下面三行的注释去掉,其中AutomaticLogin行修改成自己的用户名。
    WaylandEnable=false
    AutomaticLoginEnable = true
    AutomaticLogin = waveshare
  6. 重启Jetson Nano
    sudo reboot
下载安装VNC Viewer
使用VNC Viewer远程连接Jetson Nano
  1. 打开VNC Viewer,输入Jetson Nano的IP地址回车确认。例如:
    192.168.15.102
  2. 输入前面设置的VNC登录密码,点击ok:
  3. 此时就成功登录Jetson Nano了。
    VNC-DESKTOP水印.png

SDK安装

Jetpack主要包括系统镜像,库,APIs,开发者工具,示例和一些文档。在SDK Manager软件中,我们首先安装的是OS,也就是系统镜像,未安装的部分便是SDK,如下图,您可以使用指令直接安装或者使用SDK Manger安装
SDK.jpg
SDK里包含TensorRT、cuDNN、CUDA、Multimedia API、Computer Vision、Developer Tools。

  • TensorRT :用于图像分类、分割和对象检测神经网络的高性能深度学习推理运行,它加快了深度学习推理的速度,并减少了卷积和反卷积神经网络的运行时内存占用。
  • cuDNN :CUDA深度神经网络库为深度学习框架提供高性能原语,它包括对卷积、激活函数和张量变换的支持。
  • CUDA :CUDA工具包为构建 GPU 加速应用程序的 C 和C++开发人员提供了一个全面的开发环境。该工具包包括用于 NVIDIA GPU 的编译器、数学库以及用于调试和优化应用程序性能的工具。
  • ultimedia API : Jetson Multimedia API为灵活的应用程序开发提供了低级 API。
  • Computer Vision :VPI(视觉编程接口)是一个软件库,提供在PVA1(可编程视觉加速器)、GPU和CPU上实现的计算机视觉/图像处理算法,其中OpenCV是用于计算机视觉、图像处理和机器学习的领先开源库,现在具有用于实时操作的 GPU 加速功能,其中VisionWorks2是一个用于计算机视觉(CV)和图像处理的软件开发包。
  • Developer Tools :Developer Tools CUDA工具包为构建GPU加速应用程序的C和C++开发人员提供了一个全面的开发环境。该工具包包括用于NVIDIA GPU的编译器、数学库以及用于调试和优化应用程序性能的工具。

以上是SDK的部分功能。 前面的系统安装的时候只是安装了基本的系统,其他的JetPack SDK组件,比如CUDA等都需要在系统正常启动后进一步安装,这里提供安装SDK的步骤说明。若要安装该部分,请保证是在以TF卡或者U盘为主系统的情况下,因为下载内容可能会导致EMMC磁盘容量告急。

使用SDK Manager安装

使用SDK Manager安装SDK的时候,不需要设置nano为recovery模式,也就是不需要进行短接引脚的操作。

  • 正常上电启动Nano
  • Jetson Nano进入系统正常启动后,用USB数据线连接Jetson Nano的Micro USB接口到Ubuntu主机
  • Ubuntu主机电脑运行sdkmanager指令打开SDK Managaer(需要先安装SDK Manager)
  • 类似于前面烧录系统的操作,不同的是,在步骤而中,不勾选 OS选项,而是勾选SDK' 选项, 然后continue到安装
  • 在下载资源之后,会弹窗提示填写用户名和密码,填写nano系统的用户名和密码即可
  • 等待SDK安装成功

使用指令安装

没有ubuntu或虚拟机的用户,可以选择在Jetson Nano上使用以下指令直接进行安装

sudo apt update
sudo apt install nvidia-jetpack

Linux操作基础

常见指令介绍

文件系统

sudo
  • sudo命令以系统管理者的身份执行指令。
  • 要想使用root用户,可使用waveshare用户登录,执行下面命令
  • sudo su   #切换为超级用户
    su waveshare #切换普通用户
    
ls
  • ls命令用于显示指定工作目录下之内容(列出目前工作目录所含之文件及子目录)。
  • 常用的指令:
    ls
    ls -a   #显示所有文件及目录 (. 开头的隐藏文件也会列出)
    ls -l   #除文件名称外,亦将文件型态、权限、拥有者、文件大小等资讯详细列出
    ls -lh  #文件大小以容易理解的格式列出,例如4K
    
  • 想要学习了解指令更多参数,我们可以使用help指令来查看:
    ls --help
chmod
  • chmod命令是控制用户对文件的权限的命令。
  • Linux/Unix 的文件调用权限分为三级 : 文件所有者(Owner)、用户组(Group)、其它用户(Other Users)。
  • 在下图中,显示了Linux根目录下的详细文件信息。在这些文件信息中, 最重要的就是第一列,它详细描述了文件和目录的权限,而第三与第四列则显示了这个文件和目录属于哪一个用户或组。
    Jetson-chmod.png
  • Linux的文件属性可以分为三种:只读(r)、写(w)和可执行(x)。但是上面的文件属性却分为10小格,这是因为除了第一格显示目录外,另外三组每组三格分别表示文件所有者权限、同一组内的权限以及其他用户权限。
    • 第一栏中如果显示d,则表示这是一个目录;如果是链接文件,则在这里显示l;如果是设备文件,则显示c。
    • 第一个rwx栏位:-rwx------ 表示文件拥有者所拥有的权限。
    • 第二个rwx栏位:---rwx--- 表示同一工作组内用户权限。
    • 第三个rwx栏位:------rwx 表示其他用户权限。
    • 例如:
    • -rwx rwx rwx 表示无论哪个用户都可以对这个文件读写与执行。
    • -rw- --- --- 表示只有文件拥有者有读写权限,但是没有执行权限。
    • -rw -rw -rw 表示所有用户都有读写权。
  • 符号模式
    • who(用户类型)
      who 用户类型 说明
      u user 文件所有者
      g group 文件所有者所在组
      o others 所有其他用户
      a all 所用用户, 相当于 ugo
    • operator(符号模式表)
      Operator 说明
      + 为指定的用户类型增加权限
      - 去除指定用户类型的权限
      = 设置指定用户权限的设置,即将用户类型的所有权限重新设置
    • permission 的符号模式表
      模式 名字 说明
      r 设置为可读权限
      w 设置为可写权限
      x 执行权限 设置为可执行权限
      X 特殊执行权限 只有当文件为目录文件,或者其他类型的用户有可执行权限时,才将文件权限设置可执行
      s setuid/gid 当文件被执行时,根据who参数指定的用户类型设置文件的setuid或者setgid权限
      t 粘贴位 设置粘贴位,只有超级用户可以设置该位,只有文件所有者u可以使用该位
    • 符号模式实例
      1. 给file的所有用户增加读权限
        chmod a+r file
      2. 删除file的所有用户的执行权限
        chmod a-x file
      3. 给file的所有用户增加读写权限
        chmod a+rw file
      4. 给file的所有用户增加读写执行权限
        chmod +rwx file 
      5. 对file的所有者设置读写权限,清空该用户组和其他用户对file的所有权限(空格代表无权限)
        chmod u=rw,go= file
      6. 对目录waveshare和其子目录层次结构中的所有文件给用户增加读权限,而对用户组和其他用户删除读权限
        chmod -R u+r,go-r waveshare
  • 八进制语法
    • chmod命令可以使用八进制数来指定权限。文件或目录的权限位是由9个权限位来控制,每三位为一组,它们分别是文件所有者(User)的读、写、执行,用户组(Group)的读、写、执行以及其它用户(Other)的读、写、执行。
      # 权限 rwx 二进制
      7 读 + 写 + 执行 rwx 111
      6 读 + 写 rw- 110
      5 读 + 执行 rwx 101
      4 只读 r-- 100
      3 写 + 执行 -wx 011
      2 只写 -w- 010
      1 只执行 --x 001
      0 --- 000
    • 例如:765的解释如下:
      • 所有者的权限用数字表达:属主的那三个权限位的数字加起来的总和。如 rwx ,也就是 4+2+1 ,应该是 7。
      • 用户组的权限用数字表达:属组的那个权限位数字的相加的总和。如 rw- ,也就是 4+2+0 ,应该是 6。
      • 其它用户的权限数字表达:其它用户权限位的数字相加的总和。如 r-x ,也就是 4+0+1 ,应该是 5。
    • 常用的数字权限
      • 400 -r-------- 拥有者能够读,其他任何人不能进行任何操作;
      • 644 -rw-r–r-- 拥有者都能够读,但只有拥有者可以编辑;
      • 660 -rw-rw---- 拥有者和组用户都可读和写,其他人不能进行任何操作;
      • 664 -rw-rw-r-- 所有人都可读,但只有拥有者和组用户可编辑;
      • 700 -rwx------ 拥有者能够读、写和执行,其他用户不能任何操作;
      • 744 -rwxr–r-- 所有人都能读,但只有拥有者才能编辑和执行;
      • 755 -rwxr-xr-x 所有人都能读和执行,但只有拥有者才能编辑;
      • 777 -rwxrwxrwx 所有人都能读、写和执行(该设置不建议使用)。
    • 实例
      • 给file的所有用户增加读权限,拥有者和组用户可编辑权限
        sudo chmod 664 file
touch
  • touch命令用于修改文件或者目录的时间属性,包括存取时间和更改时间。若文件不存在,系统会建立一个新的文件。
  • 例如,在当前目录下,使用该指令创建一个空白文件"file.txt",输入如下命令:
    touch file.txt
mkdir
  • mkdir命令用于创建目录。
  • 在工作目录下,建立一个名为waveshare的子目录 :
    sudo mkdir waveshare
  • 在工作目录下建立一个名为waveshare/test的目录。
    sudo mkdir -p waveshare/test
  • 若waveshare目录原本不存在,则建立一个。(注:本例若不加 -p 参数,且原本 waveshare 目录不存在,则产生错误。)
cd
  • 切换当前工作目录。
    cd ..            #返回上一层目录
    cd /home/waveshare #进入/home/waveshare 目录
    cd               #返回用户目录
    
cp
  • cp命令主要用于复制文件或目录。
  • 参数:
    • -a:此选项通常在复制目录时使用,它保留链接、文件属性,并复制目录下的所有内容。其作用等于dpR参数组合。
    • -d:复制时保留链接。这里所说的链接相当于 Windows 系统中的快捷方式。
    • -f:覆盖已经存在的目标文件而不给出提示。
    • -i:与 -f 选项相反,在覆盖目标文件之前给出提示,要求用户确认是否覆盖,回答y时目标文件将被覆盖。
    • -p:除复制文件的内容外,还把修改时间和访问权限也复制到新文件中。
    • -r:若给出的源文件是一个目录文件,此时将复制该目录下所有的子目录和文件。
    • -l:不复制文件,只是生成链接文件。
  • 使用指令cp将当前目录test/下的所有文件复制到新目录 newtest 下,输入如下命令:
    sudo cp –r test/ newtest 
mv
  • mv命令用来为文件或目录改名、或将文件或目录移入其它位置。
  • 参数:
    • -b: 当目标文件或目录存在时,在执行覆盖前,会为其创建一个备份。
    • -i: 如果指定移动的源目录或文件与目标的目录或文件同名,则会先询问是否覆盖旧文件,输入y表示直接覆盖,输入n表示取消该操作。
    • -f: 如果指定移动的源目录或文件与目标的目录或文件同名,不会询问,直接覆盖旧文件。
    • -n: 不要覆盖任何已存在的文件或目录。
    • -u:当源文件比目标文件新或者目标文件不存在时,才执行移动操作。
  • 使用指令mv将当前目录test/下的file1文件复制到新目录/home/waveshare下,输入如下命令:
    sudo mv file1 /home/waveshare
rm
  • rm命令用于删除一个文件或者目录。
  • 参数:
    • -i 删除前逐一询问确认。
    • -f 即使原档案属性设为唯读,亦直接删除,无需逐一确认。
    • -r 将目录及以下之档案亦逐一删除。
    • 删除文件可以直接使用rm命令,若删除目录则必须配合选项"-r",例如:
    sudo rm  test.txt 
    • rm:是否删除 一般文件 "test.txt"? y
    sudo rm  homework  
    • rm: 无法删除目录"homework": 是一个目录
    sudo rm  -r  homework  
    • rm:是否删除 目录 "homework"? y
reboot
  • reboot命令用于用来重新启动计算机,更改Tinker Board 2的配置经常需要重启。
  • 参数:
    • -n : 在重开机前不做将记忆体资料写回硬盘的动作
    • -w : 并不会真的重开机,只是把记录写到 /var/log/wtmp 档案里
    • -d : 不把记录写到 /var/log/wtmp 档案里(-n 这个参数包含了 -d)
    • -f : 强迫重开机,不呼叫 shutdown 这个指令
    • -i : 在重开机之前先把所有网络相关的装置先停止
  • 重新启动
    sudo reboot
shutdown

  • Jetson Nano的关机是不能直接拔掉电源线的,因为Tinker Board 2会将内存作为暂存区,如果直接拔掉电源线会使一些在内存中的数据没有来得及写入SD卡中,从而造成数据的丢失或是损坏SD卡上的数据,造成系统无法启动。
  • 参数
    • -t seconds : 设定在几秒钟之后进行关机程序。
    • -k : 并不会真的关机,只是将警告讯息传送给所有使用者。
    • -r : 关机后重新开机。
    • -h : 关机后停机。
    • -n : 不采用正常程序来关机,用强迫的方式杀掉所有执行中的程序后自行关机。
    • -c : 取消目前已经进行中的关机动作。
    • -f : 关机时,不做 fsck 动作(检查 Linux 档系统)。
    • -F : 关机时,强迫进行 fsck 动作。
    • time : 设定关机的时间。
    • message : 传送给所有使用者的警告讯息。
  • 实例
    • 立即关机
    sudo shutdown -h now
    • 指定 10 分钟后关机
    sudo shutdown -h 10
    • 重新启动计算机
    sudo shutdown -r now
  • 无论使用哪一个命令来关闭系统都需要root用户权限,如果用户使用linaro这样的普通用户,可以使用sudo命令暂时获得root权限。
pwd
  • 该pwd命令显示当前工作目录的名称:在Jetson nano上,输入pwd将输出类似/home/waveshare。
head
  • 该head命令显示文件的开头。可用于-n指定要显示的行数(默认为 10 行),或与-c指定字节数。
    head test.py -n 5
tail
  • 该tail显示文件的结尾。-c字节或-n行数指定文件中的起始点
df
  • 用于df显示已安装文件系统上可用和使用的磁盘空间。用于df -h以可读的格式查看输出,使用 M 表示 MB,而不是显示字节数。
    df -h
tar
  • tar命令是用来建立,还原备份文件的工具程序,它可以加入,解开备份文件内的文件。
  • 压缩文件:
    tar -cvzf waveshare.tar.gz *
  • 解压文件:
    tar -xvzf waveshare.tar.gz 
apt
  • apt(Advanced Packaging Tool)是一个在 Debian 和 Ubuntu 中的 Shell 前端软件包管理器。
  • apt 命令提供了查找、安装、升级、删除某一个、一组甚至全部软件包的命令,而且命令简洁而又好记。
  • apt 命令执行需要超级管理员权限(root)。
  • apt 常用命令
    • 列出所有可更新的软件清单命令:sudo apt update
    • 升级软件包:sudo apt upgrade
    • 列出可更新的软件包及版本信息:apt list --upgradeable
    • 升级软件包,升级前先删除需要更新软件包:sudo apt full-upgrade
    • 安装指定的软件命令:sudo apt install <package_name>
    • 安装多个软件包:sudo apt install <package_1> <package_2> <package_3>
    • 更新指定的软件命令:sudo apt update <package_name>
    • 显示软件包具体信息,例如:版本号,安装大小,依赖关系等等:sudo apt show <package_name>
    • 删除软件包命令:sudo apt remove <package_name>
    • 清理不再使用的依赖和库文件: sudo apt autoremove
    • 移除软件包及配置文件: sudo apt purge <package_name>
    • 查找软件包命令: sudo apt search <keyword>
    • 列出所有已安装的包:apt list --installed
    • 列出所有已安装的包的版本信息:apt list --all-versions
  • 例如我们安装nano编辑器
    sudo apt install nano

网络

ifconfig
  • 用于在不带任何参数(即)ifconfig运行时显示当前系统上接口的网络配置详细信息。
  • 用SSH连接时可以通过ifconfig查找IP地址,终端输入
    ifconfig
  • 查看有线网络IP地址,终端输入
    ifconfig eth0
  • 查看无线网络IP地址,终端输入
    ifconfig wlan0
hostname
  • 该hostname命令显示系统的当前主机名。我们使用Jetson Nano的时候经常需要使用远程工具,而默认的网络配置IP地址采用动态分配,会造成IP地址不确定的问题
  • 当我们的Jetson Nano的IP地址发生变化时,可以使用主机名登录。
  1. 登录Jetson Nano,修改hosts文件,命令如下:
    sudo vim /etc/hosts
    • 将jp46替换成要修改的名字,例如waveshare,按下键盘ZZ保存、退出:

    Jetson-hosts.png

  2. 修改hostname文件,将这里jp46也替换成要修改的名字,例如waveshare,按下键盘ZZ:
    sudo vim /etc/hostname

    Jetson-hostname.png

  3. 修改完成重启Jetson Nano即可:
    sudo reboot
  4. 我们也可以使用如下命令查看IP地址:
    hostname -I

Vim编辑器使用

  • Vim编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和常用命令。
  • 基本上 vim 共分为三种模式,分别是命令模式(Command mode),输入模式(Insert mode)和底线命令模式(Last line mode)。
    • 命令模式:控制屏幕光标的移动,字符、字或行的删除,移动复制某区段。
    • 输入模式:在此模式下输入字符,编辑文件。
    • 底线模式:将文件保存或退出vim,也可以设置编辑环境,如寻找字符串、列出行号等。
    • 我们可以将这三个模式想成底下的图标来表示:

Vim模式水印-1.png

  1. 首先删除默认Vi编辑器
    sudo apt-get remove vim-common
  2. 然后重装Vim
    sudo apt-get install vim
  3. 为方便使用还得在/etc/vim/vimrc文件后面添加下面三句
    set nu  #显示行号
    syntax on  #语法高亮
    set tabstop=4  #tab退四格

常用命令

  • 打开文件、保存、关闭文件(vi命令模式下使用)
      vim filename     //打开filename文件
           :w                    //保存文件
           :q                    //退出编辑器,如果文件已修改请使用下面的命令
           :q!                   //退出编辑器,且不保存
           :wq                   //退出编辑器,且保存文件
           :wq!                 //强制退出编辑器,且保存文件
           ZZ                    //退出编辑器,且保存文件
           ZQ                   //退出编辑器,且不保存
  • 插入文本或行(vi命令模式下使用,执行下面命令后将进入插入模式,按ESC键可退出插入模式)
    	a       //在当前光标位置的右边添加文本
    	i        //在当前光标位置的左边添加文本
    	A      //在当前行的末尾位置添加文本
    	I       //在当前行的开始处添加文本(非空字符的行首)
    	O     //在当前行的上面新建一行
    	o     //在当前行的下面新建一行
    	R     //替换(覆盖)当前光标位置及后面的若干文本
    	J     //合并光标所在行及下一行为一行(依然在命令模式)
  • 删除、恢复字符或行(vi命令模式下使用)
    	x          //删除当前字符
    	nx        //删除从光标开始的n个字符
    	dd       //删除当前行
    	ndd     //向下删除当前行在内的n行
    	u         //撤销上一步操作
    	U         //撤销对当前行的所有操作
  • 复制、粘贴(vi命令模式下使用)
    	yy      //将当前行复制到缓存区
           	nyy    //将当前行向下n行复制到缓冲区
    	yw     //复制从光标开始到词尾的字符
    	nyw   //复制从光标开始的n个单词
    	y^     //复制从光标到行首的内容
    	y$     //复制从光标到行尾的内容
    	p      //粘贴剪切板里的内容在光标后
    	P      //粘贴剪切板里的内容在光标前

配置

文件传输

  • 本教程以Windows系统远程连接到Linux服务器为例,有多种方式可以把本地的文件上传到服务器。

MobaXterm文件传输

  • 使用MobaXterm工具传输文件是非常简单、方便的
    • 将文件从Windows传输到树莓派只需拖动文件到MobaXterm左边目录里即可
    • 同理,将树莓派文件传输到Windows,只需拖动MobaXterm左边目录里文件到Windows即可。
      MobaXterm-文件传输.gif

NoMachine文件传输

  • 当使用NoMachine远程连接成功后,Jetson Nano桌面右上角会出现NoMachine图标,我们点击图标,选择Transfer a file
    • Upload file from the client是将文件从Windows电脑传输到Jetson Nano上
    • Download file from the server是将文件从Jetson Nano传输到Windows电脑上
      Nomachine-filetransfer水印.png

SCP文件传输

  • SCP命令可用于跨Linux系统安全地复制或加密传输文件和目录。
  • 格式:
    scp +参数 +用户名/登陆名+@+主机名/IP地址+ : + 目标文件路径+本地存放路径
  • 首先进入要存放文件的目录按住键盘Shift且右键空白处,打开Windows PowerShell
  • 将file文件从Jetson Nano复制到本地Windows,在终端输入
    scp waveshare@192.168.15.100:file .

    其中“.”表示当前路径

  • 将file文件从本地Windows复制到Jetson Nano,在终端输入
    scp file waveshare@192.168.15.100:
  • 将file文件夹从Jetson Nano复制到本地Windows,由于file是一个目录,就需要加上参数r,在终端输入
    scp -r waveshare@192.168.15.100:/home/pi/file .
  • 将file文件夹从本地Windows复制到Jetson Nano,在终端输入
     scp -r file waveshare@192.168.15.100:
  • 注意:以上的waveshare需要改成你的系统的用户名,IP地址改成Jetson Nano实际IP地址。

文件共享(Samba)

使用Samba服务可实现文件共享。在windows的网上邻居即可访问Jetson Nano文件系统,非常方便。

  1. 首先安装Samba,在终端输入
    sudo apt-get update
    sudo apt-get install samba -y
  2. 在/home/waveshare目录下创建共享文件夹sambashare
    mkdir sambashare
  3. 安装完成后,修改配置文件/etc/samba/smb.conf:
    sudo nano /etc/samba/smb.conf

    拉到文件的最后,将下面的语句添加到文件尾部

    [sambashare]
       comment = Samba on JetsonNano
       path = /home/waveshare/sambashare
       read only = no
       browsable = yes

    注意:这里的waveshare需要改成你的系统的用户名。也就是说path是你要设置的共享文件夹路径。

  4. 重启Samba服务
    sudo service smbd restart
  5. 设置共享文件夹密码
    sudo smbpasswd -a waveshare

    注意:这里的username需要改成你系统的用户名,如果不是用户名就会失败。
    这里会要求设置Samba密码,建议是直接用你的系统的密码,比较方便记忆

  6. 设置完成之后,在你的电脑端,打开文件管理器
    \\192.168.15.100\sambashare
  7. 输入登录名和前面第5步设置的密码
    Jetson-samba水印.png
  8. 我们来验证下,在windows新建test文件夹,在Jetson Nano sambashare目录下就可以看到test文件夹
    Jetson-nano-Samba1水印.png
    Jetson-nano-Samba水印.png

系统备份

  1. 在Windows电脑桌面上新建一个空白的.img后缀的文件。插入带有系统镜像的SD卡,选择对应的SD卡的盘符。
  2. 打开Win32DiskImager-烧录镜像软件,点击“Read”读取,即可将Jetson Nano的SD卡文件转为镜像。

摄像头

查看接入的第一个摄像头画面:

nvgstcapture-1.0

查看接入的第二个摄像头画面:

nvgstcapture-1.0 --sensor-id=1


FAN

风扇转速调节,注意需要4线才可以调试风扇

sudo sh -c 'echo 255 > /sys/devices/pwm-fan/target_pwm'
#其中255 是最大转速,0是停止,修改值即可修改转速
cat /sys/class/thermal/thermal_zone0/temp
#获取CPU温度,可以通过程序智能控制风扇
#系统自带温控系统,不必要情况可以不需要手动控制


无显示屏连接WiFi(适用带有无线网卡套餐)

  • 在第一次登录成功后,我们后面想连接WiFi使用。
  1. 扫描WIFI
    sudo nmcli dev wifi
  2. 连接到WIFI网络(“wifi_name”和“wifi_password”需要替换为您的实际 WiFi 的 SSID 和密码。)
    sudo nmcli dev wifi connect "wifi_name" password "wifi_password"
  3. 显示“ successfully”就成功连接无线网络了,主板下次开机会自动连接到您指定的 WiFi。
    Jetson-Nmcli.png

AI入门

  • 本教程基于JetPack4.6系统镜像,Python版本为Python3.6,TensorFlow版本为2.5.0,Pytorch版本为1.9.0为例。
  • 注意:TensorFlow版本Pytorch版本一定要和JetPack版本相互对应。

PIP安装

  1. Jetson Nano中默认安装了 Python3.6 版本,直接安装PIP
    sudo apt update
    sudo apt-get install python3-pip python3-dev
  2. 安装完成后我们查看PIP版本
    pip3 -V

    Pip3 9.0.1.png

  3. 默认安装的PIP是 9.01 版本,需要把它升级到最新版
    python3 -m pip install --upgrade pip

    Pip-21.png

  4. 升级成功后,查看pip版本信息,发现有些问题
    pip3 -V

    Pip-V.png

  5. 我们使用命令如下解决
    python3 -m pip install --upgrade --force-reinstall pip
    sudo reboot

    Pip-V1.png

  6. 安装机器学习领域重要的安装包
    安装机器学习领域重要的包
    sudo apt-get install python3-numpy
    sudo apt-get install python3-scipy
    sudo apt-get install python3-pandas
    sudo apt-get install python3-matplotlib
    sudo apt-get install python3-sklearn

设置CUDA环境

  1. 查看CUDA版本,出现command not found,需要配置下环境
    nvcc -V
    cat /usr/local/cuda/version.txt

    Cat-cuda10.2.png
    注意:这里使用cat命令查看不到版本,进入/usr/local/目录查看下是否有CUDA目录,
    如果没有参考后面未安装CUDA部分安装CUDA,安装完成后再配置环境。

  2. 设置环境变量
    sudo vim .bashrc
    在文件末尾加入:
    export PATH=/usr/local/cuda-10.2/bin:$PATH
    export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH
    export CUDA_HOME=$CUDA_HOME:/usr/local/cuda-10.2

    Bashrc-cuda.png

  3. 更新环境变量
    source .bashrc
  4. 再次查看CUDA版本
    nvcc -V

    Nvcc-cuda-success.png

Tensorflow GPU环境搭建

  1. 安装所需要的包
    sudo apt-get install libhdf5-serial-dev hdf5-tools libhdf5-dev zlib1g-dev zip libjpeg8-dev liblapack-dev libblas-dev gfortran
    sudo pip3 install -U pip testresources setuptools==49.6.0
  2. 安装 python 的依赖项
    sudo pip3 install -U --no-deps numpy==1.19.4 future==0.18.2 mock==3.0.5 keras_preprocessing==1.1.2 keras_applications==1.0.8 gast==0.4.0 protobuf pybind11 cython pkgconfig packaging
    sudo env H5PY_SETUP_REQUIRES=0 pip3 install -U h5py==3.1.0
  3. 安装Tensorflow(在线安装经常失败,可以参考第4步离线安装)
    sudo pip3 install --pre --extra-index-url https://developer.download.nvidia.com/compute/redist/jp/v46 tensorflow
  4. 最后建议离线安装,先登录英伟达官网下载TensorFlow安装包(以jetpack4.6 TensorFlow2.5.0 nv21.08为例,建议使用火狐浏览器下载) Jp46-TensorFlow.png
    pip3 install tensorflow-2.5.0+nv21.8-cp36-cp36m-linux_aarch64.whl
  5. 安装完成后,检查是否安装成功,在终端输入
    python3
    import tensorflow as tf

    Tensorflow-success.png

  6. 查看版本信息
    tf.__version__

    Tensorflow-version.png

Pytorch环境搭建

Pytorch安装

  1. 首先登录英伟达官网下载Pytorch安装包,我们以PyTorch v1.9.0为例
    Torch-download.png
  2. 下载依赖库
    sudo apt-get install libjpeg-dev zlib1g-dev libpython3-dev libavcodec-dev libavformat-dev libswscale-dev libopenblas-base libopenmpi-dev
    
  3. 安装Pytorch
    sudo pip3 install torch-1.9.0-cp36-cp36m-linux_aarch64.whl 
  4. 验证Pytorch是否安装成功
    python3
    import torch
    x = torch.rand(5, 3)
    print(x)

    Torch-success.png

  5. 查看版本信息
    import torch
    print(torch.__version__)

    Torch-verson.png

Torchvision安装

  1. Torchvision版本要与Pytorch版本相匹配,我们前面安装的Pytorch版本为1.9.0,Torchvision安装 v0.10.0版本
    Pytorch-torchvision.png
  2. 下载、安装torchvision
    git clone --branch v0.10.0 https://github.com/pytorch/vision torchvision
    cd torchvision
    export BUILD_VERSION=0.10.0
    sudo python3 setup.py install
  3. 验证Torchvision是否安装成功
    python3
    import torchvision

    Torchvision.png

  4. 出现报错可能是Pillow版本太高,卸载重装
    sudo pip3 uninstall pillow
    sudo pip3 install pillow

    Pillow9.1.1.png

  5. 查看版本信息
    import torchvision
    print(torchvision.__version__)

    Torchvision-version.png

Yolo V4环境搭建

  1. 首先在github上下载darknet
    git clone https://github.com/AlexeyAB/darknet.git
  2. 下载完成后,需要修改下Makefile文件
    cd darknet
    sudo vim Makefile

    将前四行0改成1

    GPU=1
    CUDNN=1
    CUDNN_HALF=1
    OPENCV=1
  3. cuda版本和路径也要改成我们的实际版本和路径,否则会编译失败
    将NVCC=nvcc修改为
    NVCC=/usr/local/cuda-10.2/bin/nvcc
  4. 修改完成后进行编译,在终端输入
    sudo make
  5. 使用YOLOv4进行推理

    • 基本的推理方法有三种:图片、视频、摄影头 ( 实时影像 )
    • 选择Yolo v4和Yolo v4-tiny(更轻量化的模型,适合在Jetson Nano上运行)进行测试。首先需要下载已训练好的模型权重文件
    图片测试
    1. 测试
      ./darknet detector test cfg/coco.data cfg/yolov4.cfg yolov4.weights data/dog.jpg

      Yolov4-test水印1.png

    2. 如果要开启图片的话需使用 test模式,他会在执行之后要你输入图片的位置
      ./darknet detector test ./cfg/coco.data ./cfg/yolov4.cfg ./yolov4.weights
    视频测试
    1. Yolov4-tiny 视频的检测(github下来的data里面并没有该视频文件,需要用户自行上传要检测的视频文件到 data 文件夹下)
      ./darknet detector demo cfg/coco.data cfg/yolov4-tiny.cfg yolov4-tiny.weights data/xxx.mp4

      Yolo-MP4水印.png
      帧数大约是14帧

    实时图像测试
    1. 查看USB摄像头的设备号
      ls /dev/video*
      ./darknet detector demo cfg/coco.data  cfg/yolov4-tiny.cfg  yolov4-tiny.weights /dev/video0
      ./darknet detector demo cfg/coco.data  cfg/yolov4.cfg  yolov4.weights /dev/video0

    Hello AI World

    • Hello AI World项目集成了NVIDIA非常强大的 TensroRT 加速引擎,将性能提升了数倍以上。

    环境搭建

    1. 安装cmake
      sudo apt-get update
      sudo apt-get install git cmake libpython3-dev python3-numpy
    2. 获取jetson-inference开源项目
      git clone https://github.com/dusty-nv/jetson-inference
      cd jetson-inference
      git submodule update --init
    3. 新建文件夹,编译
      注意:编译不报错才能正常运行下面的示例。
      sudo mkdir build
      cd build
      sudo cmake ../

      由于内容是外网上的,可能导致下载不了box.com上的文件,所以下载模型和Pytorch界面我们选择跳过(Quit和Skip)。
      Jetson-inference-model水印.png Jetson-inference-pytorch水印.png

    4. 下载模型,然后再放置到jetson-inference/data/networks目录下,然后解压,为了方便用户,这里我们提供部分模型参考下载指令:
      cd ~/jetson-inference/data/networks/
      #如果你需要下载更多的算法,请参考这里的方法,首先在github上获取model的下载地址,然后用wget 加指令下载。这里下载三个model以作参考
      wget https://github.com/dusty-nv/jetson-inference/releases/download/model-mirror-190618/facenet-120.tar.gz
      wget https://github.com/dusty-nv/jetson-inference/releases/download/model-mirror-190618/GoogleNet.tar.gz
      wget https://github.com/dusty-nv/jetson-inference/releases/download/model-mirror-190618/SSD-Mobilenet-v2.tar.gz
      #下面的指令是解压前面下载的model的,只有解压出来才能用
      tar -zxvf facenet-120.tar.gz
      tar -zxvf GoogleNet.tar.gz
      tar -zxvf SSD-Mobilenet-v2.tar.gz
      
    5. 也可以使用U盘或者文件传输方式将文件复制到Jetson Nano中
      cd jetson-inference/build
      sudo make
      sudo make install
    6. 安装v4l摄像头驱动,终端输入
      sudo apt-get install v4l-utils
      v4l2-ctl --list-formats-ext

    DetectNet运行实时摄像头检测

    • 使用摄像头对环境物体进行识别
      cd  ~/jetson-inference/build/aarch64/bin/
      ./detectnet-camera

      Helloai-camera水印.png
      使用TensorRT加速帧率达到24帧。

    • 下面是可供下载的预训练对象检测网络表,以及用于加载预训练模型的相关--network参数:
      ./detectnet-camera --network=facenet #运行使用面部识别网络
      ./detectnet-camera --network=multiped #运行使用多级行人/行李探测器
      ./detectnet-camera --network=pednet #运行使用原始单级行人探测器
      ./detectnet-camera --network=coco-bottle #在摄像头下检测 瓶/汽水罐
      ./detectnet-camera --network=coco-dog #在摄像头下检测狗
    • 让我们使用detectnet程序在静态图像中定位对象。除了输入/输出路径之外,还有一些额外的命令行选项:
      • 更改正在使用的检测模型的可选--network标志(默认为 SSD-Mobilenet-v2)。
      • --overlay标志,可以是逗号分隔的box, lines, labels, conf, 和none
        • 默认--overlay=box,labels,conf显示框、标签和置信度值
        • 该box选项绘制填充的边界框,而lines仅绘制未填充的轮廓
      • --alpha值,设置覆盖期间使用的 alpha 混合值(默认值为120)。
      • --threshold设置检测的最小阈值的可选值(默认为0.5)。
      • --camera 标志设置要使用的摄像头设备
        • 默认为使用 MIPI CSI 传感器 0(--camera=0)
      • --width 和--height 标志设置相机分辨率(默认为 1280x720)
    • 分辨率应设置为相机支持的格式,使用v4l2-ctl --list-formats-ext查询
      ./detectnet-camera --network=facenet #使用 FaceNet,默认 MIPI CSI 相机(1280×720)
      ./detectnet-camera --camera=/dev/video1 --network=facenet #使用 PedNet,V4L2 摄像机/dev/video1(1280x720)
      ./detectnet-camera --width=640 --height=480 --network=facenet #使用 PedNet,默认 MIPI CSI 摄像机(640x480)

    硬件控制

    • Jetson TX1、TX2、AGX Xavier 和 Nano 开发板包含一个 40 针 GPIO 接头,类似于 Raspberry Pi 中的 40 针接头。

    GPIO

    • 可以使用 Jetson GPIO 库包中提供的 Python 库来控制这些 GPIO 的数字输入和输出。
    • Jetson GPIO 库提供了 RPi.GPIO 库提供的所有公共 API。下面讨论每个 API 的使用:
    1. 要导入 Jetson.GPIO 模块,请使用:
      import Jetson.GPIO as GPIO
    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)
        GPIO.setmode(GPIO.BCM)
        GPIO.setmode(GPIO.CVM)
        GPIO.setmode(GPIO.TEGRA_SOC)
      • 要检查已设置的模式,您可以调用:
        mode = GPIO.getmode()
        模式必须是 GPIO.BOARD、GPIO.BCM、GPIO.CVM、GPIO.TEGRA_SOC 或 None 之一。
    3. 如果GRIO检测到一个引脚已经被设置成了非默认值,那么你将看到一个警告信息。
      • 你可以通过下列代码禁用警告:
        GPIO.setwarnings(False)
    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. 输入
      • 要读取通道的值,请使用:
        GPIO.input(channel)
        这将返回 GPIO.LOW 或 GPIO.HIGH。
    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(channel, (GPIO.LOW, GPIO.HIGH, GPIO.HIGH))
    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
    8. Jetson Board 信息和库版本
      • 要获取有关 Jetson 模块的信息,请使用/阅读:
        GPIO.JETSON_INFO

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

      • 要获取有关库版本的信息,请使用/阅读:
        GPIO.VERSION

        这提供了一个具有 XYZ 版本格式的字符串。

    9. 中断
        除了忙轮询之外,该库还提供了三种额外的方法来监视输入事件:
      • wait_for_edge() 函数
      • 此函数阻塞调用线程,直到检测到提供的边缘。该函数可以如下调用:
        GPIO.wait_for_edge(channel, GPIO.RISING)
      • 第二个参数指定要检测的边沿,可以是 GPIO.RISING、GPIO.FALLING 或 GPIO.BOTH。如果您只想将等待限制为指定的时间,可以选择设置超时:
        # timeout is in milliseconds
        GPIO.wait_for_edge(channel, GPIO.RISING, timeout=500)
        该函数返回检测到边缘的通道,如果发生超时,则返回 None。
      • 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)
      • 如果不再需要边缘检测,可以将其删除,如下所示:
        GPIO.remove_event_detect(channel)
    10. 检查GPIO通道功能
      • 此功能允许您检查提供的 GPIO 通道的功能:
        GPIO.gpio_function(channel)
        该函数返回 GPIO.IN 或 GPIO.OUT。

    点亮LED灯

    • 示例程序
      import Jetson.GPIO as GPIO
      import time as time
      
      LED_Pin = 11
      
      GPIO.setwarnings(False)
      GPIO.setmode(GPIO.BOARD)
      GPIO.setup(LED_Pin, GPIO.OUT)
      
      while (True):
         GPIO.output(LED_Pin, GPIO.HIGH)
         time.sleep(0.5)
         GPIO.output(LED_Pin, GPIO.LOW)
         time.sleep(0.5)
      

    例程使用

    • 针对jetson.gpio库,官方也提供了一些简单的例程
    • 首先下载jetson-gpio:
      git clone https://github.com/NVIDIA/jetson-gpio
    • 将下载的文件移动到/opt/nvidia下
      sudo mv ~/jetson-gpio
    • 进入jetson-gpio库文件夹,并安装库
      cd /opt/nvidia/jetson-gpio
      sudo python3 setup.py install
    • 使用前,还需要创建一个 gpio 组,把你的当前的账号加到这个组,并赋予使用权限
      sudo groupadd -f -r gpio
      sudo usermod -a -G gpio user_name

      注意:user_name是你使用的用户名,比如说waveshare

    • 将99-gpio.rules文件复制到rules.d目录
      sudo cp /opt/nvidia/jetson-gpio/lib/python/Jetson/GPIO/99-gpio.rules /etc/udev/rules.d/
    • 为了使新规则生效,您需要通过运行以下命令重新引导或重新加载udev规则
      sudo udevadm control --reload-rules && sudo udevadm trigger
    • 配置完成后,我们就可以使用里面的例程了,例如simple_input.py可以读取引脚的状态
      cd /opt/nvidia/jetson-gpio/samples/
      sudo python3 simple_input.py

      Jetson-gpio.png

    IIC

    1. 首先安装I2Ctool,终端输入:
      sudo apt-get update
      sudo apt-get install -y i2c-tools
      sudo apt-get install -y python3-smbus
    2. 检查安装情况,终端输入:
      apt-cache policy i2c-tools

      输出如下即为安装成功

      i2c-tools:
      已安装:4.0-2
      候选: 4.0-2
      版本列表:
      *** 4.0-2 500
      500 http://ports.ubuntu.com/ubuntu-ports bionic/universe arm64 Packages
      100 /var/lib/dpkg/status

    i2cdetect

    • 查询i2c设备:
       sudo i2cdetect -y -r -a 0

      Jetson-i2c0.png

      • 参数: -y是无视交互问题直接执行,-r是SMBus read byte命令,-a是所有地址,0是指SMBus 0。
    • 扫描寄存器数据:
      sudo i2cdump -y 0 0x68


    • 寄存器数据写入:
      sudo i2cset -y 0 0x68 0x90 0x55
      • 参数:
        参数 含义
        0 代表I2C设备号
        0x68 代表I2C设备地址
        0x90 代表寄存器地址
        0x55 代表向寄存器写入的数据
    • 寄存器数据读出:
      sudo i2cget -y 0 0x68 0x90
      • 参数:
        参数 含义
        0 代表I2C设备号
        0x68 代表I2C设备地址
        0x90 代表寄存器地址

    SPI

    官方B01套件请直接参考打开SPI.
    Jetson Nano B01 带emmc模组版本,也就是国产套件,无法通过jetson-io.py来直接配置40PIN引脚。这里提供直接修改设备树文件的方式来开启SPI1. 笔者目前只验证了JetPack4.6.2, 本次操作需要重装系统,请用户谨慎操作。

    硬件准备

    1. Ubuntu电脑主机或者虚拟机
    2. Jetson Nano 主板
    3. Micro USB数据线

    安装必要的函数库

    sudo apt-get install minicom 
    sudo apt-get install python-pip nano
    sudo pip install pyserial
    sudo pip install spidev==3.1
    

    软件设置 (Host PC)

    需要在系统资源上修改设备树文件,如果你之前用SDK Manager安装过系统镜像,可以直接在上面修改。 如果没有的话,请参考以下资源下载部分先进行操作,以下资源包是Jetpack4.6.2版本的,如果你需要别的版本资源包下载,请参考FAQ里的资源包下载方法

    资源下载

    1. 在ubuntu电脑新建一个文件夹:
      sudo mkdir sources_nano
      cd  sources_nano
    2. 下载以下两个资源包:
      https://developer.nvidia.com/embedded/l4t/r32_release_v7.2/t210/jetson-210_linux_r32.7.2_aarch64.tbz2
      https://developer.nvidia.com/embedded/l4t/r32_release_v7.2/t210/tegra_linux_sample-root-filesystem_r32.7.2_aarch64.tbz2
    3. 将资源包移到文件夹,并解压(实际操作的时候,请尽量用tag按键自动补齐指令)
      sudo mv ~/Downloads/Jetson-210_Linux_R32.7.2_aarch64.tbz2 ~/sources_nano/
      sudo mv ~/Downloads/Tegra_Linux_Sample-Root-Filesystem-R32.7.2_aarch64.tbz2 ~/sources_nano/
    4. 解压资源
      tar -xjf Jetson-210_Linux_R32.7.2_aarch64.tbz2
      cd Linux_for_Tegra/rootfs/
      tar -xjf ../../Tegra_Linux_Sample-Root-Filesystem-R32.7.2_aarch64.tbz2 
      cd ../
      sudo ./apply_binaries.sh  (若出现报错按照系统提示操作,然后再次输入该行命令)

    修改设备树

    1. 安装dtc工具
      sudo apt-get install -y device-tree-compiler
    2. 反编译出dts文件
      cd kernel/dtb
      sudo dtc -I dtb -O dts -o tegra210-p3448-0002-p3449-0000-b00.dts tegra210-p3448-0002-p3449-0000-b00.dtb
    3. 修改dts文件
      sudo cp tegra210-p3448-0002-p3449-0000-b00.dts tegra210-p3448-0002-p3449-0000-b00-bak.dts
      sudo gedit tegra210-p3448-0002-p3449-0000-b00.dts

      找到spi@7000d400{}部分
      Config1-1.jpg
      在其中的spi@0结构和spi@1结构分别添加语句 status = "okay" ;
      Config1-2.jpg
      找到spi1的引脚设置,将其中的nvidia, function 改为spi1, nvidia,tristate改为0x0, nvidia,enable-input改为0x1. 如图, 五个引脚都要操作。
      Config1-3.jpg

    4. Ctrl+S保存文件,并重新编译为dtb. 注意,如果你还需要修改SD卡等操作,请一起操作。主要不要修改错位置,否则容易导致系统无法正常启动。
      sudo dtc -I dts -O dtb -o tegra210-p3448-0002-p3449-0000-b00.dtb tegra210-p3448-0002-p3449-0000-b00.dts

    重新烧录系统

      将nano设置为recovery烧录模式,接入ubuntu电脑。注意,这里不支持只更新dtb分区,因此需要重新烧录整个系统,烧录系统后需要重新做开机配置,因此,请提前将HDMI屏幕和键盘连接到nano上。
      cd ../../
      sudo ./flash.sh jetson-nano-emmc mmcblk0p1

    测试SPI

    1. 系统烧录成功后,完成开机配置,nano自动重启
      加载spidev:
      sudo modprobe spidev
      git clone https://github.com/rm-hull/spidev-test
      cd spidev-test/
      gcc spidev_test.c -o spidev_test
    2. 用一根排线将nano 40PIN的19和21号引脚短接,运行程序测试:
      ./spidev_test -v -D /dev/spidev0.0 -p "Test"

      如果中断打印信息RX和TX可以正常的发送和接受信息即可。
      Config1-4.jpg

    官方B01套件打开SPI

      在如下文件中添加:
      sudo nano /etc/modules-load.d/modules.conf
      

      添加一行

      spidev
      

      按ctrl+x 然后按Y,回车保存退出,然后打开硬件SPI:

      sudo /opt/nvidia/jetson-io/jetson-io.py
      

      如下图所示所示
      选择配置40PIN管脚
      RS485-CAN-for-JetsonNano wiki1.png
      键盘下选,配置管脚
      RS485-CAN-for-JetsonNano wiki2.png
      键盘下选,移动到SPI1,并回车确定,有*号出现
      RS485-CAN-for-JetsonNano wiki3.png
      键盘下选,保存并选择重启。
      RS485-CAN-for-JetsonNano wiki4.png
      Jetson-io.png
      重启后,ls /dev/spidev*即可看到设备号
      Pin.png
      测试SPI

资料

学习资料

微雪课堂

Jetson Nano系列教程
教程名2
  • 列表2
教程名3
  • 列表3
教程名4
  • 列表4
教程名5
  • 列表5
教程名6
  • 列表6

NVIDIA官方资料

软件

3D图纸

JETSON-NANO-DEV-KIT-3D

FAQ


Xavier NX的散热器使用的是PWM可调速风扇,在系统中设置了阈值,只有在达到一定温度才会运转。如果你想要手动让风扇运转,可以手动设置风扇#FAN


该扩容方法是针对SD卡或者U盘空间足够,但是镜像烧录后分配的空间小于实际存储设备的空间的。可以通过扩容脚本将文件系统扩容到完整的存储空间大小。

打开终端,输入以下指令:

cd /usr/lib/nvidia/resizefs/
sudo chmod 777 nvresizefs.sh
sudo ./nvresizefs.sh
sudo reboot


进入英伟达官网,点击右上角的搜索输入jetpack,按下回车搜索,进入后查找自己下载的Jetpack对应版本,如下:

版本关系水印.png
点击进入即可查看对应版本关系。


由于分区问题,烧写了Jetson Nano的镜像的TF卡在Windows电脑上无法正常识别出盘符,如果需要重新做格式化,在widnows的搜索栏中,搜索磁盘管理并打开磁盘管理界面。找到TF卡所在的移动盘(注意不要认错成其他的盘),右键 选择删除卷,然后新建卷,默认格式化。在默认格式化之后,会重新识别出TF的盘符。此时的TF卡空间内存不对,注意需要用格式化软件再重新对新的盘符做快速格式化。格式化之后,TF卡如果内存空间正常,就可以正常重新烧写新的镜像了。


首先进入英伟达官网,点击右上角搜索,输入你需要下载的Jetpack版本,比如jetpack4.6.1,然后回车,进入以下界面

Jetpack4.6.1-sample.png
点击进入,下拉找到KEY FEATURES IN JETPACK,点击L4T 32.7.1,如下图
L4T-sample.png
进入后找到32.7.1 Driver Details,然后找到Jetson Nano的一列,下载 L4T Driver Package (BSP)和Sample Root Filesystem文件。
Download sources-sample.png


技术支持


联系人:张工
微信:扫下方二维码添加
QRCode SiminZhang.png

说明:进行售后服务前,请准备好客户信息(定货单位、定货人等),以供验证