
前阵子帮客户做一款可穿戴心电设备的功耗优化发现整机的耗电大头根本不在MCU跑算法上而在ADC采样、数据搬运和无线发送这几个环节。一块小小的传感器几毫瓦的功耗光是往外搬原始波形数据就吃掉一大半。这个现象在行业里太常见了大家习惯性把“智能“都堆在后端却忽略了感知端本身。而传感器端计算in-sensor computing这个方向恰好就是冲着这个问题去的与其把海量原始数据搬出去再算不如让传感器在感知的同时就把计算做掉一部分。这篇文章我会从产品原型验证的角度聊聊传感端计算到底怎么理解、哪些场景真正适合它、动手做原型要走什么流程以及我踩过的那些坑。如果你正在做低功耗AIoT、可穿戴健康监测、工业状态检测这类项目或者对“边缘计算还能不能再往下沉一层”感兴趣这篇文章应该能给你一些能直接上手的参考。我说的不一定都是标准答案但都是从实际项目里验证过的思路。1. 传感器端计算到底在解决什么问题1.1 数据搬移的成本远比你想象的高我们先看一个非常典型的链路传感器采集信号经过放大、ADC转换送到MCU或者SoC然后做特征提取、推理最后把结果传出去。看起来每一步都很合理但问题在于传感器输出的原始数据量远远超过真正有用的信息量。举一个简单的数字。一颗100万像素的CMOS图像传感器每个像素输出8bit30fps的情况下每秒产生大约240MB的数据。打个比方这就好比一个图书馆每天要把所有藏书复印一遍送到某个地方去只为了让研究员查找其中某一页的内容。最后得到的分类结果可能只是一个“有人”或“没人”的标签几个bit就够但中间搬运了几百兆字节的数据。这种数据搬移带来的功耗和延迟在边缘设备上是非常奢侈的。传感器端计算的核心逻辑就是把计算下沉到传感器内部在数据还没有被大范围搬移之前就在感知阵列里面完成一部分特征提取甚至分类推理。这样做的结果就是后端拿到的可能是压缩后的特征向量、事件流统计值甚至是直接可用的分类结果原始数据不用大规模离开传感区域。这条思路在神经形态计算、事件相机、感存算一体这些领域里已经是公认的方向。1.2 传感端计算与边缘计算、近传感器计算的区别很多朋友会把传感器端计算和边缘计算混在一起。严格来说它们是不同层级上的概念。边缘计算通常指的是网关、硬件加速器或者设备端处理器上进行的计算传感器和处理器之间还有数据传输链路。而近传感器计算指的是把处理器和传感器封装在一起但物理上还是两颗独立的芯片比如现在很多手机摄像头模组里自带的ISP。传感器端计算则是更激进的做法把计算单元直接做进像素阵列或者传感元件旁边甚至直接在模拟域里完成部分运算。为了更好理解我画一个简单的对照表计算层级计算位置数据搬移量典型时延典型功耗代表方案云端计算数据中心极大高极高视频上传云端分析边缘计算网关/设备处理器较大中中摄像头端部署轻量CNN近传感器计算传感器模组内独立芯片较小低较低传感器ISP集成模组传感器端计算传感阵列内部/模拟域极小极低极低像素内处理、事件相机传感器端计算的终极目标是做到“感知即计算”数据还没”出门“计算就已经发生了。这个思路在生物体里是天然存在的人的视网膜不是简单地把图像传到大脑而是在视网膜层面就先做了边缘增强、运动检测这类预处理。这也是为什么很多做机器视觉的研究者会从类脑计算里找灵感。1.3 什么场景真正需要传感器端计算不是所有场景都需要这种技术。我自己判断一个项目是否适合做传感器端计算通常看三个条件。第一数据量远大于信息量。比如连续采样的振动信号、视频流、多通道生物电信号。如果任务只是监测异常、检测特定事件那么大多数原始数据都是冗余的。第二功耗和延迟预算极度紧张。比如纽扣电池供电的穿戴设备、植入式医疗设备、微型传感器节点。这类设备往往连MCU都舍不得一直全速跑更别说把原始数据往外搬了。第三隐私或者带宽限制。如果原始数据一旦出传感器就必须加密传输而带宽又很有限那么在传感器端直接把原始数据打碎只输出特征是一个合理的架构选择。反之如果你需要的是高保真原始波形做离线分析或者算法还在频繁迭代那就不要急着做传感器端计算。算法不稳定的时候过早固话在硬件里会让自己非常被动。2. 核心原理拆解传感端计算到底在哪里算、怎么算2.1 模拟域计算让光电二极管直接“算”起来传感器端计算最底层的实现方式是在模拟域里做计算。以图像传感器为例传统做法是每个像素的光电二极管把光信号转成电荷电荷再转成电压经过ADC变成数字量。而模拟域计算的想法是在电荷或者电压还没有转成数字之前就直接利用物理特性完成计算。最典型的操作是加权求和。比如我们想要检测画面里某个方向的边缘标准做法是拿Sobel核去卷积图像。卷积操作本质上是大量乘累加。在像素阵列内部可以通过共享电容或者电荷耦合的方式让相邻几个像素的光电流直接按权重累积起来最后测得的总电荷量就是卷积结果。整个过程不需要逐个像素ADC量化也不需要数字乘法器功耗可以低到让人惊讶的程度。我常用的一个生活化类比是“水桶倒水”。你有一排水桶代表像素你往每个桶里倒的水量代表该像素的亮度与权重的乘积然后你把相邻几个桶的水全部倒进一个大容器里量一下总水量这就是卷积结果。全部操作在物理层面完成不涉及任何数字逻辑翻转。当然模拟域计算也有代价。它的精度有限容易受工艺偏差、温度漂移影响而且一旦流片之后再想改算法就很难了。所以实际产品里通常采用“模拟粗算数字精算”的混合架构传感器端提取一些可靠的低层特征后端做小型分类器。2.2 事件驱动没有变化就不计算和模拟域计算并列的另一条重要路线是事件驱动传感计算。这类传感器不按固定帧率输出图像而是异步输出事件每个像素独立检测光强变化只有当变化量超过阈值时才输出一个包含位置、时间戳和极性的事件。没有变化的区域完全不产生数据也就完全不消耗计算和带宽。事件相机Dynamic Vision SensorDVS是这条技术路线最典型的代表。DVS的I/O不是整帧图片而是事件流。事件流天然稀疏非常适合做手势识别、工业振动检测、高速运动分析这类任务。而且事件相机的时间分辨率非常高微秒级的事件时间戳意味着它可以捕捉极高速的动态变化。从传感器端计算的角度看事件相机最有价值的地方在于它摆脱了“全局快门帧传输”的固定模式。传统视觉传感器的功耗和时间都浪费在采集和传输不包含运动信息的静态背景上。事件相机只对“变化”响应把资源集中在真正有信息量的动态部分。做事件相机应用时有个关键体验事件流里的“事件”并不等于“特征”它更像是原始像素级变化信号。实际还是需要后端做聚类、计数、方向统计等处理。好在事件流的稀疏性让这些统计运算量急剧下降一个低功耗MCU完全能在几毫秒内处理完。2.3 感存算一体把存储也搬进传感阵列如果我们再往前推一步把存储能力也集成进传感器就进入了感存算一体In-Sensor Computing and Storage的范畴。这个方向这几年和存内计算Computing-in-Memory融合得非常紧密。为什么要研究感存算一体因为传统架构中传感器采集完数据要先把数据存到存储器里再拿去做计算。即使计算本身已经下沉到传感器边缘如果数据还是要在“计算单元”和“存储单元”之间来回搬运依然会浪费功耗。感存算一体希望把权重值、中间特征图这些数据直接存到传感阵列的像素结构里实现原位计算。比如在图像传感器里可以通过非易失器件如铁电器件、阻变器件实现像素内权重存储。光照产生的光电流与存储的权重直接在像素内完成乘法然后通过列级共享信号线完成累加。这样一来整个卷机操作可以在一个很短的时间内并行完成而且不需要把任何中间数据搬出去。不过说实话感存算一体目前更多还是在学术研究和早期原型阶段。作为个人或者小团队能接触到的成熟商用芯片很少。我做原型验证时更多是用FPGA去模拟“像素级并行计算”的行为或者用商业化器件去逼近“传感端计算”的效果而不是直接流片。3. 实操指南从零设计一个传感端手势唤醒识别原型3.1 项目目标与系统架构选型没有实操的讲解都是耍流氓。下面以我做过的一个手势识别原型为例讲讲具体流程。这个项目的目标场景是低功耗智能门铃平时休眠当有人挥手时设备主动唤醒进入人脸识别模式。传统方案是摄像头一直开着把每一帧送到SoC里跑检测模型。功耗高隐私也不好。我们希望把“是否有人挥手”这个判断尽量下沉到传感器端。硬件选型上我选择了事件相机作为感知前端后端配上低功耗MCU。选事件相机的原因有二第一事件流天然只输出动态变化对“挥手”这种动作非常敏感第二事件流数据量小MCU不需要昂贵的高速接口就能处理。并不是所有传感器端计算都必须用事件相机但这个场景下它确实是最顺手的选择。整个系统分成两个阶段。第一阶段是“传感端计算”事件相机内部或者紧邻的FPGA直接对事件流做特征统计比如事件率、活跃区域位置、方向直方图。第二阶段是“后端子分类”MCU拿到这几维特征向量后跑一个非常轻量的分类模型比如决策树或者几十个参数的MLP判断是否挥手。注意MCU拿到的不是原始事件流而是已经压缩过的特征统计量这是传感端计算架构的关键区别。3.2 事件流特征提取怎么做事件相机输出的事件格式是(x, y, t, p)。x和y是像素坐标t是时间戳p是极性变亮或变暗。原始事件流可以非常密集尤其在快速挥手时每秒可能产生几十万事件。虽然比原帧率数据已经少很多但如果直接把事件流全量送给MCUMCU也会被中断压垮。我的做法是在靠近传感器的地方做三级特征提取。第一级是背景活动滤波Background Activity FilterBAF。事件传感器受噪声影响会输出很多孤立事件这些事件在空间和时间上跟相邻事件没有关联。BAF只保留在时间和空间附近有其他事件伴生的事件把孤立噪声滤掉。这一步一般放在传感器的逻辑层或者紧邻的FPGA里完成。第二级是时间表面统计。把事件流划分成非常短的时间窗口比如10ms统计每个窗口内的事件计数、事件重心坐标以及事件在x和y方向上的正负极性和。思路很简单一个人挥手时事件重心会跟随手的运动轨迹变化方向极性也会出现有规律的交替。这个统计量只有几维非常精简。第三级是滑动窗口差分。把相邻两个时间窗口的特征值做差分得到事件重心移动的方向和速度。这一步可以在MCU上完成因为数据量已经很小了。下面给一个参考公式。在第k个时间窗口内x方向事件重心坐标可以表示为Gx(k) (sum(x_i * p_i)) / (sum(p_i))其中x_i是事件横坐标p_i是事件极性。当手在左右摆动时Gx(k)会呈现出明显的周期变化。通过相邻窗口差分可以得到运动速度估算值Vx(k) (Gx(k) - Gx(k-1)) / delta_t这个Vx向量序列就是后续分类的输入特征。整个过程从事件相机原始输出到特征提取可以流水线化处理延迟控制在几十毫秒以内。3.3 轻量分类模型的设计思路拿到特征向量之后手势识别问题就变得非常简单。我不建议在这个环节上CNN一个只有几十个参数的小型分类器已经足够了。挥手动作的特征模式在时间维度上有非常明确的规律事件率升高、重心轨迹呈正弦状周期变化、运动速度交替正负。我第一次实现时用的是MCU上的三层MLP输入维度6包含事件率、重心坐标、运动速度等隐层16个节点输出2个类别有挥手/无挥手。训练数据来自实际场景采集大概采集了200段正样本和400段负样本。模型参数量不到两百个在MCU上推理一次只需要几十微秒功耗几乎可以忽略。有一个特别重要的点合成数据和实际数据的分布差异。如果只是在实验室合成事件流来做训练部署到实际场景基本会翻车。因为室内的光照变化、人体阴影、开关门这些都会产生大量干扰事件。我强烈建议在目标场景里多采集真实数据而且标注时要把“背景事件”和“目标事件”尽量分开。3.4 功耗估算与参数调优传感端计算带来的功耗收益在整个系统链路里非常明显。实测下来事件相机工作功耗在几个毫瓦到几十毫瓦之间具体的和分辨率、事件率有关不同厂家的器件差异比较大MCU平时进入低功耗休眠模式只有收到事件相机的中断唤醒信号才运行整体平均功耗可以控制在毫瓦级。参数调优是这里面最能体现手感的部分。事件相机的对比度阈值是“灵敏度”的核心参数。阈值设置过高事件少但可能漏检轻微的手部移动阈值设置过低事件数量爆炸噪声也增多。一般来说先默认用厂家的推荐值然后在目标场景里观察事件率分布再针对性调整。我自己的经验是以手部正常摆动的速度为准保证事件率达到每秒几万到十几万的水平效果会比较理想。另一个关键参数是BAF的时间窗口和空间邻域大小。窗口太大会把真正的手部运动事件也滤掉窗口太小则无法滤除噪声。建议先从时间窗口5ms、空间邻域3x3开始调。下面是一张调参速查表我在项目里经常用参数影响调节方向对比度阈值灵敏度与噪声水平事件过多就调大事件过少就调小BAF时间窗口噪声滤除强度噪声多就调大运动模糊就调小BAF空间邻域孤立事件滤除通常3x3起步时间窗口长度特征稳定性和延迟延迟要求高就调小特征要稳就调大唤醒中断阈值系统唤醒灵敏度误唤醒多就调高漏唤醒多就调低调试时不要只盯着一个参数看最好先把事件流可视化直观感受每个参数对事件分布的影响。我看过太多人一上来就调算法连原始事件流长什么样都不知道最后白费功夫。4. 工具链与开发环境现阶段怎么把原型跑起来4.1 数据集与仿真环境做传感端计算原型第一步通常不是买硬件而是先把手上的数据集搞清楚。事件相机领域有几个公开数据集可以用于算法验证比如N-MNIST、DVS128 Gesture、ASL DVS等。N-MNIST适合做基础分类的基线测试DVS128 Gesture非常适合做手势识别预研里面有多个受试者的挥手、拍手、旋转等动作。算法验证层面我推荐用Python生态。处理事件流数据时tonic这个库很好用它专门负责事件流数据集的加载和增强。dv-processing是英文事件相机厂商提供的数据流处理库用来读事件流文件和做可视化非常方便。拿到事件流之后可以先用numpy做特征统计把特征向量导出来用scikit-learn训练一个小模型。这样在还没有硬件的情况下就能把算法链路完整跑通。仿真还有一个容易被忽视的环节模拟传感器端计算的非理想性。为了模拟模拟域计算带来的噪声和失配我在做算法验证时经常会给特征向量故意注入一些随机偏移和噪声看看模型对模拟误差的鲁棒性。这样做出来的模型迁移到真实硬件上的成功率要高很多。4.2 硬件平台选择与电路设计硬件平台的选型取决于你的目标精度和开发预算。如果只是想验证事件流特征提取的可行性直接用厂商的评估板比如基于DVS芯片的评估套件加上一块低功耗MCU开发板就够了。如果希望更贴近“传感端计算”的架构可以在传感器和MCU之间加一块小规模FPGA把特征提取逻辑直接写进FPGA里这样MCU只做最终决策。FPGA选型方面我推荐Lattice的iCE40系列或者CrossLink-NX。前者是超低功耗的适合电池供电场景后者自带MIPI接口可以直接接图像传感器或事件相机不需要额外的桥接芯片。如果是做模拟域计算相关的定制芯片那就是完全不同的流程了。需要用到Cadence模拟设计套件做晶体管级仿真还要设计像素版图、做DRC/LVS验证。这种开发周期通常要半年以上而且流片成本极高。个人开发者想接触感存算一体的核心电路建议先通过学术合作或者开源芯片项目切入不要一上来就自己流片。4.3 能效评估用数据说话传感端计算最终面向的是低功耗场景所以能效评估不能只看算法精度。一个完整的评估体系至少包括以下指标端到端精度、传感器与计算单元的总功耗、单次推理延迟、芯片面积成本、每秒处理的帧数或事件数。其中“总功耗”是最容易被低估的很多方案只报计算核心的功耗把ADC、时钟、接口逻辑、片上存储器的功耗全部隐藏掉这样得出的数字没有任何参考意义。能效比指标通常用每瓦特每秒处理的帧数FPS/W或者每瓦特每秒处理的GOPSGOPS/W来描述。对于传感器端计算方案我建议额外增加一个指标每比特有效信息的能耗也就是“完成一次有效识别消耗的能量”。这个指标能够把“数据搬移节省”体现出来。我个人在做项目汇报时会把对比基准定为“传统帧相机后端MCU推理”的方案用同一套数据集和同一套精度要求分别测量两种架构的总功耗与端到端时延。只有在这种同一基准的横向对比下传感端计算的优势和代价才是真实的。5. 常见问题与排查技巧实录5.1 分类漂移严重光照一变就失灵这是事件流方案最常遇到的情况。事件相机的对比度阈值本质上是在光强对数域上设定的它和绝对光照强度有关。强光环境下手部轻微动作可能触发大量事件弱光环境下同样的动作可能触发很少事件。排查思路是先看事件率直方图。在目标场景的不同光照条件下分别采集一段静态背景事件流和动态手势事件流观察事件率分布。如果动态和静态的事件率差异在弱光下变得非常小说明阈值或特征提取选得不对。解决办法通常是加一个自动增益机制。比如根据过去一段时间的事件率来动态调整传感器阈值参数或者在后端对特征做归一化处理。我做项目时更倾向于后者因为传感器参数动态调节在大批量部署时会增加标定成本。特征归一化是在算法层解决更稳妥。5.2 荧光灯环境下的周期性误触发室内照明下的50Hz或者100Hz频闪会让事件相机输出大量周期性事件。这类事件在时间维度上非常规律容易被误识别为节奏性的手势。排查方法是把事件流按时间戳做快速傅里叶变换如果频谱在50Hz或100Hz处有明显峰值基本可以断定是照明频闪。解决方案有很多种最简单粗暴的是在特征提取环节加一个高通或者带通滤波器把频闪对应的频率成分去掉。也可以在特征统计时拉长时间窗口让周期性噪声在窗口内被平均消解。如果你手头数据量充足也可以在训练时加入频闪噪声增强让模型学会忽略这类干扰。我个人最推荐在传感端用低功耗模拟或简单数字滤波把频闪成分先干掉也就是在事件流转换成特征之前就滤除。这样后端得到的数据会非常干净MCU的负担也更小。5.3 模拟域精度不够可靠性和数据救场如果你做的是更底层的模拟域传感计算一定会被精度问题折磨。不同芯片之间的工艺偏差、同一芯片不同像素之间的失配、温度漂移都会导致计算结果偏离理论值。纯模拟计算很难做到8bit以上的有效精度。我踩过几次坑之后总结出几个缓解办法。第一在传感阵列里做差分结构让两个相邻像素的差值参与计算这样可以抵消一部分共模噪声和固定的像素失配。第二流片前做好每个像素的输出校准把增益和偏移系数存进片上查找表。第三算法模型在训练时就要引入噪声鲁棒性把传感器的非理想特性当作可学习的噪声处理而不是期望它是完美的。说实话模拟域计算并不适合精度要求高、动态范围大的任务。适合它的是那种“只需要判断一个大概状态”的任务比如热释电感应、环境光变化检测、震动事件判断。做方案选型的时候不要把模拟域计算神化先问自己这个任务真的需要那么高精度吗如果不需要那就可以大胆地利用模拟域的低功耗特性。5.4 功耗评估虚低传感器端计算隐藏功耗很多朋友做的原型测完后发现并没有比传统方案省多少电。排查完发现问题出在“只测了计算核心的功耗”而忽略了传感器读取电路、时钟生成、接口通信这些外围部分的功耗。我处理这类问题的方法是把整个采集链路的功耗逐级拆开测传感元件、模拟前端、ADC、接口、计算单元、存储、唤醒电路每一级的功耗都单独标定。拆完之后你会发现有时候真正耗电的不是计算本身而是模拟前端和接口。这时可以在架构上做减法如果计算已经发生在传感器端接口和存储是不是就可以省掉或者把ADC的采样率降低还有一个容易忽略的是“空闲功耗”。事件相机在没有任何事件的时候功耗很低但一旦持续有大量事件输入功耗会线性上升。如果你的应用环境是非常复杂的动态纹理场景比如树叶摇晃事件率会居高不下功耗也会远超预期。这种情况需要在系统设计阶段就预留功耗余量。5.5 从原型到量产工程细节才是拦路虎实验室原型跑通之后真正的挑战才刚刚开始。批量部署时每个传感器的参数都不完全一样需要产线标定。温度范围拉大之后比如零下20度到60度模拟阈值漂移会让设备性能发生明显变化。这些都是原型阶段不容易察觉但量产时必然会遇到的问题。我现在的习惯是在设计研发之初就给产品预留测试点和校准接口。比如在传感器板上留I2C接口用于产线自动校准在算法里预留阈值参数的外部配置入口这样不用改固件也能针对性调整。别看这些工程细节不起眼很多项目就是死在这些细节上的。另外一个非常实用的建议在做传感端计算方案时一定要保留一个原始数据的旁路输出接口。平时正常工作是特征流或者事件流出去遇到问题时可以切换到原始数据模式把完整传感数据送出来分析问题。没有这个旁路排查故障会痛苦好几倍。回到最开始的那个心电项目。后来我帮客户重新设计了架构在传感器端直接做R波检测和心率计算MCU只在需要的时候读取心率值和异常片段整机功耗降到了原来的三分之一而且隐私问题也顺带解决了。这个经历让我越来越确信传感端计算不是学术圈自嗨的概念它在当下的低功耗设备设计里是真正能落地、能解决问题的方向。当然它不是万灵药。它改变的是“数据在哪里被处理”这件事而不是“算法本身有多聪明”。如果你的算法还不成熟、特征还没定下来别急着往下沉。先在后端把算法磨清楚再下沉到传感器端这是我自己比较推荐的稳妥路径。最后再分享一个小技巧。在做任何一个传感端计算方案时先画一张“数据流瀑布图”把每一个环节的数据量、精度、功耗、时延都标在上面。画完之后你会发现哪些环节该砍、哪些该合并、哪些必须保留全都一目了然。这张图比100页的需求文档都有用。