嵌入式面试真题第 04 题:资源受限设备中的低功耗短时事件识别架构
问题
在一款资源受限的嵌入式产品中,业务希望通过一个低成本、低维度、低功耗传感器识别某类短时用户意图或异常事件,例如敲击外壳、碰撞、低功耗唤醒、防拆振动、佩戴交互或机械冲击。但硬件受成本、体积和功耗限制,不能增加更高维度传感器、专用 DSP 或复杂边缘 AI 芯片。
这类事件通常持续时间很短,背景干扰又很多。例如跑步、咀嚼、走路、跌落轻碰、桌面摩擦、线缆拉扯或结构共振,都可能在传感器上产生相似波形。你会如何在 MCU 上设计一套极低功耗的短时事件识别算法,使系统尽量降低误触和漏检,并把“完美屏蔽干扰”这类不可验证需求转化为可落地的工程指标?
具体到本题,目标事件可以实例化为“使用普通单轴加速度计识别双击设备外壳接听电话”。
回答
结论:这类问题不能抽象成“某个传感器值超过固定阈值就触发事件”。更合理的通用设计是“低功耗粗筛 + 短窗口精采样 + 轻量信号处理 + 特征提取 + 状态机/小分类器确认 + 干扰抑制 + 业务门控 + 置信度输出”的事件识别管线。
这类问题的关键不是追求一个孤立算法,而是把传感器信息量、MCU 算力、功耗预算、目标事件时序、干扰分布和业务触发范围一起设计。低维传感器只能观测真实世界事件的一部分投影。如果干扰事件在该观测维度上的短时波形与目标事件足够相似,算法没有额外信息可用于数学意义上的完美区分。因此工程回答必须明确边界:可以通过多级过滤和业务约束把误触率压到可接受范围,但不能承诺“完美屏蔽”。
推荐的通用实现步骤如下。
- 低功耗粗筛:传感器或外设长期工作在低功耗监听模式,只检测粗阈值、活动变化、边沿、能量突增或 wake-on-motion。MCU 大部分时间休眠。
- 短窗口精采样:粗筛触发后,MCU 在很短时间内提高采样率,抓取目标事件前后波形,而不是持续高频采样。
- 预处理与特征提取:对窗口数据做去直流、去慢变、限幅、高通/带通或滑动能量计算,再提取峰值、峰宽、能量、频带比例、过零率、衰减时间、事件间隔和持续时间。
- 状态机或小分类器确认:用时序状态机确认“候选事件是否符合目标事件结构”;数据足够时,可用小型逻辑回归、决策树或查表分类器替代部分人工规则。
- 干扰抑制:识别持续性、周期性、低频占比高、峰数量异常、衰减过慢或背景活动过强的干扰窗口,并拒绝触发。
- 自适应阈值:根据背景噪声、安装差异、用户使用方式和运动状态动态更新基线,使用
baseline + margin,不要依赖全场景固定阈值。 - 业务门控:只在业务允许的状态下打开高灵敏识别;非目标业务状态下降低灵敏度、延长冷却时间或关闭该识别路径。
- 指标化验收:把“完美屏蔽”改写为检出率、误触率、唤醒频率、平均功耗、响应延迟和边界场景覆盖率。
一句话概括:低功耗外设负责粗筛,MCU 只在短窗口内做精筛,状态机约束事件时序,干扰模型拒绝高风险样本,业务状态限制触发范围,最终输出置信度而不是绝对真值。
本题如何落回单轴双击识别
如果把上述通用问题实例化为“单轴加速度计双击接听电话”,各模块可以对应如下。
| 通用模块 | 单轴双击识别中的落地方式 |
|---|---|
| 低功耗粗筛 | 加速度计低功耗阈值中断或 wake-on-motion 唤醒 MCU。 |
| 短窗口精采样 | 中断后临时提高 ODR,采集 100ms 到 300ms 的冲击波形。 |
| 特征提取 | 计算峰值、峰宽、短时能量、过零率、衰减时间、峰间隔和峰数量。 |
| 状态机确认 | Idle -> FirstTap -> WaitSecondTap -> Confirm/Reject,第二击必须落在合理时间窗内。 |
| 干扰抑制 | 跑步看周期性、低频能量和持续时间;咀嚼看节律、连续峰数量和背景活动强度。 |
| 自适应阈值 | 根据佩戴松紧、外壳结构、环境噪声和运动评分更新触发阈值。 |
| 业务门控 | 只在来电或可接听状态下启用高灵敏双击识别;运动模式或非电话场景降敏。 |
| 验收指标 | 用双击检出率、跑步/咀嚼误触率、平均电流和响应延迟验收,而不是承诺绝对无误触。 |
因此,原题不是单纯考“单轴加速度计怎么识别双击”,而是在考“低成本传感器 + 低功耗 MCU + 强干扰场景下,如何设计一个可验收的事件识别系统”。
总体架构
1 | flowchart LR |
这个架构里,低功耗传感器中断只是候选事件入口,不直接等于双击事件。MCU 被唤醒后也不应长时间连续采样,而是只采一段足够覆盖敲击波形和第二击等待窗口的数据。真正的双击判断由短窗口波形特征、状态机、干扰抑制和业务上下文共同完成。
通用机制与芯片/开源实现的对应关系
| 通用机制 | 可参考机制 | 能否直接使用 | 主要参考价值 |
|---|---|---|---|
| 低功耗唤醒 | 活动检测、wake-up interrupt、wake-on-motion | 如果传感器支持可直接使用;普通单轴传感器至少要用阈值中断 | 让 MCU 长时间休眠,只在候选振动出现时唤醒。 |
| 短窗口采样 | 传感器高 ODR、FIFO、数据就绪中断 | 取决于具体传感器;没有 FIFO 时由 MCU 定时采样 | 中断后临时提高采样率,避免长期高功耗。 |
| 单/双击时序 | tap threshold、quiet time、latency window | 高端加速度计可能内置;普通单轴传感器需要 MCU 实现 | 双击不是两个过阈值点,而是峰形、静默时间和第二击窗口组合。 |
| 轻量滤波 | IIR/FIR、高通、滑动能量、峰值检测 | MCU 上直接实现;Cortex-M 可参考 CMSIS-DSP | 去除姿态慢变和低频运动,只保留敲击相关瞬态。 |
| 干扰抑制 | 活动识别、步态周期、连续振动检测 | 单轴上只能近似实现 | 跑步和咀嚼多为持续性或周期性振动,不能只看瞬时峰值。 |
| 业务门控 | 来电态、佩戴态、运动态、冷却时间 | 必须结合产品业务实现 | 把算法工作范围限制到真正需要触发的场景。 |
很多三轴加速度计已经内置 tap/double tap、活动检测、FIFO 或自动低功耗切换功能;本题的限制是“最普通的单轴传感器”,所以要在 MCU 上软件化实现类似能力。参考这些芯片特性不是为了假设硬件已经具备功能,而是为了理解成熟实现通常会同时配置阈值、静默时间、最大双击间隔、唤醒中断和功耗状态切换。
低功耗入口如何设计
平时系统应处于粗筛状态,而不是一直高频采样。
1 | stateDiagram-v2 |
低功耗入口建议分成三层。
| 层级 | 动作 | 目的 |
|---|---|---|
| 传感器低功耗层 | 配置低 ODR、阈值中断、活动检测或 wake-on-motion | 让传感器承担最低成本的粗筛。 |
| MCU 睡眠层 | MCU 进入 Stop/Standby/Light Sleep,只保留 GPIO/EXTI/RTC | 降低常驻功耗。 |
| 临时精筛层 | 中断后提高采样率并开启短窗口算法 | 只在候选事件出现后消耗算力。 |
传感器如果支持活动/非活动联动,可以让传感器在低功耗模式下检测活动,并通过中断唤醒 MCU。若传感器只提供最简单的模拟或数字数据输出,没有活动中断能力,则需要用更低频的 RTC 周期采样做粗筛,但功耗会更高,响应也会更差。
采样窗口如何设计
敲击外壳通常是短时冲击响应。它的典型表现不是持续大幅运动,而是一个陡峭峰值后接快速衰减的振铃。因此采样窗口要覆盖峰值、峰宽、衰减和双击间隔。
建议参数如下,实际需要按产品结构、传感器安装位置和外壳材料实测调整。
| 参数 | 建议范围 | 说明 |
|---|---|---|
| 粗筛 ODR | 6Hz ~ 50Hz | 只用于唤醒候选事件,越低越省电但越容易错过短冲击。 |
| 精筛 ODR | 200Hz ~ 1000Hz | 覆盖敲击瞬态和振铃;外壳刚性越强,所需频率越高。 |
| 单击分析窗口 | 40ms ~ 120ms | 判断峰值、峰宽、衰减和静默时间。 |
| 双击等待窗口 | 80ms ~ 350ms | 第二击太近可能是一击振铃,太远用户感知不像双击。 |
| 冷却时间 | 500ms ~ 1500ms | 防止同一次动作或连续振动重复触发。 |
短窗口策略的功耗优势在于:高频采样不是常态,而是中断后的短时行为。平均功耗可以用以下方式估算:
1 | I_avg = I_sensor_lp |
其中 N_wake_per_s 是每秒候选唤醒次数。误唤醒越多,平均功耗越高,所以粗筛阈值不能过低。粗筛阈值的目标不是尽量灵敏,而是在漏检和唤醒频率之间取得平衡。
预处理与特征提取
单轴数据可以记为 x[n]。预处理目标是去掉静态重力投影、佩戴姿态慢变和低频运动,只保留敲击瞬态。
推荐处理顺序如下。
1 | raw x[n] |
一个低成本高通可以用一阶 IIR 实现:
1 | baseline[n] = baseline[n-1] + alpha * (x[n] - baseline[n-1]) |
其中 alpha 要足够小,使 baseline 跟踪姿态和慢变运动,而不吞掉敲击瞬态。若 MCU 有足够余量,也可以用短阶 FIR/IIR 带通,把低频步态和高频噪声压掉。
建议提取以下特征。
| 特征 | 含义 | 对误触抑制的价值 |
|---|---|---|
peak_abs |
窗口内最大绝对峰值 | 粗略判断是否有冲击。 |
peak_width |
超过阈值的持续时间 | 敲击通常窄;挤压、晃动通常宽。 |
energy_short |
短窗口能量 | 判断冲击强度。 |
energy_low_ratio |
低频能量占比 | 跑步和晃动低频占比通常更高。 |
zero_cross_rate |
过零次数或符号翻转次数 | 敲击振铃可能更明显;慢变运动较少。 |
decay_time |
峰后能量衰减时间 | 外壳敲击通常快速衰减;持续振动衰减慢。 |
peak_count |
时间窗内候选峰数量 | 跑步、咀嚼可能出现连续节律峰。 |
inter_tap_gap |
两次敲击间隔 | 双击必须落在合理时间窗内。 |
不要用单一峰值阈值替代这些特征。单轴传感器在跑步落地、线缆碰撞、牙齿咬合或外壳刮擦时都可能出现大峰值;峰形、时序和上下文比峰值本身更重要。
单击候选如何判定
单击候选可以用硬门限加评分的方式判断。硬门限用于快速拒绝明显不符合的波形,评分用于处理边界样本。
1 | is_tap_candidate = |
然后再计算置信度:
1 | score = w1 * norm_peak |
如果产品没有足够训练数据,优先使用规则状态机,不要一开始就上复杂模型。等产测和用户测试积累了足够样本后,可以把规则特征输入到一个很小的逻辑回归、决策树或查表分类器中。低功耗 MCU 上不建议把问题一开始就设计成大模型推理。
双击状态机如何设计
双击不是两个峰值过阈值这么简单。第一击后需要有静默约束,第二击需要落在合理间隔内,并且两次峰形都要像敲击。
1 | stateDiagram-v2 |
建议状态参数如下。
| 参数 | 典型范围 | 作用 |
|---|---|---|
tap_width_max |
10ms ~ 60ms | 限制单击候选的冲击持续时间。 |
quiet_min |
30ms ~ 80ms | 第一击后必须有短静默,避免把振铃当第二击。 |
gap_min |
80ms ~ 120ms | 第二击不能太近。 |
gap_max |
250ms ~ 450ms | 第二击不能太远。 |
score_confirm_th |
按实测标定 | 双击确认阈值。 |
refractory_ms |
500ms ~ 1500ms | 触发后冷却,避免重复识别。 |
状态机必须把 reject 原因记录下来,例如 REJECT_TOO_LONG、REJECT_PERIODIC、REJECT_LOW_FREQ、REJECT_CONTEXT、REJECT_TIMEOUT。这些原因对后续调参非常重要,否则现场误触只能看到一个失败结果,无法定位是阈值、状态机还是业务门控问题。
如何抑制跑步误触
跑步误触的典型问题是周期性冲击。落地冲击可能在单轴上产生很高峰值,但跑步不是孤立双击,而是连续、周期性、持续时间较长的振动序列。
抑制策略如下。
| 检测项 | 跑步特征 | 拒绝策略 |
|---|---|---|
| 周期性 | 300ms ~ 900ms 左右重复出现峰值,具体与步频有关 | 维护 1s ~ 3s 活动窗口,若峰值周期稳定则提高阈值或禁用双击。 |
| 持续能量 | 能量不是一次快速衰减,而是持续存在 | 若连续多个窗口能量高于背景,进入 motion_suppress。 |
| 低频占比 | 步态低频成分更强 | energy_low_ratio 超阈值时拒绝。 |
| 峰数量 | 一个等待窗口内可能出现多个非敲击峰 | peak_count 超过上限时拒绝。 |
| 业务状态 | 跑步模式、运动检测、用户正在移动 | 由业务状态提高门槛或关闭该手势。 |
工程上可以维护一个活动评分:
1 | motion_score = a * low_freq_energy |
当 motion_score 高于阈值时,不是直接永久关闭识别,而是进入抑制状态:提高 tap_peak_th、缩短等待窗口、要求更高静默质量,或者仅在来电前几秒内开启识别。
如何抑制咀嚼误触
咀嚼误触在耳机、眼镜、头戴或贴近头部的设备上更常见。咀嚼的振动可能沿结构传到外壳,单轴上也可能出现明显峰值。但咀嚼通常具有持续性和节律性,不像两次孤立敲击后快速静默。
抑制策略如下。
| 检测项 | 咀嚼特征 | 拒绝策略 |
|---|---|---|
| 持续时间 | 往往持续数秒,而不是 300ms 内结束 | 连续活动时间超过阈值时进入抑制。 |
| 节律性 | 多个相似峰按节律出现 | peak_count 和周期稳定性超阈值时拒绝。 |
| 峰形 | 可能较宽、衰减慢,或伴随多个小峰 | 限制 peak_width、decay_time 和峰后静默。 |
| 触发上下文 | 非来电状态下误触价值低 | 非电话可接听状态关闭高灵敏度识别。 |
需要注意,咀嚼和轻敲在某些结构上可能高度相似。单轴加速度计无法可靠识别“用户意图”,只能识别波形模式。因此文档、需求评审和测试报告里不要写“完全屏蔽咀嚼”,应写“在定义测试集和业务场景下,误触率低于目标阈值”。
自适应阈值如何做
固定阈值的问题是样机、量产机、佩戴松紧、结构胶、外壳材料和个体习惯都会改变波形幅值。阈值应随背景噪声和场景调整。
建议维护以下统计量。
1 | noise_floor = 背景高通能量的滑动估计 |
阈值可以写成:
1 | tap_peak_th = max(factory_min_peak, peak_baseline + k1 * noise_floor + k2 * motion_score) |
自适应要有两个限制。
- 只在非候选敲击窗口更新背景,避免把真正敲击学习成噪声。
- 设置上下限,避免阈值越调越高导致漏检,或越调越低导致误触。
如果业务允许,可以把灵敏度分成高、中、低三档。来电态用中高灵敏度,运动态用低灵敏度,非电话态关闭或只保留很粗的事件记录。
业务门控必须参与识别
双击接听电话不是通用常开手势,而是强业务相关事件。业务门控越严格,误触越容易控制。
推荐门控条件如下。
| 业务状态 | 策略 |
|---|---|
| 无来电、非通话、非可接听 | 不输出接听事件;可不启用高灵敏度识别。 |
| 来电响铃 | 开启高灵敏度双击识别。 |
| 已接通通话 | 根据产品定义切换为挂断、静音或关闭该手势。 |
| 音乐播放 | 若双击已有其他语义,避免复用造成冲突。 |
| 运动模式或高活动评分 | 提高阈值,要求更严格静默,必要时关闭。 |
| 刚触发过事件 | 进入 refractory 时间,不重复输出。 |
很多误触不是算法本身完全解决的,而是靠业务状态降低损失。例如用户跑步时没有来电,算法即使检测到疑似双击,也不应触发接听动作。把手势限定在“来电可接听”这一窄场景,误触风险会显著下降。
MCU 实现建议
MCU 上建议使用定点实现,避免浮点和复杂频域计算。短窗口样本数很少,规则特征足够高效。
数据结构
1 |
|
处理流程
1 | accel_irq_handler() |
计算复杂度
若窗口为 256 点,每点只做一阶滤波、能量累加、峰值检测和少量比较,则一次识别通常是 O(N) 复杂度。对 Cortex-M0/M3/M4 这类 MCU 来说,这比持续 FFT 或神经网络推理更适合低功耗场景。
参数如何量化
参数不能只凭感觉设置,应先由产品目标反推。
1 | P_false_target = 允许误触率,例如每用户每天小于 1 次 |
然后建立测试集。
| 数据集 | 内容 | 用途 |
|---|---|---|
| 正样本 | 不同用户、不同力度、不同位置、不同佩戴状态下的双击 | 标定检出率和双击时间窗。 |
| 跑步负样本 | 慢跑、快跑、上下楼、跳跃、手持晃动 | 标定运动抑制策略。 |
| 咀嚼负样本 | 轻咀嚼、用力咀嚼、说话、大笑、头部动作 | 标定持续节律干扰。 |
| 结构干扰 | 桌面碰撞、外壳摩擦、线缆拉扯、跌落轻碰 | 标定峰宽、衰减和冷却时间。 |
| 业务场景 | 来电、非来电、通话中、音乐中、运动模式 | 验证业务门控。 |
评价指标至少包括检出率、误触率、唤醒频率、平均功耗和响应延迟。只看识别准确率是不够的,因为低功耗识别系统的失败可能表现为功耗超标、响应慢或频繁误唤醒。
为什么不能承诺完美屏蔽
原因很直接:单轴传感器只输出一个方向上的加速度投影,它没有三维方向信息,也没有声音、压力、电容触摸或结构应变信息。如果干扰在该轴上的时间波形与真实敲击足够接近,算法没有额外信息可用。
可以做到的是:
- 用波形特征降低非敲击冲击误判。
- 用状态机降低振铃和单击误判。
- 用运动抑制降低跑步、咀嚼等持续节律振动误判。
- 用业务门控降低误触造成业务动作的概率。
- 用测试数据定义误触率目标,而不是承诺绝对无误触。
需求评审时应把“完美屏蔽”改写为可验证指标,例如:
1 | 在定义佩戴方式和测试动作集合下,来电态双击检出率 >= 95%; |
这比“完美屏蔽”更适合工程验收。
调试与量产验证
建议固件保留轻量日志能力,但不要长期记录原始高频数据。量产固件可只记录特征和 reject reason。
1 | timestamp |
调试阶段可以通过串口、RTT、BLE debug 或离线日志导出少量原始窗口数据。量产阶段只保留统计计数,避免功耗、存储和隐私风险。
参数更新建议采用灰度策略。先在实验室和小批量用户中收集误触与漏检样本,再更新阈值表或固件参数。不要只凭单个开发板上的手敲效果就固化量产阈值。
最终回答组织方式
回答这类题时,可以按以下顺序展开:
- 先把问题抽象为“资源受限设备中的低功耗短时事件识别”,而不是只讨论某个传感器阈值。
- 再说明约束边界:低维传感器信息不足,不能承诺数学意义上的完美屏蔽,只能工程化降低误触率。
- 接着讲低功耗架构:外设低功耗粗筛,MCU 短窗口精采样,避免长期高频运行。
- 然后讲信号处理:去直流、高通/带通、峰值、峰宽、能量、频带比例、过零率和衰减时间。
- 再讲事件确认:用状态机或小分类器约束目标事件的时序、形态和置信度。
- 补充干扰抑制:持续性、周期性、低频占比高或背景活动过强的窗口优先拒绝。
- 最后讲业务门控和验收指标:只在业务相关状态下启用高灵敏识别,用检出率、误触率、功耗和延迟验收。
一句话概括:这类题的通用答案不是“某个动作怎么判”,而是“如何用弱传感器在强约束下构建一条低功耗、可解释、可调参、可验收的短时事件识别管线”;单轴双击接听电话只是这个框架下的一个具体实例。








