1. 拿到 Jetson Nano 4GB B01 之后,先把这几件事搞明白
Jetson Nano 这块板子在边缘计算入门这一档里,到现在依然是个绕不开的选择。我手上这台是 4GB B01 版本,472 GFLOPS 的 FP16 算力、128 核 Maxwell GPU、4GB LPDDR4 内存,跑 SSD-MobileNet 这类轻量目标检测模型完全够用,用来做视觉入门、机器人小车、课堂实验都很合适。但它的"入门门槛"其实不在写代码,而在前面那一堆看起来简单、实际上处处是坑的准备工作:镜像版本选错、SD 卡槽找不到、供电不够导致随机重启、编译到一半内存爆掉——这些我都踩过。
这篇东西我打算按自己实际操作的顺序捋一遍:从开箱确认硬件、烧录系统、首次开机初始化,到编译jetson-inference、跑通官方目标检测(detectNet)和手势识别(gestureNet)两个 Demo,最后是性能调优和踩坑记录。内容偏向"照着做就能复现",适合第一次接触 Jetson Nano 的人,也适合已经装过系统但 Demo 一直没跑起来的同学。整套流程在一台正常的 Nano 4GB 上大约 3 到 4 小时能走完,其中大部分时间是在等下载和编译。
1.1 B01 和 A02、2GB 版到底差在哪
很多人拿到板子第一反应是"我这个是什么版本",因为网上教程五花八门,镜像也分好几种。Jetson Nano 4GB 开发套件历史上出过 A02 和 B01 两个主要修订版,现在市面上能买到的基本都是 B01。
两个版本的核心差异是 MIPI CSI-2 摄像头接口数量:A02 只有一个 CSI 接口,B01 有两个(载板上丝印 CAM0、CAM1),所以 B01 可以同时接两路 CSI 摄像头做双目或者多视角。另外 B01 在电源部分做了些优化,PCB 布局也有调整。核心 SoC、内存、GPU 规格完全一样,所以性能上没有区别。
真正需要区分清楚的是4GB 版和 2GB 版。2GB 版是后来推出的低成本版本,内存砍半,供电主要靠 micro-USB,CSI 接口也只有一个,而且它的系统镜像和 4GB 版不通用。如果你把 4GB 的镜像烧到 2GB 的卡上,或者反过来,最典型的症状就是卡在 NVIDIA logo 那里一动不动。所以下载镜像前,先确认自己板子上印的型号。
1.2 配件清单:少一样都开不了机
Nano 开发套件本身只有一块载板加一个核心 module,其他都得自己配。我建议按下面这个清单准备,缺任何一样都会让你卡在某个环节:
- microSD 卡:官方推荐 32GB UHS-1,但 32GB 装完系统加模型基本就满了,我建议直接上 64GB 或 128GB 的 A1/V30 卡。劣质卡的表现是烧录很慢、启动要两分钟以上、编译时随机报 I/O 错误,别在这上面省几十块钱。
- 电源:5V 4A 的 DC 圆孔电源是首选,配上 J48 跳线帽短接,才能解锁 10W 模式。如果只用 micro-USB 供电,官方限制是 5V 2A,一旦插上 USB 摄像头加无线网卡,很容易触发欠压保护直接重启。
- USB 摄像头或 CSI 摄像头:USB 摄像头最省事,插上就是
/dev/video0;CSI 摄像头延迟更低、占用 CPU 更少,但需要单独买排线,而且 B01 的排线方向和某些第三方摄像头模组可能相反,插反了不烧但不出图。 - HDMI 显示器 + USB 键鼠:首次初始化必须有,除非你走串口方案。
- 散热片和风扇:官方套件通常带一个 5V PWM 风扇,如果没有,务必自己加一个。Nano 满载跑目标检测时,裸板温度十分钟就能上 70℃ 以上,然后开始降频,帧率会掉得很明显。
- 网线或 USB 无线网卡:初始化完成后建议直接接网线,比无线网卡稳定,速度也快得多。
1.3 供电和散热是前期最容易翻车的两个环节
先说供电。Nano 载板上有两个供电入口:micro-USB 口和 DC 圆孔。圆孔旁边有两个针脚,丝印是 J48,用跳线帽短接之后,系统才知道"我应该从圆孔取电"。如果不短接 J48 却插了 DC 电源,板子依然会尝试从 micro-USB 取电,结果就是供电不足、USB 设备识别不稳定。这个跳线帽在官方套件里是附带的,很小,容易丢,丢了可以用杜邦线母头临时顶一下。
再说散热。Jetson Nano 的温度监控点有好几个,CPU、GPU、PLL、PMIC 各有一个。跑 detectNet 的时候,GPU 温度会比 CPU 高,通常也是它的温度先逼近阈值。我的经验是:只要上了风扇,把target_pwm开到 200 左右,满载长时间跑也能稳在 60℃ 上下;如果只有散热片没风扇,五分钟之内就会看到帧率从 20 掉到 12 左右,那就是在降频了。后面第 6 节我会给一个自动控温的脚本,比手动写 PWM 值省心得多。
2. 系统镜像烧录:JetPack 版本选择与 SD 卡处理
系统安装这一步看起来简单,但选错版本是新手最常见的时间黑洞。我先说结论:Jetson Nano 4GB(含 B01)只能用 JetPack 4.6.x 系列,底层是 Ubuntu 18.04 LTS。下面解释为什么,以及具体怎么烧。
2.1 为什么只能说 Ubuntu 18.04 和 JetPack 4.6.x
Jetson Nano 用的是 Tegra X1 系列 SoC,NVIDIA 对它的 L4T(Linux for Tegra)支持停在 32.x 版本,而 L4T 32.x 对应的根文件系统就是 Ubuntu 18.04。JetPack 5.x 开始只支持 Xavier、Orin 这一代,Nano 不在支持列表里。所以你在网上看到"Jetson 装 Ubuntu 22.04"的教程,绝大多数讲的是 Orin Nano 或者 Xavier NX,不要直接套到 Nano 上。
那能不能自己动手把 Nano 升到 20.04 甚至 22.04?技术上能,需要自己编译内核、处理 GPU 驱动的依赖,社区里有人做过,但过程非常折腾,而且大概率会遇到 CUDA 和 OpenCV 的兼容问题。对于"我要跑通官方 Demo"这个目标来说,完全没有必要。接受 Ubuntu 18.04 这个事实,后面能省掉一整天的debug时间。
具体镜像我推荐找JetPack 4.6.1(L4T 32.7.1)或 4.6.4的 SD 卡镜像,文件名形如jetson-nano-jp461-sd-card-image.zip。注意一定要看清楚是 4GB 版还是 2GB 版的镜像,两者的文件名里会有区分。
2.2 镜像下载与烧录完整流程
镜像压缩包大概 6 到 7 GB,解压出来的img文件接近 14 GB。下载完之后按下面步骤操作:
首先校验一下压缩包完整性,如果下载过程中断了,解压会报错,白等半天:
sha256sum jetson-nano-jp461-sd-card-image.zip # 和官方页面给出的哈希值对比然后解压:
unzip jetson-nano-jp461-sd-card-image.zipWindows 用户直接用 BalenaEtcher 就行,图形界面,选镜像、选卡、点 Flash,不需要额外操作。Linux 或 macOS 用户可以用dd,但一定要确认目标设备名,写错盘符会直接毁掉你的系统盘:
lsblk # 先确认 SD 卡是 /dev/sdX 还是 /dev/mmcblkX sudo dd if=sd-blob-b01.img of=/dev/sdX bs=4M status=progress conv=fsync syncconv=fsync这个参数很有用,它保证数据真正落盘再返回,不用手动再敲一次 sync。bs=4M比默认的 512 字节快很多,64GB 的卡大概 8 到 15 分钟能写完。
注意:
dd的of=后面必须是整块设备(比如/dev/sdb),不能带分区号(不能写/dev/sdb1)。写错了会把分区表搞乱,虽然通常还能重新格式化救回来,但没必要冒这个风险。
2.3 拆 module 插 SD 卡:新手最容易卡住的一步
这是我觉得最反直觉的一个设计:Jetson Nano 开发套件的 microSD 卡槽在核心 module 的背面,也就是朝向载板的那一面。也就是说,你必须先把 module 从载板上拆下来,才能插卡。
操作步骤是:先把所有线缆(电源、HDMI、USB、网线)全部拔掉,卸下 module 两端的两颗固定螺丝,然后用双手拇指顶住 module 的边缘,沿着 SODIMM 连接器的方向斜向上轻轻拔出。module 和载板之间是 260 pin 的 SODIMM 接口,插拔手感类似笔记本内存条,需要一点力但绝对不要用蛮力撬。
拔下来翻面,就能看到卡槽。把 microSD 卡金属触点朝下推进去,听到"咔"的一声说明卡住了。然后把 module 装回去,注意方向和金手指对齐,斜着插到底再压平,拧上螺丝。
我见过不少人插好卡装回去之后,上电没反应,最后发现是 module 没插到底,金手指只接触了一半。所以装回去之后,用手轻轻按一下 module 的四个角,确认没有翘起。
3. 首次开机与基础系统配置
卡插好了,接下来就是初始化。这一步的分岔点是:你有没有显示器。
3.1 有显示器 / 没显示器两种初始化路线
有显示器的情况(推荐):接上 HDMI 显示器、USB 键鼠、网线,然后接 DC 电源。第一次开机大概需要 1 到 2 分钟,屏幕上会出现 NVIDIA 的 logo,然后进入 Ubuntu 的 OEM 配置向导。
向导里几个关键选择:语言建议选English,虽然选中文也能用,但部分命令行工具在中文 locale 下会输出乱码,目录名变成"桌面""下载"之后,很多脚本的路径会找不到,后面还得改回来。用户名不要用nvidia(旧版镜像会拒绝创建,因为系统里有同名用户),密码自己设,简单点无所谓,这是局域网内网设备。
最后一步会问你 APP partition size,一定选max,让它把整张卡的空间都用上。如果这里选小了,后面还得用resize2fs手动扩,多一道工序。
没显示器的情况:有两个办法。一是走串口,Nano 载板上有一个 4 针的串口调试口(丝印 J44),用 USB-TTL 模块把 TXD 接 RXD、RXD 接 TXD、GND 接 GND,波特率设 115200 8N1,开机就能看到完整的启动日志和登录提示。二是把 SD 卡插到读卡器上,在电脑上挂载 rootfs 分区,用镜像自带的l4t_create_default_user.sh脚本预置默认账号:
sudo mount /dev/sdX1 /mnt sudo cp /usr/bin/qemu-aarch64-static /mnt/usr/bin/ sudo chroot /mnt /bin/bash # 进入 chroot 后 /l4t_create_default_user.sh -u nvidia -p nvidia -n jetson-nano -a exit sudo umount /mnt这样系统启动后会跳过 OEM 向导,直接用nvidia/nvidia登录。第二种方法需要一定的 Linux 基础,中间任何一步出错都可能让系统起不来,我更推荐第一次装的时候老老实实接显示器。
3.2 换源、扩容 swap、装 jtop
进系统之后先别急着跑 Demo,把基础环境理顺。第一件事是换 apt 源,默认的ports.ubuntu.com在国内下载速度感人,更新一次能等到睡着。
Ubuntu 18.04 ARM64 的源列表在/etc/apt/sources.list,注意一定要用ubuntu-ports路径,不能用 x86 的ubuntu路径:
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak sudo sed -i 's|http://ports.ubuntu.com/ubuntu-ports|https://mirrors.ustc.edu.cn/ubuntu-ports|g' /etc/apt/sources.list sudo apt-get update注意:NVIDIA 自己的 L4T 源在
/etc/apt/sources.list.d/nvidia-l4t-apt-source.list,不要动它。那个源里的包版本和你的 L4T 版本是强绑定的,换成第三方镜像很容易出现依赖冲突,导致 CUDA 组件装不上。
第二件事是扩容 swap。4GB 内存编译jetson-inference的时候非常容易 OOM,因为make -j4会同时起四个编译进程,每个进程峰值能吃到 1GB 以上。默认镜像的 swap 只有 2GB 左右,不够用。扩到 8GB:
sudo swapoff /var/swapfile sudo dd if=/dev/zero of=/var/swapfile bs=1M count=8192 status=progress sudo chmod 600 /var/swapfile sudo mkswap /var/swapfile sudo swapon /var/swapfile free -h # 确认 swap 那一行变成 8G这里用dd而不是fallocate,是因为部分 SD 卡的控制器对 fallocate 预分配的空间处理有问题,写进去的数据可能是坏的,dd一个字节一个字节写最稳妥。顺便把 swappiness 调低一点,让系统优先用物理内存:
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf第三件事是装jetson-stats,也就是jtop,这是个必装工具,能实时看 CPU/GPU 占用、内存、各区域温度、风扇转速、当前电源模式,比htop有用得多:
sudo apt-get install python3-pip sudo -H pip3 install -U jetson-stats sudo systemctl restart jetson_stats.service jtoppip 也可以换成国内源,不然装包的时候会一直转圈:
mkdir -p ~/.pip cat > ~/.pip/pip.conf << 'EOF' [global] index-url = https://pypi.tuna.tsinghua.edu.cn/simple trusted-host = pypi.tuna.tsinghua.edu.cn EOF3.3 Python 环境与依赖安装的取舍
Jetson Nano 上的 Python 包选择有个原则:能用 apt 装的就用 apt,不要用 pip。原因是 aarch64 架构的预编译 wheel 很少,pip install numpy在 Nano 上会现场编译,运气好二十分钟,运气不好直接 OOM。
系统自带 Python 3.6,python3-numpy、python3-opencv、python3-dev这些常用包直接用 apt 装:
sudo apt-get install -y python3-numpy python3-opencv python3-dev python3-pipCUDA 和 cuDNN 是 JetPack 镜像里预装的,不用自己折腾。验证一下:
nvcc --version # 应该显示 CUDA 10.2 ls /usr/lib/aarch64-linux-gnu/ | grep cudnn如果nvcc找不到,可能是环境变量没配,加到~/.bashrc里:
export PATH=/usr/local/cuda/bin:$PATH export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH4. 官方 Demo 一:目标检测跑通全流程
准备工作做完,就可以进入正题了。NVIDIA 官方的jetson-inference项目是跑 Demo 最省事的路径,它把 TensorRT 推理、摄像头采集、OpenGL 显示都封装好了,编译完直接命令行就能用。
4.1 编译 jetson-inference 的正确姿势
先拉代码。用--recursive是因为它依赖几个 submodule,漏了这个参数后面编译会报找不到头文件:
sudo apt-get install -y git cmake libpython3-dev cd ~ git clone --recursive --depth=1 https://github.com/dusty-nv/jetson-inference cd jetson-inference mkdir build && cd build接下来是cmake,这一步有个坑要提前知道:配置阶段会弹出一个基于 dialog 的模型下载界面。它会把所有可用的预训练模型列出来让你勾选,如果全选,总下载量有好几个 GB,网速慢的话能等一小时。我的建议是第一次只勾需要的:
SSD-MobileNet-V2(目标检测,COCO 91 类,必选)ResNet-18(图像分类,顺手勾上)GestureNet(手势识别,5.2 节要用)
用方向键移动、空格勾选、回车确认。如果勾错了想重来,删掉build目录重新cmake一次就行。
然后编译。这里一定要根据内存情况调整并行度:
make -j2 # 4GB 内存建议 -j2 sudo make install sudo ldconfigmake -j2比-j4慢一些,但不会 OOM。如果你已经按 3.2 节把 swap 扩到了 8GB,可以试试-j3,但-j4我不推荐,实测有概率在编译cuda相关文件时被 OOM killer 干掉。
编译时间大概 40 到 90 分钟,取决于 SD 卡速度。期间可以用jtop盯着温度和内存,如果温度持续超过 75℃,把风扇 PWM 调高。
4.2 detectNet 命令详解与参数调优
编译完成后,可执行文件在build/aarch64/bin下。先跑一张静态图片看看能不能出结果:
cd ~/jetson-inference/build/aarch64/bin ./detectnet --network=ssd-mobilenet-v2 /usr/share/backgrounds/gnome/*.jpg output.jpg会生成一张画了检测框的output.jpg。确认能跑通之后,接摄像头:
./detectnet /dev/video0 # USB 摄像头 ./detectnet csi://0 # CSI 摄像头 ./detectnet csi://0 --network=ssd-inception-v2常用参数我列一下,这几个是实际调优时最常改的:
| 参数 | 作用 | 建议值 |
|---|---|---|
--network | 选择模型 | ssd-mobilenet-v2(速度优先)/ssd-inception-v2(精度优先) |
--threshold | 置信度阈值 | 0.4~0.6,太低会满屏误检 |
--overlay | 叠加显示内容 | box,labels,conf或只留box提速 |
--alpha | 叠加层透明度 | 180 左右比较好看清 |
--stats | 打印帧率统计 | 调优时开着 |
调优思路上,--threshold是最值得花时间的参数。默认 0.5,在光线一般的室内场景下,人、杯子、键盘这些常见物体的置信度会在 0.35 到 0.55 之间浮动。把它降到 0.35,检出率上来了,但误检也明显变多;提到 0.7,画面干净但经常漏掉远处的目标。我的经验是按场景定:固定机位、光照稳定用 0.5,移动场景用 0.4。
另外--overlay里如果去掉labels,渲染开销会小一些,帧率能提 1 到 2 FPS,在 Nano 这种 GPU 和显示共用资源的平台上,这个提升不算小。
Python 版本也有,接口一样,只是把可执行文件换成detectnet.py:
./detectnet.py /dev/video0 --network=ssd-mobilenet-v24.3 实测帧率、功耗与温度数据
我在自己的 B01 上做了一轮实测,环境是:10W 模式(nvpmodel -m 0)+jetson_clocks,USB 摄像头 640x360 MJPEG,SSD-MobileNet-v2,输入 300x300,jtop记录数据。结果大致如下:
| 场景 | 平均帧率 | GPU 占用 | 温度 | 整板功耗 |
|---|---|---|---|---|
| 关显示输出,纯推理 | 21~24 FPS | 85%~95% | 62℃ | 约 7.5W |
| 开 HDMI 显示叠加 | 15~18 FPS | 95%+ | 66℃ | 约 8.2W |
| 5W 模式,无风扇 | 8~10 FPS | 99%,降频 | 72℃+ | 约 4.6W |
| 10W 模式,无风扇 | 12~15 FPS | 99%,间歇降频 | 75℃+ | 约 8W |
几个结论值得注意。第一,显示输出会吃掉 5 FPS 左右,因为 Nano 的 GPU 要同时做推理和 OpenGL 渲染,如果只是做后台推理(把结果通过网络推出去),帧率会明显更高。第二,风扇的有无对持续帧率的影响比想象中大,短时间跑看不出差别,超过三分钟就开始分化。第三,5W 模式基本没有实用价值,除非你在做电池供电的移动设备并且能接受 8 FPS。
4.4 目标检测常见报错排查
跑 detectNet 时遇到的错误,我整理了几个高频的:
报segmentation fault或者直接退出:八成是模型没下载完整。检查jetson-inference/data/networks/SSD-MobileNet-V2/目录,应该有一个.onnx和一个.caffemodel之类的文件,大小对不上就删掉重新跑cmake触发下载。
报failed to open /dev/video0:先用ls /dev/video*确认设备号,有些摄像头枚举出来是video1或video2。再看v4l2-ctl --list-devices有没有识别到。如果插的是 CSI 摄像头,确认排线方向和接口编号(CAM0 对应csi://0)。
画面卡住不动、帧率突然掉到 1 FPS:检查 SD 卡是不是写满了,或者 swap 在疯狂读写。jtop里能看到 SD 卡占用率和 swap 使用量。如果 swap 一直在动,说明物理内存不够,考虑换个更小的模型或者关掉一些后台服务。
检测框抖动严重:这不是 bug,是单帧检测的固有特性。SSD 系列不带跟踪,每一帧独立推理,物体稍微动一下框就跳。要平滑得靠后处理加跟踪算法,或者换更稳定的模型。
提示:
jetson-inference还自带了detectnet-snap.py之类的示例脚本,可以把检测结果直接存成图片,做数据集筛选或者效果对比的时候很省事。
5. 官方 Demo 二:手势识别实测
目标检测跑通之后,手势识别是另一个很有意思的官方 Demo。它和 detectNet 最大的区别是:它不是对单张图做分类,而是对一段视频序列做动作判断,所以输入必须是连续的视频流,静态图片喂进去没意义。
5.1 gestureNet 的模型原理和它能识别什么
gestureNet用的是 3D 卷积网络,训练数据来自 20BN-Jester 数据集的一个子集。所谓 3D 卷积,就是在普通卷积的"高、宽"两个维度之外,多加了"时间"这一个维度,卷积核同时在空间和时间上滑动,因此它能捕捉"手在往哪个方向移动"这类动态信息,而不是只看单帧的手势形状。
它能识别的手势是固定的一组,大致包括:
- 向上、向下、向左、向右滑动
- 顺时针、逆时针转手
- 大拇指向上、大拇指向下
- 双手/单指放大、缩小
- 手指敲击、把手拉近、把手推远
- 无手势、其他动作
注意"无手势"和"其他动作"是两个独立的类别,模型会把画面里任何不符合上述动作的东西都归到这两类里。这也是实测时最容易困惑的地方——你随便挥挥手,它可能一直输出"no gesture"。
因为要做时间维度的卷积,模型需要缓存一段帧序列才能出一次结果,所以它的输出延迟明显高于目标检测,而且帧率越低,同一个动作被识别的概率越低,因为采样点变少了。
5.2 运行命令与输入流注意事项
gestureNet是通过imagenet这个工具调用的,因为它本质还是个分类网络:
cd ~/jetson-inference/build/aarch64/bin ./imagenet /dev/video0 --network=gesturenet ./imagenet csi://0 --network=gesturenet实际命令行参数可能会随版本略有差别,跑之前先./imagenet --help看一眼,以你本地版本为准。
实测下来有几个要点必须注意:
第一,手要在画面里待够时间。动作做完之后别急着放下,保持一两秒,模型才有足够的帧来判定。我一开始做"向上滑动",手划一下就放下来,结果一直识别成"no gesture",后来把手停在画面上方等了两秒,才正确输出 "swiping up"。
第二,背景要干净。3D 卷积对背景运动很敏感,如果画面里有人在走动、风扇在转,很容易干扰。找一面素色墙或者纯色桌面对着,识别率会明显提升。
第三,光照要均匀。逆光或者单侧强光会让手的轮廓糊掉,模型区分不了手指动作。室内正常顶灯就够。
第四,帧率要够。手势识别在 Nano 上实测大概 8 到 15 FPS,比目标检测低一截,因为 3D 卷积的计算量更大。如果用 USB 摄像头,建议把摄像头分辨率降到 640x480 并把格式设成 MJPEG,能减轻不少带宽和解码压力:
v4l2-ctl --device=/dev/video0 --set-fmt-video=width=640,height=480,pixelformat=MJPG5.3 实测效果、延迟和适用边界
我在正常室内光线下测了一轮,把每个手势做十次,大致的结果是:向上、向下、向左、向右这四个滑动动作最稳,十次里能对七八次;放大缩小和转手这些动作识别率差一些,大概五成到六成;大拇指上下比较容易和"其他动作"混淆。
延迟方面,从动作结束到屏幕输出正确标签,大概有 0.5 到 1 秒的滞后,这是模型需要攒帧导致的,属于原理层面的限制,不是配置问题。所以它不适合做实时性要求高的交互,比如用它控制小车转向什么的,体验会很差。
它适合的场景是:做演示 Demo、课堂讲解 3D 卷积原理、验证摄像头和推理链路是否正常。真要拿手势做实际交互,更靠谱的路线是用轻量关键点检测(比如手部 21 点检测)加自研的规则判断,或者用 Edge Impulse 这类平台在 PC 上训一个小模型再部署过来,延迟和准确率都会好很多。
6. 让 Nano 跑得更稳:性能与散热调优
Demo 能跑起来只是第一步,长时间稳定运行是另一回事。这一节讲几个实际调优手段。
6.1 nvpmodel 与 jetson_clocks 的组合用法
Jetson Nano 有两个预设的电源模式,用nvpmodel切换:
sudo nvpmodel -q # 查询当前模式 sudo nvpmodel -m 0 # 10W 模式:4 核全开 1.43GHz sudo nvpmodel -m 1 # 5W 模式:2 核 918MHz10W 模式必须配合 DC 5V4A 供电和 J48 跳线短接才能启用,否则切过去之后系统会因为供电不足直接挂掉。
jetson_clocks是另一回事,它不是超频,而是把频率锁在最高档,禁止 DVFS 动态调频:
sudo jetson_clocks # 锁定最高频 sudo jetson_clocks --show # 查看当前频率 sudo jetson_clocks --restore # 恢复默认这两个命令组合起来用效果最好:nvpmodel -m 0解锁硬件上限,jetson_clocks保证推理时频率不会因为短暂的负载波动掉下来。实测在目标检测场景下,这个组合相比默认状态能提升 15% 到 20% 的稳定帧率。
但要注意,jetson_clocks锁频之后功耗和温度都会上升,必须保证散热跟上。如果只有散热片,不要开这个。
6.2 风扇控制与温度监控脚本
官方 PWM 风扇的转速是写在/sys/devices/pwm-fan/target_pwm里的,取值范围 0 到 255:
sudo sh -c 'echo 255 > /sys/devices/pwm-fan/target_pwm' # 全速 sudo sh -c 'echo 0 > /sys/devices/pwm-fan/target_pwm' # 停转手动调太麻烦,我一般直接挂一个后台脚本,按温度自动调速。温度读数的位置在/sys/devices/virtual/thermal/thermal_zoneN/temp,几个 zone 对应不同区域,数值单位是毫摄氏度,需要除以 1000:
#!/bin/bash # fan_ctl.sh - 按最高温度自动调节风扇转速 while true; do max_temp=0 for zone in /sys/devices/virtual/thermal/thermal_zone*/temp; do t=$(cat $zone) [ "$t" -gt "$max_temp" ] && max_temp=$t done temp=$((max_temp / 1000)) if [ $temp -lt 45 ]; then pwm=0 elif [ $temp -lt 55 ]; then pwm=100 elif [ $temp -lt 65 ]; then pwm=180 else pwm=255 fi echo $pwm | sudo tee /sys/devices/pwm-fan/target_pwm > /dev/null sleep 5 done这个脚本每 5 秒检查一次所有温区,取最高值来决定转速。阈值我设的是 45℃ 以下停转、75℃ 以上全速,实际跑下来温度基本稳在 55 到 65 之间,风扇也不会一直狂转吵人。
注意:不同版本的 BSP 里
pwm-fan的路径可能略有差异,如果写入报"No such file",用find /sys -name 'target_pwm'找一下实际路径。
6.3 后续可扩展方向
官方的这两个 Demo 跑通之后,接下来的路线大致有三条。
一是换更实用的检测模型。jetson-inference自带的 SSD 系列精度一般,如果想做具体场景(比如行人、车辆、安全帽),可以自己用 YOLOv5 训练,然后导出 ONNX,在 Nano 上用 TensorRT 转成 engine 跑。YOLOv5s 在 Nano 4GB 上用 FP16,输入 640,实测大概 8 到 12 FPS,能做到实用。关键是 PyTorch for Jetson 的 wheel 要从 NVIDIA 官方渠道装,不要用 pip 默认源里的。
二是上 DeepStream。如果你要做多路视频流的解码、推理、编码推流,自己写 GStreamer 管道太累,DeepStream 把这些封装好了。不过它在 Nano 上能跑的版本比较老,多路并发能力有限,适合做两路以内的场景。
三是考虑升级硬件。如果项目真的卡在算力上,Orin Nano 是个很自然的升级路径,同样的软件栈、同样的开发方式,算力提升是数量级的。Jetson Nano 的定位始终是学习和原型验证,别难为它做工业级的多路实时推理。
7. 踩坑记录与常见问题速查
7.1 问题速查表
把前面提到的和没提到但经常遇到的问题汇总一下,方便对着排查:
| 现象 | 大概率原因 | 处理方式 |
|---|---|---|
| 上电无任何输出 | module 没插到底 / SD 卡没插好 | 重新拔插 module,确认卡到位 |
| 卡在 NVIDIA logo 不动 | 镜像版本与板子不匹配 | 重新烧录对应 4GB 版镜像 |
| 开机反复重启 | 供电不足 | 换 DC 5V4A,短接 J48 |
| 首次开机进不了向导 | HDMI 分辨率不匹配 | 换显示器或换线,尝试 1080p |
apt update大量 404 | 源地址不对 | 恢复ports.ubuntu.com或用正确的ubuntu-ports路径 |
| 编译到一半进程被杀 | 内存不足 | 扩 swap 到 8GB,make -j2 |
| 模型下载卡住 | 网络问题 | 删掉build目录重新cmake触发下载 |
| 摄像头打不开 | 设备号不对或供电不足 | ls /dev/video*,接外供电 Hub |
| 帧率突然掉一半 | GPU 降频 | jtop看温度,检查风扇 |
| 风扇一直不转 | 排线松动或 PWM 为 0 | 检查排线,手动写target_pwm |
| pip 装包卡死 | 正在现场编译 aarch64 包 | 改用 apt 版本,或换国内 pip 源 |
| 系统时间不对 | 无 RTC 电池 | 接网后同步 NTP,或手动date -s |
7.2 几条我实测有效的经验
第一个经验是把整个系统的镜像备份下来。所有环境配好、Demo 跑通之后,用dd把整张 SD 卡读出来存成.img,以后不管怎么折腾坏了,十几分钟就能恢复到可用状态,比重新装一遍省太多时间。
sudo dd if=/dev/mmcblk0 of=~/nano_backup.img bs=4M status=progress第二个经验是不要在 SD 卡上跑需要频繁读写磁盘的任务。SD 卡寿命有限,日志狂写、数据集频繁读取都会加速磨损。如果项目要长期跑,考虑用 USB 3.0 移动硬盘或者网络存储来放数据和日志。
第三个经验是串口调试口是救命的。当系统因为配置错误起不来、SSH 也连不上时,串口是唯一能看到内核日志的通道。花二十块钱买个 USB-TTL 模块备用,不会亏。
最后一个经验是先确认硬件,再折腾软件。我见过太多人把时间花在改配置、换镜像上,最后发现是电源不够或者散热不行。拿到板子第一件事,拍照记录型号、确认电源规格、检查跳线帽、把风扇插好,这十分钟能让后面少走很多弯路。