ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

树莓派摄像头在Jetson Orin Nano上的适配指南:从物理层到驱动

树莓派摄像头在Jetson Orin Nano上的适配指南:从物理层到驱动 1. 从一次翻车现场说起为什么我要把树莓派摄像头插到Orin Nano上手里同时有Jetson Orin Nano和树莓派的人大概率都动过一个念头树莓派那堆便宜好用的CSI摄像头模块能不能直接插到Orin Nano上跑毕竟树莓派官方的Camera Module V2IMX219才一百多块而Jetson生态里标着官方兼容的摄像头动辄四五百起步。这个价差摆在那里不试试心里痒。我就是这么想的。手头正好有一块Orin Nano 8GB开发者套件还有几个树莓派4B时代留下来的OV5647和IMX219模块线材也是现成的15pin FPC排线。理论上两边都是MIPI CSI-2接口物理针脚数一样插上去应该能亮。结果第一次上电dmesg里干干净净/dev/video*一个都没冒出来v4l2-ctl --list-devices返回空列表。摄像头模块摸上去微微发热说明供电是通的但I2C通信根本没建立起来。这个现象其实很典型。MIPI CSI-2只是定义了高速数据链路层和物理层的传输协议它管的是数据怎么传但不管设备怎么被识别。摄像头能不能被系统认出来取决于三个层面的匹配物理连接排线针脚定义和方向、控制通道I2C地址和上电时序、驱动适配设备树里的sensor节点配置。树莓派和Jetson在这三层上都有差异只是差异大小不同。这篇文章就是把我踩过的坑、验证过的方案、以及最终跑通的完整配置流程整理出来。适合手里有Orin Nano又不想花大价钱买官方摄像头的人也适合做树莓派毕设想升级到Jetson平台跑轻量视觉模型的同学。核心结论先放这里OV5647基本没戏IMX219可以跑通但需要改设备树IMX477HQ Camera成功率最高。下面逐层拆解。2. 物理层先过关15pin排线的针脚陷阱与方向判断很多人以为排线插上就行实际上这是第一个大坑。树莓派和Jetson Orin Nano的CSI接口虽然都是15pin FPC但针脚定义和排线方向要求并不完全一致。2.1 两边接口的物理差异树莓派4B/5的CSI接口是标准的15pin、1.0mm间距FPC座针脚1在靠近板边的一侧排线金手指朝向板外也就是常说的金手指朝外。Orin Nano开发者套件的CSI接口同样是15pin、1.0mm间距但座子的针脚1位置和树莓派相反排线需要金手指朝向PCB板内侧插入。我第一次插的时候按树莓派的习惯金手指朝外结果就是供电针脚和信号针脚错位摄像头模块发热但完全不工作。更危险的是如果错位刚好把3.3V怼到数据线上有可能烧掉sensor或者Jetson端的CSI控制器。所以插之前一定用万用表蜂鸣档确认一下排线一端的针脚1对应另一端的针脚1不要想当然。对比项树莓派4B/5 CSIJetson Orin Nano CSI针脚数15pin15pin间距1.0mm1.0mm针脚1位置靠近板边靠近板内排线金手指方向朝板外朝板内供电针脚3.3V3.3V时钟/数据对1对CLK 2对DATA1对CLK 2对DATA2.2 排线长度对信号完整性的影响MIPI CSI-2的差分信号速率很高IMX219在1080p30fps下每lane速率大约在450Mbps左右四lane配置下总带宽接近2Gbps。这个速率下排线长度超过15cm就容易出现误码表现为图像花屏、丢帧、或者干脆枚举失败。树莓派原装排线一般是15cm和30cm两种规格。30cm那根在树莓派上能用是因为树莓派的CSI控制器驱动能力调得比较激进。但换到Orin Nano上我实测30cm排线在1080p下大概有30%的概率出现间歇性花屏换成15cm排线后问题消失。如果你手头只有长排线建议先降分辨率到720p测试确认链路通了再往上调。提示排线插拔次数有限FPC座子的锁扣很脆弱。插之前先打开锁扣排线金手指用无水酒精棉签擦一下确认没有氧化再插。插好后轻拉一下排线确认锁紧但不要用力过猛。2.3 供电能力的边界树莓派CSI接口的3.3V供电来自板载LDO典型限流在300mA左右。Orin Nano的CSI接口供电能力更强一些但也不是无限。IMX219工作电流大约在150mA到200mA之间OV5647稍低IMX477因为传感器更大峰值能到250mA以上。如果你同时接多个摄像头或者用了带红外补光的模块供电就可能不够。表现是摄像头枚举成功但一采集就掉线。这种情况需要外接供电或者用带供电的CSI扩展板。我试过用Orin Nano同时接两个IMX219第二个摄像头在启动时能识别但跑几分钟后就会因为电流不足而断开后来加了一块带外部供电的CSI HAT才稳定。3. 控制通道的暗礁I2C地址、上电时序与时钟配置物理层通了之后下一个关卡是I2C控制通道。摄像头模块除了MIPI数据线还有一组I2C线用于配置寄存器。Jetson和树莓派在这块的差异比物理层更隐蔽也更难排查。3.1 I2C地址冲突与总线编号IMX219的I2C地址是0x107位地址OV5647是0x36IMX477是0x1A。这些地址在树莓派和Jetson上是一样的因为地址由sensor本身决定跟主控无关。问题出在总线编号和复用关系上。树莓派4B的CSI接口对应I2C总线编号是10在较新内核里而Orin Nano的CSI接口对应的是I2C总线编号2或9具体取决于你用的是哪个CSI座子。Orin Nano开发者套件有两个CSI座CSI0对应i2c3180000总线号2CSI1对应i2c3190000总线号9。排查的时候先用i2cdetect扫一遍# 在Orin Nano上扫描CSI0对应的I2C总线 sudo i2cdetect -y -r 2如果地址0x10出现说明sensor的I2C通信正常。如果全是--那要么是排线问题要么是sensor没上电要么是设备树里没使能对应的I2C控制器。我遇到过一种情况i2cdetect能看到0x10但驱动加载后/dev/video0不出现。这通常是设备树里sensor节点的reg属性写错了或者status还是disabled。Jetson的设备树和树莓派的DT overlay机制不一样Orin Nano用的是完整的device tree blob改起来更麻烦。3.2 上电时序与reset/pwdn引脚树莓派摄像头模块上通常有两个控制引脚RESET或XCLR和PWDN。树莓派的驱动会在初始化时拉高/拉低这两个引脚来完成sensor复位。但Jetson的默认设备树里这两个引脚可能没有正确映射到GPIO。IMX219在树莓派上的典型上电时序是先给3.3V供电然后拉低PWDN拉高RESET保持至少1ms再拉低RESET最后通过I2C配置寄存器。如果RESET引脚一直悬空或者电平不对sensor就处于复位状态I2C也不会响应。Orin Nano的设备树里CSI接口的GPIO映射需要手动配置。在tegra234-p3767-0000-p3768-0000-a0.dts里你要找到对应的cam_i2c节点和gpio节点确认reset-gpios和pwdn-gpios属性指向正确的GPIO编号。这个编号在Jetson的pinmux表里查不能照搬树莓派的BCM编号。注意Jetson的GPIO编号体系和树莓派完全不同。树莓派用BCM编号比如GPIO 17Jetson用Linux全局GPIO编号比如348。直接照搬树莓派的配置必错。3.3 时钟源INCK的差异IMX219需要一个24MHz的外部时钟输入INCK。树莓派CSI接口上有一路24MHz时钟输出直接供给sensor。Orin Nano的CSI接口同样有时钟输出但默认频率和使能状态可能不同。在Orin Nano的设备树里时钟源由nvidia,csi-clk或者clock-names属性控制。如果这个时钟没使能sensor的I2C虽然能通因为I2C不依赖INCK但一旦开始采集就会失败因为sensor内部PLL锁不住。我踩过的坑是i2cdetect能看到0x10v4l2-ctl --list-devices也能看到video0但v4l2-ctl --stream-mmap一跑就报VIDIOC_STREAMON: Bad file descriptor。查了半天发现是设备树里clock-frequency写成了24000000但assigned-clock-rates没配导致时钟实际输出是默认的6MHzsensor PLL配置失败。4. 驱动与设备树让IMX219在Orin Nano上真正出图物理层和I2C都通了之后最后一步是驱动适配。Jetson的L4TLinux for Tegra内核里已经包含了IMX219的驱动但默认配置是针对官方摄像头模块的树莓派模块需要改设备树。4.1 确认内核版本与驱动模块Orin Nano出厂一般带L4T 35.x或36.x。先确认版本cat /etc/nv_tegra_release # 输出类似R35 (release), REVISION: 4.1, GCID: 12345678IMX219的驱动在drivers/media/i2c/imx219.c编译成imx219.ko。检查是否已加载lsmod | grep imx219 # 如果没有输出手动加载 sudo modprobe imx219如果modprobe报错说找不到模块说明内核编译时没包含这个驱动需要重新编译内核或者用NVIDIA提供的jetson-io工具配置。4.2 用jetson-io配置CSI接口NVIDIA提供了一个jetson-io.py工具可以图形化配置40pin header和CSI接口。但注意这个工具主要针对官方摄像头模块树莓派模块的pinmux可能不在预设列表里。sudo /opt/nvidia/jetson-io/jetson-io.py在菜单里选择Configure Jetson 24pin CSI Connector然后选对应的sensor。如果列表里没有IMX219就选Custom手动配置。配置完成后会生成一个DT overlay重启后生效。但实测下来jetson-io对树莓派IMX219的支持并不完整。它会把I2C和GPIO配好但clock-frequency和lane配置可能还是默认值。所以更可靠的方式是直接改设备树源文件。4.3 手动修改设备树的关键节点Orin Nano的设备树源文件在hardware/nvidia/platform/t23x/p3768/kernel-dts/目录下。你需要改的是tegra234-p3767-0000-p3768-0000-a0.dts里关于cam_i2c和imx219的部分。关键修改点/* I2C控制器使能 */ i2c3180000 { status okay; clock-frequency 400000; imx219_cam0: imx21910 { compatible sony,imx219; reg 0x10; status okay; /* 时钟配置 */ clocks bpmp TEGRA234_CLK_EXTPERIPH1; clock-names extperiph1; clock-frequency 24000000; assigned-clocks bpmp TEGRA234_CLK_EXTPERIPH1; assigned-clock-rates 24000000; /* GPIO配置编号需查pinmux表 */ reset-gpios gpio TEGRA234_MAIN_GPIO(H, 3) GPIO_ACTIVE_HIGH; pwdn-gpios gpio TEGRA234_MAIN_GPIO(H, 4) GPIO_ACTIVE_HIGH; /* MIPI lane配置 */ port { imx219_out0: endpoint { remote-endpoint csi_in0; >cd /usr/src/linux-headers-$(uname -r) sudo make dtbs sudo cp arch/arm64/boot/dts/nvidia/*.dtb /boot/ sudo reboot4.4 验证出图与常见报错处理重启后检查# 确认video设备出现 ls /dev/video* # 查看支持的格式 v4l2-ctl -d /dev/video0 --list-formats-ext # 抓一帧测试 v4l2-ctl -d /dev/video0 --set-fmt-videowidth1920,height1080,pixelformatRG10 --stream-mmap --stream-count1 --stream-totest.raw如果--list-formats-ext返回空说明驱动加载了但sensor没初始化成功。查dmesg | grep imx219常见错误和对应原因报错信息原因解决imx219 2-0010: failed to read chip idI2C通信失败检查排线、I2C地址、供电imx219 2-0010: Error writing reg上电时序不对检查reset/pwdn GPIOimx219: probe failed设备树节点不匹配检查compatible和regVIDIOC_STREAMON: Bad file descriptor时钟或lane配置错误检查clock-frequency和data-lanes我遇到最诡异的一次是failed to read chip id但i2cdetect能看到0x10。后来发现是设备树里reg 0x10写成了reg 0x10 0x00多了一个地址长度导致驱动解析出错。这种细节问题查起来很费时间建议改设备树时逐行对照官方示例。5. 实测对比OV5647、IMX219、IMX477谁能在Orin Nano上跑通不是所有树莓派摄像头都能在Orin Nano上跑。我手头三个模块都试了一遍结果差异很大。5.1 OV5647基本没戏OV5647是树莓派最早的Camera Module V1用的sensor500万像素I2C地址0x36。Jetson的L4T内核里没有OV5647的驱动/lib/modules/$(uname -r)/kernel/drivers/media/i2c/下找不到ov5647.ko。理论上可以自己移植驱动但OV5647的寄存器配置和树莓派深度绑定移植工作量不小。而且OV5647只支持两lane MIPI带宽有限1080p30fps已经是极限。在Orin Nano上跑这个性价比太低不建议折腾。5.2 IMX219能跑通需要改设备树IMX219是树莓派Camera Module V2用的sensor800万像素I2C地址0x10。Jetson L4T内核自带imx219.ko这是最大的优势。实测在Orin Nano上改完设备树后1080p30fps可以稳定跑CPU占用率在5%以下因为MIPI数据直接进ISP不占CPU。4K15fps也能跑但需要四lane配置而且排线质量要够好。色彩方面IMX219在Jetson上的默认ISP调校和树莓派不同直出画面偏绿需要手动调白平衡。如果你用GStreamer pipeline可以加white-balance-mode参数。5.3 IMX477成功率最高但价格也最高IMX477是树莓派HQ Camera用的sensor1200万像素I2C地址0x1A。Jetson L4T内核同样自带驱动。IMX477在Orin Nano上的兼容性最好因为它的上电时序和Jetson官方IMX477模块基本一致设备树改动最小。1080p60fps和4K30fps都能跑画质明显好于IMX219。但IMX477模块价格在300到400之间比IMX219贵一倍多。如果你只是做轻量视觉任务比如跑个YOLOv5-tiny做目标检测IMX219够用了。如果要做高质量图像采集或者对低照度有要求IMX477值得上。模块I2C地址Jetson驱动设备树改动1080p帧率4K支持价格区间OV56470x36无需移植30fps不支持50-80IMX2190x10自带中等30fps15fps100-150IMX4770x1A自带较小60fps30fps300-4005.4 一个容易被忽略的点CSI lane数量与带宽Orin Nano的CSI控制器支持最多四lane。IMX219和IMX477都支持两lane和四lane模式。两lane下1080p30fps没问题但4K就需要四lane。树莓派原装排线是15pin只引出两laneCLK一对DATA两对。如果你要跑四lane需要换22pin转15pin的转接板或者直接用Jetson官方的22pin排线。这个硬件限制很多人没注意到买了四lane摄像头却发现排线只有两lane带宽上不去。6. 跑通之后用GStreamer和OpenCV验证图像链路摄像头出图只是第一步实际项目里还要把图像喂给算法。Orin Nano上常用的两条路GStreamer pipeline和OpenCV。6.1 GStreamer pipeline配置Jetson的L4T自带GStreamer和NVIDIA的插件nvarguscamerasrc。但注意nvarguscamerasrc只支持通过Argus API的摄像头而Argus需要sensor驱动注册到NVIDIA的ISP框架里。IMX219和IMX477在L4T里已经注册了所以可以用。# 预览1080p gst-launch-1.0 nvarguscamerasrc sensor-id0 ! \ video/x-raw(memory:NVMM),width1920,height1080,framerate30/1 ! \ nvvidconv ! nv3dsink # 保存一帧 gst-launch-1.0 nvarguscamerasrc sensor-id0 num-buffers1 ! \ video/x-raw(memory:NVMM),width1920,height1080 ! \ nvvidconv ! video/x-raw,formatBGRx ! \ jpegenc ! filesink locationframe.jpg如果nvarguscamerasrc报Failed to create CaptureSession说明sensor没注册到Argus。这时候只能用V4L2路径gst-launch-1.0 v4l2src device/dev/video0 ! \ video/x-raw,width1920,height1080,formatRG10 ! \ videoconvert ! nv3dsinkV4L2路径不经过ISP画质会差一些但兼容性更好。6.2 OpenCV读取CSI摄像头OpenCV默认用V4L2后端可以直接读/dev/video0import cv2 cap cv2.VideoCapture(0, cv2.CAP_V4L2) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080) cap.set(cv2.CAP_PROP_FPS, 30) while True: ret, frame cap.read() if not ret: print(Frame grab failed) break cv2.imshow(CSI, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()但这样读出来的是RAW10格式OpenCV不一定能正确解析。更稳的方式是用GStreamer pipeline喂给OpenCVpipeline ( nvarguscamerasrc sensor-id0 ! video/x-raw(memory:NVMM),width1920,height1080,framerate30/1 ! nvvidconv ! video/x-raw,formatBGRx ! videoconvert ! video/x-raw,formatBGR ! appsink ) cap cv2.VideoCapture(pipeline, cv2.CAP_GSTREAMER)这种方式走ISP色彩和曝光都是调好的直接能用于后续算法。6.3 延迟与帧率实测在Orin Nano 8GB上IMX219 1080p30fps通过GStreamer到OpenCV的端到端延迟大约在80到120ms。如果开nvvidconv做格式转换延迟会增加20ms左右。跑YOLOv5-tiny做推理整体延迟在150ms上下做实时目标检测够用。如果发现帧率上不去先查sudo tegrastats看CPU和GPU占用。CSI采集本身不占CPU但如果GStreamer pipeline里有videoconvert这种软件转换就会吃CPU。尽量用nvvidconv做硬件转换。7. 几个让我折腾最久的坑与最终解法最后分享几个实际踩过的坑都是查文档查不到、只能自己试出来的。第一个坑设备树改了但没生效。Orin Nano的启动流程会从多个位置加载DTB/boot/dtb/下的文件可能不是实际使用的那个。用sudo fdtdump /proc/device-tree确认当前生效的设备树改完之后一定要确认/boot/extlinux/extlinux.conf里的FDT路径指向你改的那个文件。第二个坑I2C总线号在重启后变了。Orin Nano的I2C总线编号有时会因为设备树加载顺序变化而改变。写脚本的时候不要硬编码总线号用i2cdetect -l动态获取。第三个坑摄像头模块的地线没接好。有些第三方IMX219模块的FPC排线地线针脚定义和官方不一样插上后I2C能通但图像有横纹。换一根官方排线就好了。这个坑最隐蔽因为I2C通了会让人以为硬件没问题。第四个坑同时开两个摄像头时带宽不够。Orin Nano的CSI控制器总带宽有限两个1080p30fps同时跑会丢帧。降到720p或者错开采集时间可以解决。提示改设备树之前先备份原始DTBsudo cp /boot/dtb/*.dtb /boot/dtb/backup/。改坏了还能恢复不然只能重新刷机。这套方案我在Orin Nano 8GB L4T 35.4.1上验证过IMX219和IMX477都能稳定出图。如果你用的是Orin Nano 4GB版本内存小一些但CSI部分是一样的配置通用。树莓派5的CSI接口和4B基本一致但树莓派5的PCIe接口和Orin Nano的M.2接口不兼容别想着把树莓派的PCIe设备直接插到Orin Nano上那个物理接口都不一样。
返回列表