
1. 从一颗传感器说起为什么要把 AI 塞进设备里前阵子帮一个做工业设备的朋友看方案他手里有一台振动监测仪原本的做法是把传感器采到的数据通过总线传到上位机再由上位机跑算法判断设备状态。问题出在现场一台设备上挂了十几个测点采样率一高总线带宽就吃紧上位机那边排队处理延迟从几十毫秒涨到几百毫秒等报警出来轴承可能已经开始磨了。他问我能不能让传感器自己聪明一点采完数据就地判断只把结论传上去。这个问题其实指向了这几年嵌入式领域一个很实在的方向——嵌入式人工智能英文里常说的TinyML也是这个范畴。简单讲就是把原本跑在云端或者工控机上的机器学习模型压缩、裁剪之后部署到MCU微控制器这类资源极其有限的芯片上让设备在本地完成推理而不是什么都往上传。传感器是这套逻辑里最典型的载体它本来就是数据源头把 AI 能力直接嵌进去等于让眼睛和耳朵自己带上了判断力。我写这篇东西不是要讲什么宏大叙事而是想把这条链路上真正会卡人的地方摊开说清楚模型怎么从训练框架落到 MCU 上、内存和算力怎么抠、传感器数据怎么喂进去、推理结果怎么用。适合正在做传感器课程设计的学生、做物联网设备开发的工程师以及想给现有硬件加一点智能但不知道从哪下手的人。哪怕你之前只写过单片机裸机程序没碰过机器学习看完也能理出一条可执行的路径。2. 嵌入式 AI 的整体设计思路为什么不能照搬云端那套2.1 云端推理和端侧推理的本质差别很多人第一次接触这个方向脑子里想的还是把模型跑起来这件事但云端和端侧的约束完全不是一个量级。云端推理你关心的是吞吐、并发、GPU 利用率内存几个 G 起步模型几百兆也无所谓。端侧推理面对的是另一套账本一颗常见的 Cortex-M4 MCU主频几十到一百多兆SRAM 可能只有 64KB 到 256KBFlash 也就 512KB 到 1MB。你要把模型、中间张量、输入缓冲区、系统栈全部塞进这个空间里。我习惯用一个类比云端跑模型像在仓库里搬货地方大叉车随便开端侧跑模型像在电梯里搬货你得先把货拆成能进电梯的尺寸还得算好一次能搬几件。这个拆和算就是嵌入式 AI 的核心工作。具体到数字上一个普通的卷积神经网络动辄几百万参数按 float32 存就是几 MB 到几十 MB直接放进 MCU 的 Flash 都放不下更别说推理时还要额外的中间激活值。所以端侧方案的第一原则是模型必须为硬件量身定做而不是训练完再想办法塞。2.2 三种主流落地路线的取舍实际项目里把 AI 放进传感器大致有三条路各有各的适用场景选错了后面全是坑。第一条是纯 MCU 端侧推理。模型量化成 int8用 TensorFlow Lite for Microcontrollers 或者 CMSIS-NN 这类库跑在 MCU 上。优点是成本低、功耗低、响应快一颗几块钱的 MCU 就能干活。缺点是模型容量受限复杂任务做不了适合关键词识别、简单振动分类、异常检测这类任务。第二条是MCU 加专用加速器。有些芯片内置了 NPU 或者 DSP 扩展比如带 Ethos-U 的 Cortex-M 系列或者带 Hexagon DSP 的方案。算力比纯 MCU 高一个数量级能跑稍大的模型功耗仍然可控。代价是开发工具链更复杂模型部署要过厂商的编译器。第三条是传感器加边缘网关。传感器本身只做采集把数据送到附近一个算力更强的边缘设备比如带 GPU 的小盒子上推理。这条路的模型自由度最高但延迟和成本也上去了适合多传感器融合的复杂场景。我个人的经验是先看任务的实时性要求和数据量。如果要求毫秒级响应、单点数据量不大优先考虑纯 MCU如果模型确实压不下来再往上升级。别一上来就上网关很多时候是杀鸡用牛刀。2.3 传感器侧的特殊约束传感器这个载体还有它自己的麻烦。第一是数据质量传感器信号往往带噪声、漂移、温漂模型在实验室数据上表现好到现场就崩。第二是采样与推理的节奏传感器是连续采样的但推理不能每个采样点都跑一次得做窗口切分窗口长度和步长直接影响延迟和准确率。第三是功耗预算很多传感器节点靠电池供电推理一次耗多少电、多久跑一次直接决定电池能撑几个月。这三点决定了嵌入式 AI 在传感器上的设计不是模型越小越好而是在准确率、延迟、功耗、内存之间找平衡点。下面几节我会把每个环节拆开讲。3. 核心细节解析模型、数据、硬件三件事怎么对齐3.1 模型压缩量化、剪枝、知识蒸馏的实际效果模型压缩是绕不开的第一步。我按实际用下来的感受排个序。量化是最有效也最常用的手段。把 float32 的权重和激活值转成 int8模型体积直接降到四分之一推理速度通常能提升两到四倍因为整数运算在 MCU 上比浮点快得多。代价是精度会掉一点通常掉 1% 到 3%做得好可以控制在 1% 以内。量化的关键是校准你需要一批有代表性的数据跑一遍统计每层激活值的动态范围确定缩放因子。校准数据选得不好精度掉得会很厉害。剪枝是把模型里贡献小的权重去掉让模型变稀疏。理论上能减小体积但实际在 MCU 上收益有限因为稀疏矩阵的运算不一定比稠密快除非硬件专门支持。我一般只在模型实在压不下来时才考虑。知识蒸馏是拿一个大模型教一个小模型让小模型学到接近大模型的表现。这个在端侧很有用但训练成本高需要同时维护两个模型。适合对精度要求高、又有训练资源的场景。我的建议是先量化量化后精度不够再考虑蒸馏剪枝放最后。大部分传感器任务量化后的模型就够用了。3.2 数据窗口与特征工程别让模型输在起跑线传感器数据和图像不一样它是时间序列。你不能把一个采样点丢给模型得切成窗口。窗口长度怎么定这取决于你要检测的事件持续时间。比如检测电机轴承故障故障特征频率可能在几百赫兹窗口至少要覆盖几个周期通常取 256 到 1024 个采样点。步长决定推理频率步长等于窗口长度就是无重叠步长小于窗口长度就是有重叠重叠能提高召回率但增加计算量。特征工程这块很多人想直接上原始数据让模型自己学但在 MCU 上这往往不划算。原始振动信号直接进 CNN第一层计算量就很大。更实际的做法是先做传统特征提取比如时域的均方根、峰值因子、峭度频域的 FFT 后取几个频带能量把这些特征组成一个几十维的向量再喂给一个小型全连接网络或者决策树。这样模型能小到几 KB推理一次几毫秒精度还不差。我做过一个对比同样检测三种电机状态原始信号进 CNN 的模型是 120KB准确率 94%手工特征加全连接网络的模型是 8KB准确率 92%。在 MCU 上后者明显更实用。3.3 硬件选型算力、内存、外设的三角平衡选 MCU 的时候别只看主频。我列几个真正影响嵌入式 AI 的指标。指标为什么重要常见参考值SRAM 大小决定中间张量能开多大至少 64KB推荐 128KB 以上Flash 大小决定模型能存多大至少 256KB推荐 512KB 以上是否带 FPU影响浮点运算速度有 FPU 能省不少事是否带 DSP 指令影响定点运算效率CMSIS-NN 能利用上主频影响推理延迟80MHz 以上比较从容外设接口决定传感器怎么接I2C、SPI、ADC 按需如果预算允许带 Cortex-M4 或 M7 内核、有 FPU 和 DSP 指令的芯片是首选。M0 也能跑但基本只能跑极小的模型而且得全定点。我踩过的坑是一开始选了颗 M0模型量化后跑起来推理一次要 80ms采样窗口都来不及处理最后只能换芯片。4. 实操过程从训练到部署的完整链路4.1 训练环境的搭建与模型定义训练还是在 PC 上做用 TensorFlow 或者 PyTorch 都行。我习惯用 TensorFlow因为后面转 TFLite 比较顺。环境用 conda 建一个隔离的Python 3.8 到 3.10 都行太新的版本有些库还没跟上。模型定义的时候就要想着端侧约束。几个原则层数别太深超过 10 层的网络在 MCU 上基本跑不动通道数别太大卷积层通道数控制在 32 以内避免大核卷积5x5 以上尽量用两个 3x3 替代全连接层节点数别超过 256。这些约束在训练时就要遵守不然训练完再改结构等于重来。import tensorflow as tf model tf.keras.Sequential([ tf.keras.layers.Conv1D(16, 3, activationrelu, input_shape(256, 3)), tf.keras.layers.MaxPooling1D(2), tf.keras.layers.Conv1D(32, 3, activationrelu), tf.keras.layers.MaxPooling1D(2), tf.keras.layers.Flatten(), tf.keras.layers.Dense(32, activationrelu), tf.keras.layers.Dense(3, activationsoftmax) ])这个模型输入是 256 个采样点、3 个通道比如三轴加速度输出 3 分类。参数量大概几万量化后几十 KBM4 上跑没问题。4.2 训练、量化与转换的具体步骤训练本身没什么特别的注意数据要按类别均衡传感器数据往往正常样本远多于异常样本得做重采样或者加权。训练完先看 float 模型的准确率作为基准。量化用 TensorFlow 的 TFLite 转换器关键是提供代表性数据集。这个数据集要从训练集里抽覆盖各种工况一般 100 到 500 个样本就够。def representative_dataset(): for i in range(200): yield [train_data[i:i1].astype(float32)] converter tf.lite.TFLiteConverter.from_keras_model(model) converter.optimizations [tf.lite.Optimize.DEFAULT] converter.representative_dataset representative_dataset converter.target_spec.supported_ops [tf.lite.OpsSet.TFLITE_BUILTINS_INT8] converter.inference_input_type tf.int8 converter.inference_output_type tf.int8 tflite_model converter.convert() with open(model.tflite, wb) as f: f.write(tflite_model)转完之后一定要验证量化模型的精度用测试集跑一遍和 float 模型对比。如果掉得超过 3%回去检查校准数据或者调整模型结构。4.3 把模型部署到 MCU 上TFLite 模型是个二进制文件需要用xxd转成 C 数组或者用厂商工具直接生成。然后集成 TFLite Micro 运行时到工程里。xxd -i model.tflite model_data.cc在 MCU 代码里初始化解释器、分配张量内存、喂数据、取结果。这里最容易出问题的是内存分配。TFLite Micro 需要一个 arena大小要够放所有中间张量。太小会报错太大浪费 SRAM。我一般先用一个偏大的值跑通再用interpreter-arena_used_bytes()看实际用了多少然后调到刚好够用加一点余量。constexpr int kTensorArenaSize 60 * 1024; static uint8_t tensor_arena[kTensorArenaSize]; tflite::MicroInterpreter interpreter( model, resolver, tensor_arena, kTensorArenaSize); interpreter.AllocateTensors(); int8_t* input interpreter.input(0)-data.int8; // 填充 input interpreter.Invoke(); int8_t* output interpreter.output(0)-data.int8;推理延迟实测下来上面那个模型在 80MHz 的 M4 上大概 15ms 一次完全够用。4.4 传感器数据接入与推理调度传感器接入这块看接口类型。I2C 的传感器读起来简单但速率有限适合低速信号。SPI 快适合高速采样。模拟传感器走 ADC要注意采样率和分辨率。推理调度我一般用一个定时器触发比如每 100ms 采一批数据凑够一个窗口就跑一次推理。窗口之间可以重叠提高响应速度。注意推理期间不要阻塞采样可以用 DMA 把采样数据搬到缓冲区CPU 专心跑推理。功耗方面如果电池供电可以让 MCU 大部分时间休眠定时器唤醒采样和推理跑完继续睡。实测下来这种间歇工作模式能把平均电流压到几百微安电池撑几个月没问题。5. 常见问题与排查技巧实录5.1 模型部署阶段的典型报错问题一AllocateTensors 返回错误。九成是 arena 太小。先加大到 128KB 试跑通后看实际用量再缩。也有可能是模型里有 MCU 不支持的算子用resolver注册算子时确认一下。问题二推理结果全是同一个类别。多半是输入数据没归一化。训练时输入是归一化到 0 到 1 或者 -1 到 1 的部署时忘了做同样的处理模型看到的分布完全不对。检查输入量化参数确保喂进去的 int8 值范围正确。问题三精度比 PC 上掉很多。先确认量化校准数据是否有代表性再检查输入输出的量化参数是否和训练时一致。有时候是某些层的激活值范围太宽量化后分辨率不够可以考虑对那层单独处理或者换激活函数。5.2 现场运行时的疑难杂症问题四实验室好好的现场就误报。传感器信号受温度、安装方式、背景噪声影响很大。解决办法是在现场采一批数据做微调或者加一些鲁棒性处理比如滑动平均、异常值剔除。我一般会在推理结果上加一个连续确认机制连续几次都判为异常才报警能过滤掉大部分偶发误报。问题五推理偶尔超时。检查是不是有中断打断了推理或者 DMA 和 CPU 抢总线。可以把推理放在低优先级任务里或者用双缓冲一个缓冲区采样时另一个跑推理。问题六功耗比预期高。用电流表测一下各个阶段的电流通常是某个外设没关或者休眠模式没进对。MCU 的休眠有好几档选最深的那档唤醒源只留定时器。5.3 一份速查表现象可能原因排查方向分配张量失败arena 太小 / 算子不支持加大 arena检查算子注册输出恒定输入未归一化 / 量化参数错核对输入范围精度骤降校准数据无代表性重选校准集现场误报多数据分布偏移现场数据微调加确认机制推理超时中断干扰 / 总线竞争调整任务优先级双缓冲功耗偏高外设未关 / 休眠档位浅逐项测电流选深休眠6. 几个容易被忽略的实操心得做这个方向几年有些经验是文档里不会写的但实际项目里特别值钱。第一别迷信模型准确率。传感器任务里一个 90% 准确率但稳定的模型比 95% 但偶尔抽风的模型有用得多。工业场景里误报的代价往往比漏报还高因为误报多了工人就不信了。第二留好升级通道。模型是要迭代的现场数据采回来重新训练是常态。设计的时候把模型数据放在单独的 Flash 区域留个接口能通过串口或者无线更新别把模型烧死在代码里。第三推理结果要带置信度。TFLite 输出的 softmax 值可以当置信度用低于阈值的就丢弃或者标记为不确定别硬报。这个在异常检测里特别重要因为异常样本本来就少模型容易过度自信。第四采样和推理的时钟要统一。我见过一个项目采样用内部 RC 振荡器推理用外部晶振时间长了窗口对不齐数据错位模型表现忽好忽坏。统一时钟源或者用硬件定时器触发采样。第五测试要覆盖边界工况。传感器在低温、高温、电压偏低时的表现可能完全不同。我一般会在高低温箱里跑一遍确认模型和硬件都扛得住。这套东西说到底核心就一句话让模型去适应硬件和数据而不是反过来。嵌入式 AI 在传感器上的价值不在于模型多先进而在于它能不能在几块钱的芯片上、在电池供电的条件下、在嘈杂的现场环境里稳定地做出一个够用的判断。把这件事做扎实比追新模型有意义得多。