
双目项目刚启动那阵我在板子上同时接了两颗Sensor想着无非就是把单路的配置复制一份改改地址就能跑。结果折腾了整整两天第二路死活不出图串口打印里Sensor在线状态倒是一路正常抓图抓出来的却是全黑或者花屏。后来把海思SDK里的PQTools和Stream工具真正用起来才意识到单路调试和双目调试根本是两码事——前者是调算法效果后者是先解决资源分配和同步问题。这篇文章就把我在实战里怎么用这两个工具加速双目、多Sensor调试的完整思路写出来给正在被海思平台折磨的兄弟们做个参考。1. 单Sensor调试和双目调试本质上是两件事很多从单路项目切到多路项目的人第一反应都是配置复制一份就行。这种思路在硬件链路简单、带宽充裕、Sensor规格一致的情况下确实能跑通但一旦涉及双目结构光、双目测距、RGBIR这种组合事情就完全不一样了。单路调试的核心是把这一路图像调到最好看、最准你只需要关注ISP pipeline里的坏点矫正、去马赛克、3DNR、WDR这些模块的参数怎么配合而多路调试的核心是让每一条链路都能稳定出图并且彼此之间不打架这涉及MIPI lane分配、VI通道绑定、ISP算力共享、内存带宽争用甚至两个Sensor之间曝光时序的硬同步。我建议所有人上手多Sensor项目时先把单Sensor的调试能力彻底吃透。这里说的吃透不是因为ISP调参只对单路有用而是PQTools这类工具的很多操作逻辑在多路场景下依然成立只是作用对象从一个Sensor变成了多个Sensor。1.1 我为什么从单路切到多路时被卡了很久当时项目用的是海思某款带双ISP的SoC硬件上两个Sensor分别接到两路MIPI。刚开始我只是改改Sample里的sensor_cfg把第二路的I2C地址、复位脚、MIPI lane数填进去然后编译烧录结果第二路在VI层就没有数据上来。我一度怀疑是硬件焊接问题拿示波器量了MCLK和复位脚确认波形没问题。后来发现根子在于海思的VI模块对每个通道能承载几路Sensor数据有严格的配置约束并不是你把sensor_cfg里的vi_num改成2就行。Stream工具里查看sensor状态时能清楚看到每一路是否在跑但前提是你得先理解它打印出来的信息和VI绑定之间的关系。1.2 PQTools和Stream工具在整条调试链路中的位置先把工具分工说清楚PQTools负责和图像质量、ISP算法效果相关的一切它能在线读改写ISP的寄存器、抓取RAW图、对比不同参数组合的效果Stream工具负责数据链路、设备状态、上下电、出图验证这些偏系统层的事情。两者配合起来大概是这样一条链路先用Stream确认Sensor在线、在出数据然后用PQTools抓RAW判断数据有没有进到ISP再调整ISP参数看效果最后再回到Stream里去验证多路同时运行的稳定性。这条链路说起来简单真正跑顺的人并不多因为很多人的习惯是闷头在代码里改而不是先拿工具把问题圈定到一个更小的范围内。2. PQTools先把单路ISP的底子打好海思的PQTools是Windows/Mac上的一个图形化工具通过网口或者串口和板端通信可以实时读取ISP寄存器状态、调节gamma、锐化、降噪、色彩等几十个模块参数。它的界面布局是可以配置的左侧一般是一棵调试项树中间是当前帧图像的预览右侧是参数调节面板。你可以把一组参数保存成一个xml文件也可以把当前sensor跑起来时用的所有参数导出。对做双目项目来说最关键的是要建立每个Sensor有一套独立参数的意识这对后续多Sensor调试很重要。2.1 PQTools能干的几类事情我自己常用的PQTools操作大概分四类寄存器级调试直接查看、修改某个ISP模块的寄存器值比如去马赛克模块的边界方向强度、坏点表是否启用。这种调试最细粒度适合定位图像里的异常纹理、错误颜色。抓取RAW图将Sensor原始数据直接从ISP前级导出保存成RAW文件。这一步的价值在于判断图像问题出在Sensor还是出在ISP。如果RAW本身就有坏线、坏点那就是Sensor侧的毛病如果RAW正常但最终图像发绿发紫那就是去马赛克或白平衡的锅。参数组对比调整某一组参数后可以将效果与之前保存的参考状态做同屏对比快速判断参数是往好了调还是往坏了调。在线运行与离线分析在线模式下实时预览效果也可以把抓出来的RAW文件放到PC端做离线分析不占用板端资源适合批量测多组参数。2.2 让我提升效率的常用操作清单如果你是第一次接触PQTools我建议按这个顺序走一遍在Stream工具里把Sensor跑起来并确认在抓取图像PQTools才能看到画面。打开PQTools连接板端。注意连接的IP/端口配置要和板端网络设置一致很多人在这一步就卡住了。先把所有锦上添花的模块关掉——3DNR、锐化、对比度增强、局部亮度补偿都先关掉只保留坏点矫正和去马赛克先把画面基础做扎实。打开RAW抓取功能把当前帧存下来观察Sensor原始数据是否有问题。如果RAW正常再逐步开启2DNR、3DNR、锐化这些模块每开一个就存一组参数方便横向对比。为什么要先关掉增强模块因为图像效果是层层叠加的如果一开始3DNR就开得很强你很难判断画面发糊到底是Sensor的清晰度不够还是降噪强度太大把细节吃掉了。先做减法再做加法这是ISP调试的底层逻辑无论单路多路都适用。2.3 PQTools的样本与在线切换逻辑海思SDK里通常会有几种sensor的PQ模板不同sensor的sensitivity、色彩滤镜、响应曲线完全不同直接套模板大概率效果很差。你在PQTools里把某一组调好的参数保存成样本文件后在代码里一般就是把旧的imetric参数替换成新的。但多Sensor项目里如果两个Sensor型号不同比如一个彩色一个黑白就要给它们分别建立样本不能用一个文件里的一套参数去套两颗Sensor。还有一个容易忽略的细节PQTools在线调参时你动某个参数它立刻生效但它立即生效的是当前ISP的寄存器不一定同步写回到你的配置文件里。如果你没有在PQTools里保存下一次重新加载驱动之前的调整全部丢失。我见过不少人在板子上调了半天效果一拍脑门就断电第二天又得重新调。3. Stream工具看起来只是个抓图工具实际不止Stream工具是海思SDK里的命令行工具功能不花哨但极其重要。它能在系统运行时查询和操作Sensor状态、配置VI通道、切换Sensor分辨率/帧率sensor_mode、抓取视频流帧甚至模拟Sensor上下电。对多Sensor调试来说Stream工具的价值在于不用每次改代码重新编译就能验证各种链路配置的可行性。3.1 Stream的工具定位与常用指令在不同版本的海思SDK里Stream工具的路径和命令参数会有差异但核心逻辑是一致的。我自己常用的几个场景查看当前系统里有多少路Sensor在线每路处于什么状态。动态切换某一路Sensor的分辨率或者帧率验证不同分辨率下ISP的输出是否正常。抓取指定通道的一帧图像保存成文件用于PQTools离线分析。让某一路Sensor下线power down测试另一路是否不受影响。这套操作在单Sensor项目里感受不那么明显但在多Sensor项目里你能用来验证其中一个Sensor突然掉电另一个Sensor的ISP会不会被拖死这种可靠性问题。3.2 多Sensor上下线与VI绑定的细节VIVideo Input是海思SoC里接收Sensor数据的模块。它内部按通道、设备、Pipe来组织数据流。多Sensor时最常见的配置错误就是以为多接几颗Sensor就是多开辟几路VI。实际上VI的能力受限于硬件的跨通道横竖分块、lane复用、虚拟通道VCVirtual Channel等机制。比如两颗Sensor都通过同一个MIPI接口用不同的Virtual Channel区分那么你在VI层看到的第0路和第1路其实是同一个物理接口的两条逻辑流。Stream工具里会区分不同VC号的Device你必须保证Sensor端的VC配置和VI端的VC配置完全对齐否则数据会乱套。还有一种是两颗Sensor各占一路MIPI接口但共用一个VI Pipe。这种情况下Time Slot或者说带宽分配就成了关键。如果你不确认Sensor输出的数据率是否超过VI对外总带宽轻则花屏重则掉帧。用Stream工具把两路都跑起来观察两路的实际帧率和丢帧计数最直观。3.3 抓RAW图配合PQTools离线调参的完整路径在单路调试中在线调参板子连着PQTools一步步调非常直观但多路调试时在线调参有个问题你同时开着两个PQTools窗口操作多个Sensor板端CPU负载和网络带宽都会上升容易干扰实时性。我比较推荐的做法是用Stream工具同时把2路Sensor拉起来确认链路稳定。用Stream分别抓取每路Sensor的一帧RAW图。把RAW文件拷回PC用PQTools离线打开逐路分析问题。在PC上把参数调好后存成最终xml再通过板端升级或加载接口烧回去。这个流程的好处是每一路Sensor都能安静地单独调不必双目同时在线导致互相干扰。调好一路再调另一路最后再把两路同时拉起来做整机验证。多Sensor调试的节奏一定是先单后双、先静后动、先稳定后效果。4. 双目同步调试的关键点时序、带宽、以及ISP资源分配如果只是做双路独立出图多Sensor并不算特别困难按上面说的链路一步步确认就行。但双目项目一般还有硬性要求两个Sensor必须同时曝光、同时出图否则在计算视差或做融合时会出现时间不一致的问题。这一点很多没有做过双目的人第一时间想不到。4.1 同步曝光为什么必须做以及怎么做双目同步曝光的本质是让两颗Sensor在同一个时间窗口内完成曝光。如果左右目各曝各的运动物体的位置在左右图里就会有细微偏差后期无论是做对齐还是做算法都会测量不准确。实现同步的方式在海思平台上一般是用硬件触发信号把两颗Sensor的曝光时序拉齐工作方式是主Sensor输出VSYNC场同步信号或者一帧的trigger信号给到从Sensor的同步输入端从Sensor被配置为跟随外部触发模式而不是自由运行模式。这样从Sensor的输出帧率、曝光起始时刻会跟随主Sensor。在软件配置上海思的Sensor驱动里一般有对应的同步模式寄存器。不同Sensor厂商的实现方式不完全一样需要查阅具体模组的数据手册。我自己有用过支持hardware sync引脚的Sensor直接把引脚连上就能工作。还有一种方案是通过软件在每一帧开始前同时给两个Sensor下发trigger命令这种方式延迟和抖动略大但胜在硬件改动少。用Stream工具验证同步我常用的办法是让场景里放一个高速转动的扇叶或LED闪烁源抓两路的画面观察它们的亮暗变化是否一致。如果两路图像中LED闪烁的相位永远对得上说明同步已经ok如果有一路总是慢半拍或者相位抖动那多半是触发时序或驱动代码有问题。4.2 MIPI虚拟通道与lane分配双目项目中两个Sensor和SoC的连接方式一般有两种一是各自走独立的MIPI接口二是在同一物理接口上通过Virtual Channel区分。后者的好处是省接口但坏处是总带宽要共享。比如一路MIPI是4 lane单颗Sensor跑1080p60fps4 lane刚好够现在接了两颗Sensor都跑1080p30fps那么4 lane总数据量就接近饱和了。一旦超过MIPI的物理带宽包就会出错图像会出现整行花掉的情况。Stream工具查到的帧率、分辨率信息只能说明软件配置上没问题物理层是否丢数据需要看MIPI的错误计数。我曾经碰到过一个情况两路Sensor配置都能出图但画面右半部分有规律性花块排查到最后是MIPI的lane分配不均匀导致的。如果不是靠工具去看这种问题改代码很难定位因为寄存器层面看起来一切正常。4.3 ISP资源在双Sensor场景下的争用很多海思SoC里ISP资源也是分时复用的。如果两颗Sensor共享同一个ISP pipeline那么算力上限、内存带宽上限都要按总和考虑。最典型的例子是3DNR这个模块对内存带宽的占用非常夸张单Sensor开满3DNR没问题双Sensor同时开满就可能出现DDR带宽饱和整个系统的其他任务比如编码、AI推理都会跟着变卡。这种问题I2C、MIPI层都查不出来要用工具去看系统带宽占用和帧率波动。我调试双目时通常先把两路Sensor的3DNR都关掉等联调和效果验证都通过之后再逐步开高以免一开始就被带宽问题搞晕方向。同样的道理也适用于WDR宽动态模式两个Sensor都开WDR时数据量不是翻倍而是更多因为WDR一般需要多帧合成。5. 一组实测案例从单路切到双目的完整排查过程前面讲的都是原则和工具使用方法这一节用我实际排查过的一组问题来串一遍你会更容易理解工具该如何落地。5.1 案例背景硬件上明明都接了图像却只有一路我调试的一块板子是RGBIR双目模组RGB Sensor接MIPI0IR Sensor接MIPI1。配置是按官方Sample改的Sample里默认有Sensor_0我照葫芦画瓢加了Sensor_1I2C地址、Reset脚、power引脚都对着原理图填了。编译烧录后RGB路图像正常IR路没图。串口log里能看到IR Sensor的I2C读写正常Sensor ID读出来也正确但VI上就是没有数据。5.2 一步步定位到第二路没有出图的根因我当时的排查顺序是这样的首先用Stream工具查看两路的Sensor状态。结果IR路显示在线说明I2C和电源没有问题。接着我用Stream抓IR通道的一帧数据得到的是一张全黑的图。这说明Sensor可能在出图但数据没有正确进入ISP或者ISP根本没有对IR做处理。然后我用PQTools连接板端观察IR对应的ISP Pipe有没有RAW数据进来。正常情况下只要Sensor出帧且VI绑定正确PQTools里能看到RAW图的流动。结果发现IR那一侧的ISP Pipe里没有有效RAW。这时候问题被缩小到Sensor虽然在出但数据到不了ISP问题大概率在MIPI配置或者VI通道绑定上。我一条条排查MIPLane数、MIPI时钟频率、VC号、VI设备的channel映射最后发现是一个很隐蔽的问题驱动里对Sensor_1的MIPI时钟是按Sensor_0的配置设置的但IR Sensor实际需要的差分时钟频率和RGB Sensor不一样。IR Sensor输出的数据率超过了VI端配置的预期值导致底层在接收时丢包严重形同无图。把MIPI时钟频率改到位之后IR路立刻出图了。5.3 修好之后不要急着调PQ先验证同步IR路出图后我没有马上开始调IR路的图像效果而是先验证左右两路的同步关系。当时做了一个简单测试用一个LED小灯板做频闪源用两路Sensor同时抓帧持续观察LED在左右目图像里的亮灭状态。结果发现有一段时间左右目的LED亮度相位经常错开明显是同步没做好。后来查到IR Sensor的驱动里有一个软触发模式没有关闭导致它仍然以自由模式跑而不是跟随RGB Sensor的VSYNC。关掉这个模式后两路的相位就完全一致了。这个案例的最大教训是多Sensor调试不能只看能否出图要看所有链路是否按照同一个节拍在跑。很多问题比图像效果更底层而底层问题的定位效率靠的就是工具把范围逐步缩小。6. 调试中容易翻车的细节与个人经验这一节我整理一些零碎但重要的经验每一条都是真金白银换来的。6.1 配置前先看Sensor datasheet的时序表海思SDK的sample配置并不一定能直接覆盖所有Sensor尤其是新模组。很多Sensor在上电时序、MCLK频率范围、PLL配置、输出分辨率切换时序上都有严格限制。如果复位后紧接着就去读Sensor ID可能会因为Sensor还没完成初始化而失败。遇到这种问题不要急着改代码先用示波器量一下电源和MCLK的实际波形确认满足datasheet的时序要求。另外多Sensor项目里两个Sensor的上电时序也要注意。如果它们共用同一路电源或同一个Reset控制脚你在驱动里单独操作其中一路时很可能无意中影响到另一路。这种硬件耦合问题不先确认代码调试会非常痛苦。6.2 日志级别和出错信息的解读海思的ISP和VI模块都有比较详细的异常打印但不同SDK版本里日志开关默认情况不一样有的一上来就是全开信息量大到可读性很差有的默认全关出问题你什么都看不到。我建议拿到新SDK后先把和VI、ISP、MIPI相关的日志级别调成打开并加上printk的时间戳这样排错时至少能判断问题出现的先后顺序。举例来说Stream工具或驱动在VI链路不通时日志里常常会出现frame lost或者buffers not enough之类的字样。第一眼看到这些词很多人会往内存分配、缓存池大小方向想但实际原因可能是MIPI接收端的时序配置不对导致一个帧周期内收不到完整的帧从而报buffer相关错误。日志只能告诉你有问题工具才能告诉你在哪一层有问题两者结合才是完整的排错思路。6.3 常用寄存器现场保存与恢复我是强烈建议你在每一次调整PQ参数前先导出一份当时ISP寄存器的完整状态。海思PQTools支持把当前全部参数导出成xml这个文件不光可以作为回归基准还可以在调试歪了的时候快速恢复省得一级一级去撤销。对多Sensor项目来说更要给每一路Sensor分别建立profile文件。比如Sensor A调好了一版3DNR参数Sensor B也调好了一版3DNR参数你不能只用一份参数跑满两个Sensor。图像效果这东西主观性很强但客观的寄存器状态是可以量化的善用工具把这些状态管理起来能省很多重复劳动。6.4 多路Sensor不要同时调参最后一个个人观点多路Sensor调试永远不要同时调整两路参数。哪怕你觉得自己脑子够用也不要这么做。因为两路参数是独立生效的同时动两路一旦画面出现异常你根本分不清是哪一路的哪一个参数导致的。正确姿势是先调A路调好之后保持不动再调B路最后再把两路一起跑起来做整体联动测试。如果联动后出现问题那多半不是单路参数的问题而是同步、带宽、资源竞争的问题直接往这个方向查就行。另外我每次调完参数都会写一行注释保存到工程里今天调了什么Sensor、当时环境光线大概是什么情况、把某个参数调到多少之后画面有什么变化。这看起来像是个笨办法但几个月后回过头来维护代码时你会感谢当时的自己。与我而言海思ISP调试的门槛不在某个工具用得不熟而在于能否把图像表现和系统链路这两层问题分开对待。PQTools和Stream工具刚好分别站在两侧搭配起来用就像一只手抓链路状态另一只手抓画面质量。先把链路跑通再谈图像效果多Sensor项目少走弯路的关键就在这里。