君正T23ZN双摄方案:智能门锁低功耗人脸识别与硬件设计实战
前阵子做了个智能门锁项目产品经理拍脑袋说猫眼要能看到门口全景同时人脸识别还得保证门锁正下方视角不能有盲区一个摄像头搞不定得上双摄。我当时第一反应就是君正T23ZN。这颗芯片做智能门锁双摄方案优势非常契合低功耗、硬件编码、SDK对双Sensor的支持也比较成熟。整个项目从画板到点亮双摄再到跑通录像和低功耗唤醒前后踩了不少坑。这篇把选型逻辑、硬件设计、SDK代码示例和调试技巧一次性写清楚给正在评估这颗芯片或者正在做门锁/门铃的兄弟留个参考。1. 为什么选君正T23ZN双摄门锁的方案选型逻辑1.1 智能门锁双摄到底解决了什么问题门锁的安装高度通常在1.3米到1.5米之间这个位置相当尴尬。普通猫眼摄像头如果做成大广角视野能覆盖整个楼道但人脸在画面里往往被切掉一半如果把镜头往下压人脸是拍全了门口全局又看不完整。很多产品最后的妥协方案是“广角但不能兼顾近处”导致访客站在门锁正下方时图像里只有头顶或者半张脸。双摄可以把这个矛盾解决掉。我的做法是两颗Sensor分好工一颗广角镜头负责看全局记录楼道动态、快递包裹、开门瞬间的完整画面另一颗斜向下的窄视角镜头专门怼人脸保证从1.5米高的孩子到1.9米高的成年男性站在门锁前方30厘米到1米的位置时都能拍到正脸。这样不管是本地人脸识别还是云端二次核验图像质量都稳定得多。而且双摄带来的玩法不止人脸识别。包裹检测可以同时看重物是否放在门口异常徘徊报警可以同时抓拍全身照而不是只有上半身云存储的事件分段也更清晰。做过门锁的人都知道现在产品拼的不只是功能而是“同样一颗芯片能比别人多做几件事”双摄天然具备这种扩展价值。1.2 T23ZN核心优势低功耗、编码能力与SDK成熟度君正T23ZN是一颗面向低功耗AIoT视频应用的处理器CPU是君正自研的XBurst2核心内部集成H.264/H.265硬件编码器性能刚好够跑720P/1080P实时视频同时还能在CPU侧跑轻量级的移动侦测和人形检测算法。放在智能门锁场景里它不需要外挂编码芯片一颗就能把图像采集、编码、网络传输全部包掉。这颗芯片最大的杀手锏是低功耗。智能门锁大多用电池供电要撑半年甚至一年待机功耗必须做到非常小。T23ZN支持深度睡眠模式配合外部的MOS管电源管理在非触发状态可以完全切断Sensor和WiFi模组的供电只保留MCU和PIR人体感应模块在微安级待机。等PIR检测到人靠近MCU再通过GPIO把T23ZN从休眠中拉起来快速启动摄像头开始抓拍和识别。相比君正T31系列T23ZN的优势是功耗更低、封装更小更适合门锁这种对电池和结构空间都苛刻的产品。而T31系列虽然算力更强但常态下功耗偏高放在门锁里需要做更多电源管理才能把待机压下去。双摄方案里T23ZN对两个Sensor同时注册和分时切换的支持在SDK里都有现成接口不用自己造轮子这对项目进度很关键。2. 硬件设计要点镜头选型、供电与Sensor组合2.1 双Sensor怎么选广角全局镜头斜下人脸镜头先明确分工Sensor A负责全局和录像Sensor B负责近距离人脸识别。Sensor A我选的是1/2.7英寸的1080P Sensor搭配120度广角镜头光圈尽量大保证楼道环境光不足时还能出片。Sensor B选的是1/3英寸720P Sensor搭配45度左右的窄视角镜头光圈和低照度同样重要因为人脸识别很多场景发生在夜间门锁补光灯只能照到正前方一小块区域。两颗Sensor都建议带IR-CUT切换白天过滤红外光夜间把IR-CUT移开配合850nm或940nm红外LED补光。选型时有一个容易忽略的点两颗Sensor的MIPI接口和I2C地址不能冲突。T23ZN的ISP可以接两路Sensor但硬件上要注意第二路Sensor挂在哪个CSI接口、I2C总线地址是多少这些在初始化代码里都要手动指定。如果两颗Sensor恰好用同一个I2C地址软件上就得额外加地址译码逻辑很麻烦所以选型阶段就尽量让两颗Sensor的I2C地址错开。顺带说一句镜头模组和Sensor的搭配不能只看视角还得看畸变和近摄距离。广角镜头边缘畸变大是正常的但用在门锁上要控制畸变率在20%以内不然人脸识别算法对关键点定位的误差会变大。人脸那颗镜头畸变要控制在5%以内毕竟是用来做身份核验的图像几何精度很重要。2.2 安装角度与视场角计算附简化公式双摄安装角度是最容易被软件忽视、实际上又非常影响体验的环节。我的经验是先把机构模型建出来再用三角函数粗算一遍最后上墙实测调整。以门锁离地1.4米、人脸高度1.6米、人脸距门锁水平距离0.4米为例。人脸镜头光轴需要向下倾斜的角度大概是俯仰角 arctan((人脸高度 - 镜头高度) / 水平距离) arctan((1.6 - 1.4) / 0.4) ≈ 26.5度也就是说人脸镜头的光轴要比水平方向往下压约26度。考虑到人脸高低有波动镜头视场角至少要留出上下各10度以上的余量所以实际选用的垂直视场角不要小于40度。如果安装距离更近比如0.3米计算出的俯仰角会更大接近33度这时就需要适当增大镜头视场角或者调整安装倾角。广角镜头同样要算。安装在1.4米高度要覆盖门口左右各1米的区域水平视场角至少要满足水平视场角 2 * arctan(覆盖半宽 / 水平距离)如果门口宽度2米最近覆盖距离0.5米那半宽1米对应的需求就是至少126度水平视场角所以120度左右的广角镜头是最低配置。实际项目里为了保留余量我会选130度甚至140度的镜头同时接受边缘畸变稍微大一点。这个表格可以给结构同事直接参考场景覆盖距离所需水平视场角推荐镜头门口全景0.5米≥126度130度广角门口全景1米≥90度120度广角人脸识别0.4米≥45度45度窄视角2.3 电源拓扑与PIR唤醒架构双摄门锁的硬件架构和普通单摄门锁差别不大关键是电源域要分清楚。我的做法是分成三个电源域MCU域、T23ZN主域、Sensor和WiFi外设域。MCU域常供电负责PIR人体感应、触摸按键、指纹模块的低功耗监听。T23ZN主域通过一颗P沟道MOS管控制MCU检测到PIR触发后把MOS管导通给T23ZN上电。Sensor和WiFi模块的供电再单独用LDO控制T23ZN起来以后通过GPIO决定是否给这些外设供电。这样设计的核心原因是T23ZN即使进入深度睡眠也不是零功耗如果不彻底断电时间一长电池撑不住。彻底断电后T23ZN每次启动都是一次冷启动需要把系统镜像从SPI Flash加载到内存并初始化外设这对启动时间的要求就非常高。启动时间的优化也属于硬件和软件协同的活。T23ZN本身支持快速启动模式可以把关键初始化逻辑精简掉实现从断电到第一帧图像输出的时间控制在500毫秒到1秒之间。PIR检测到有人靠近到门锁开始录像中间大概还有几百毫秒的余量整体体验不会觉得很“迟钝”。电源设计上还有两个细节。一是Sensor模组的供电要干净建议用低噪声LDO纹波控制在30mV以内否则夜间低照度下图像很容易出现横纹。二是FPC排线尽量短并且要避开DDR走线和WiFi天线区域双摄要同时走两路MIPI信号信号完整性问题会翻倍布局阶段就要特别留意。3. SDK环境与双摄代码示例含逐段讲解3.1 交叉编译环境与SDK目录结构君正的SDK一般会提供一整套基于Linux的交叉编译环境拿到后先解压把工具链路径加到环境变量里。T23ZN的工具链通常不是ARM的而是MIPS架构的交叉编译器具体前缀要看方案商给的版本常见的是mips-linux-uclibc-gnu。下面是我这边常用的一套环境变量设置export PATH$PATH:/opt/Ingenic-T23ZN/toolchain/mips-linux-uclibc-gnu/bin export CROSS_COMPILEmips-linux-uclibc-gnu- export ARCHmips设置好之后SDK目录结构大致分为几个部分sdk/下面放的是库文件、头文件和内核源码samples/下面放的是官方示例程序比如sample_venc、sample_ivs、sample_audio等tools/是烧录、打包工具。我第一次上手的时候直接进了samples/sample_venc目录这个示例是视频编码最完整的模板单摄初始化、编码通道创建、码流获取都有现成代码双摄改造也是从它开始的。编译单个示例也很简单进入对应目录执行make就行。如果需要在工程里加入自己的源码就把新的.c文件放到同一目录改一下Makefile把目标文件和依赖加进去。SDK自带的Makefile一般写的都是相对路径我们只需要在Inge nic SDK根目录下编译不要随意移动文件位置否则头文件路径会乱。调试阶段最常用的网络配置是让板子通过静态IP和宿主机直连。开发板上电后用串口登录执行ifconfig配置IPifconfig eth0 192.168.1.168 netmask 255.255.255.0 up ping 192.168.1.1把IP配好后就能用scp直接拉取摄像头抓拍到的图片文件这个调试效率比用串口看二进制数据高很多。3.2 Sensor初始化与编码通道创建代码示例双摄初始化和单摄最大的区别是需要同时注册两个Sensor并且给每个Sensor分配独立帧通道和编码通道。下面这段是基于君正SDK接口写的简化示例核心是讲清楚调用顺序具体参数以你们拿到的SDK版本为准。#include imp/imp_system.h #include imp/imp_framesource.h #include imp/imp_encoder.h static int sensor_a_register(void) { IMPSensorInfo sensor_a; memset(sensor_a, 0, sizeof(sensor_a)); sensor_a.index 0; sensor_a.name sc2336; // 广角Sensor名字 sensor_a.cbus_type TX_SENSOR_CONTROL_INTERFACE_I2C; sensor_a.i2c 0; // I2C总线号 sensor_a.i2c_addr 0x30; // 广角Sensor的I2C地址 sensor_a.mclk 24; // MCLK频率 return IMP_ISP_AddSensor(sensor_a); } static int sensor_b_register(void) { IMPSensorInfo sensor_b; memset(sensor_b, 0, sizeof(sensor_b)); sensor_b.index 1; sensor_b.name gc2053; // 人脸Sensor名字 sensor_b.cbus_type TX_SENSOR_CONTROL_INTERFACE_I2C; sensor_b.i2c 1; // I2C总线号 sensor_b.i2c_addr 0x37; // 人脸Sensor的I2C地址 sensor_b.mclk 24; return IMP_ISP_AddSensor(sensor_b); }这段代码是注册动作。IMP_ISP_AddSensor会把Sensor信息加入ISP的管理列表后面启用的时候才能按index找到对应Sensor。Name字段要和SDK里驱动的Sensor名字严格一致如果SDK没有这个Sensor的驱动支持Name填了也注册不上编译时会报错误或者运行时会提示找不到驱动。注册完之后分别给两个Sensor建立帧源通道和编码通道。这里以Sensor A为例int create_chn_a(void) { IMPFSChnAttr fs_chn_attr; IMPEncoderChnAttr enc_chn_attr; // 帧通道属性 memset(fs_chn_attr, 0, sizeof(fs_chn_attr)); fs_chn_attr.pixFmt PIX_FMT_NV12; fs_chn_attr.outFrmRateNum 30; fs_chn_attr.outFrmRateDen 1; fs_chn_attr.picWidth 1920; fs_chn_attr.picHeight 1080; IMP_System_Init(); IMP_FrameSource_CreateChn(0, fs_chn_attr); IMP_FrameSource_EnableChn(0); // 编码通道属性 memset(enc_chn_attr, 0, sizeof(enc_chn_attr)); enc_chn_attr.encAttr.encType PT_H264; enc_chn_attr.encAttr.profile 2; // High profile enc_chn_attr.encAttr.picWidth 1920; enc_chn_attr.encAttr.picHeight 1080; enc_chn_attr.encAttr.bFrame 0; // B帧不用 enc_chn_attr.encAttr.rcAttr.rcMode ENC_RC_MODE_CBR; enc_chn_attr.encAttr.rcAttr.attrH264Vbr.gop 30; enc_chn_attr.encAttr.rcAttr.attrH264Vbr.maxBitRate 2048; enc_chn_attr.encAttr.rcAttr.attrH264Vbr.minBitRate 512; IMP_Encoder_CreateChn(0, enc_chn_attr); IMP_Encoder_EnableChn(0); IMP_System_Start(); return 0; }这个函数里的参数有几个要注意的地方。GOP设置为30意思是每隔30帧插入一个关键帧IDR假设帧率30fps就是1秒一个关键帧。门锁场景网络波动大关键帧太稀疏会导致丢包后画面恢复慢太密集会浪费码率1秒一个是比较折中的选择。码率最大值2048Kbps也就是2Mbps对1080P视频来说这个码率属于中等偏清水平。如果网络条件差可以降到1Mbps但夜间画面噪点大的时候压缩痕迹会明显所以更推荐保持2Mbps以上。3.3 双摄分时切换与低功耗休眠的代码逻辑双摄有两种实现方式同时开双路和分时切换。同时开双路对ISP和MIPI总线带宽要求高功耗也高而且门锁这种以抓拍和人脸识别为主的场景并不需要两路视频同时持续编码。我最终做的是分时切换默认只跑广角Sensor需要人脸识别前软件切换Sensor到人脸镜头识别完成后重新切回广角或者直接进入休眠。切换流程说白了就是先把原来的Sensor和编码通道停掉再重新注册新的Sensor并创建通道。顺序不能乱尤其是先停编码器再停Sensor否则ISP已经在发送新图像了编码器还在用旧参考帧很容易出现花屏或者绿屏。一个简化的切换函数如下int switch_sensor(int sensor_index) { // 1. 停掉编码接收 IMP_Encoder_StopRecvPic(0); // 2. 停掉帧通道 IMP_FrameSource_DisableChn(0); IMP_FrameSource_DestroyChn(0); // 3. 切断当前Sensor IMP_ISP_DisableSensor(0); IMP_ISP_DisableSensor(1); // 4. 根据目标重新使能对应Sensor IMP_ISP_EnableSensor(sensor_index); IMP_System_Start(); // 5. 重新创建帧通道和编码通道 create_chn_by_index(sensor_index); // 6. 重新启动编码接收 IMP_Encoder_StartRecvPic(0); return 0; }第1步和第2步是很多新手容易踩坑的地方。IMP_Encoder_StopRecvPic会让编码器停止从帧源拿数据但不会清掉已经缓冲的历史帧。真正切换之前最好调用一下编码通道复位接口把编码器状态清干净。第3步DisableSensor的序号不能随手传要确保通过索引确认当前使能的是哪个Sensor不然中断一个没有启用的Sensor可能会让系统挂死。低功耗休眠的逻辑用状态机来描述最直观。整体流程可以抽象成下面几个状态STATE_IDLEMCU巡检PIRT23ZN断电整机待机 STATE_AWAKEPIR触发MCU给T23ZN上电初始化广角Sensor开始录像或抓拍 STATE_FACEDETECT访客靠近切换到人脸Sensor进行人脸识别比对 STATE_SLEEPING识别完成或超时后保存现场关闭外设进入深度睡眠切换状态机里最耗费时间的其实是第4步和第5步之间的Sensor重新初始化。因为不同的Sensor寄存器配置不同ISP要从头做AE和AWB收敛大约需要几百毫秒。优化办法是提前把两颗Sensor的寄存器参数都预留在内存里切换时直接加载不用每次读I2C配置实测可以把切换时间缩短30%以上。4. 调试技巧与常见问题实录4.1 串口、网络、抓帧三板斧嵌入式调试绕不开串口。T23ZN的调试串口一般是UART0波特率1152008N1。上电后串口会输出系统启动日志如果发现输出卡在某个驱动初始化阶段那基本就是对应外设没有准备好比如Sensor没有供电或者I2C通信异常。网络调试是第二板斧。开发阶段把板子通过网线直连电脑配好静态IP之后传文件、远程登录都靠它。很多人一开始就折腾WiFi其实没必要WiFi链路的不确定性太大会把图像问题、网络问题混在一起定位起来很痛苦。先用有线把图像调明白再切WiFi。第三板斧是抓帧。SDK的sample里通常有抓拍接口直接调用保存一帧JPEG到本地然后用scp拉到开发电脑上看图片。我在调试时习惯把当前帧的曝光时间、增益、白平衡值都打进日志里这样看图时能对应上参数排查图像发暗、偏色问题时非常管用。scp root192.168.1.168:/tmp/capture.jpg ./打开图片后先看两个东西整体亮度是否正常、画面角落有没有暗角。暗角通常说明镜头尺寸和Sensor靶面不匹配或者镜头装歪了。偏色则是白平衡没有收敛好优先检查红外截止滤镜有没有切换到位。4.2 四个高频Bug的排查记录第一个Bug是双摄切换后画面花屏。这是我在样机上第一次遇到的切换完Sensor后屏幕上出现大块绿色马赛克持续好几秒。排查方向很明确编码器还在用旧Sensor的参考帧。最后在IMP_Encoder_StartRecvPic之前加了一个编码通道复位动作然后强制编码器输出新的IDR帧问题解决。第二个Bug是夜间图像出现横向滚动的亮纹。一开始怀疑Sensor底噪后来用示波器量Sensor供电发现LDO输出纹波超标夜间增益特别高的时候纹波被放大成了横纹。把LDO换成低噪声型号并在Sensor电源引脚附近加了一颗22uF陶瓷电容横纹立刻消失。第三个Bug是人脸区域过曝。门锁安装位置偏低楼道里的顶灯通常在人脸正上方导致人脸Sensor对着灯光时背光严重。这个在图像调试里很典型解决办法有两个一是开启背光补偿或者宽动态把AE权重区域设置到画面下半部分二是在镜头前加物理遮光尽可能避免直射光。第四个Bug是待机电流下不去。用万用表测待机电流有几十毫安远高于设计值。逐路排查后发现是Sensor供电没有完全关断因为那一路的电源控制GPIO默认电平是高的。把GPIO方向先设成输出再拉低待机电流马上降到了微安级。这里提醒大家GPIO默认状态在初始化代码里就要确认清楚不要依赖硬件默认值。我整理了排查速查表方便后面遇到类似问题直接对照现象可能原因快速排查手段切换后花屏编码器参考帧未清空复位编码通道并强制输出IDR夜间横向亮纹Sensor供电纹波过大示波器量LDO输出换低噪声LDO人脸过曝背光补偿没开开WDR设置AE权重区域待机电流偏高Sensor或WiFi掉电不彻底逐路量GPIO控制电平确保下拉启动非常慢Flash读取慢或镜像过大开启快速启动精简初始化流程4.3 功耗测量与发热控制实操功耗是智能门锁项目的生命线。我在开发阶段用串接电流表的方式把各种状态下的电流记录下来整理成一张基准表之后每次改动代码都要回归一遍。状态电流典型值持续时间备注深度睡眠待机15uA以下常态T23ZN断电仅MCU供电PIR唤醒初始化150mA左右1s整机上电DDR初始化广角录像300mA左右按事件持续含WiFi模组在线人脸识别350mA左右2~4sSensor B 补光灯开启夜间补光录像400mA左右事件持续红外LED功耗占大头如果待机电流超过20uA我会先检查Sensor和WiFi模组的电源控制脚是否完全断开再看有没有外设通过GPIO往主控漏电。实际操作里经常遇到的问题是Capacitor漏电所以PCB布局时储能电容不能跨到常供电域和可控供电域之间。发热控制方面T23ZN在录像状态下的功耗集中在CPU和编码器建议在PCB上做铺铜散热并且把芯片底部焊盘连接到地平面。软件上可以动态降频没有事件触发时不跑高负载任务只有人脸识别那几秒才让CPU全速运行。我把编码分辨率、帧率和码率都做成可配置的夜间且电池电量低时自动降到720P 15fps既省电又降发热。最后再分享一个小技巧双摄门锁的项目周期通常很赶我的建议是把Sensor和镜头选型固定下来后另一颗Sensor尽量选同一个平台已经适配过的型号。君正SDK里预适配的Sensor比你自己从头调一个Sensor省太多事ISP参数、AE曲线都是现成的图像效果也更有保障。这套双摄方案做下来我最深的体会是双摄的难点从来不在“有两个摄像头”而在低功耗、图像效果和切换时序这三者之间的平衡。如果你们项目周期紧前期把Sensor型号、镜头角度和电源拓扑定扎实后面软件调试会顺畅很多。后面我还想在这个平台上把端侧人脸特征提取加进去把识别放到本地省掉每次唤醒都依赖网络的延迟等有新进展再回来更新。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →