嵌入式面试真题第 04 题:资源受限设备中的低功耗短时事件识别架构

问题
在一款资源受限的嵌入式产品中,业务希望通过一个低成本、低维度、低功耗传感器识别某类短时用户意图或异常事件,例如敲击外壳、碰撞、低功耗唤醒、防拆振动、佩戴交互或机械冲击。但硬件受成本、体积和功耗限制,不能增加更高维度传感器、专用 DSP 或复杂边缘 AI 芯片。
这类事件通常持续时间很短,背景干扰又很多。例如跑步、咀嚼、走路、跌落轻碰、桌面摩擦、线缆拉扯或结构共振,都可能在传感器上产生相似波形。你会如何在 MCU 上设计一套极低功耗的短时事件识别算法,使系统尽量降低误触和漏检,并把“完美屏蔽干扰”这类不可验证需求转化为可落地的工程指标?
具体到本题,目标事件可以实例化为“使用普通单轴加速度计识别双击设备外壳接听电话”。
回答
结论:这类问题不能抽象成“某个传感器值超过固定阈值就触发事件”。更合理的通用设计是“低功耗粗筛 + 短窗口精采样 + 轻量信号处理 + 特征提取 + 状态机/小分类器确认 + 干扰抑制 + 业务门控 + 置信度输出”的事件识别管线。
这类问题的关键不是追求一个孤立算法,而是把传感器信息量、MCU 算力、功耗预算、目标事件时序、干扰分布和业务触发范围一起设计。低维传感器只能观测真实世界事件的一部分投影。如果干扰事件在该观测维度上的短时波形与目标事件足够相似,算法没有额外信息可用于数学意义上的完美区分。因此工程回答必须明确边界:可以通过多级过滤和业务约束把误触率压到可接受范围,但不能承诺“完美屏蔽”。
推荐的通用实现步骤如下。
1. 低功耗粗筛:传感器或外设长期工作在低功耗监听模式,只检测粗阈值、活动变化、边沿、能量突增或 wake-on-motion。MCU 大部分时间休眠。 2. 短窗口精采样:粗筛触发后,MCU 在很短时间内提高采样率,抓取目标事件前后波形,而不是持续高频采样。 3. 预处理与特征提取:对窗口数据做去直流、去慢变、限幅、高通/带通或滑动能量计算,再提取峰值、峰宽、能量、频带比例、过零率、衰减时间、事件间隔和持续时间。 4. 状态机或小分类器确认:用时序状态机确认“候选事件是否符合目标事件结构”;数据足够时,可用小型逻辑回归、决策树或查表分类器替代部分人工规则。 5. 干扰抑制:识别持续性、周期性、低频占比高、峰数量异常、衰减过慢或背景活动过强的干扰窗口,并拒绝触发。 6. 自适应阈值:根据背景噪声、安装差异、用户使用方式和运动状态动态更新基线,使用 baseline + margin,不要依赖全场景固定阈值。7. 业务门控:只在业务允许的状态下打开高灵敏识别;非目标业务状态下降低灵敏度、延长冷却时间或关闭该识别路径。 8. 指标化验收:把“完美屏蔽”改写为检出率、误触率、唤醒频率、平均功耗、响应延迟和边界场景覆盖率。
一句话概括:低功耗外设负责粗筛,MCU 只在短窗口内做精筛,状态机约束事件时序,干扰模型拒绝高风险样本,业务状态限制触发范围,最终输出置信度而不是绝对真值。
本题如何落回单轴双击识别
如果把上述通用问题实例化为“单轴加速度计双击接听电话”,各模块可以对应如下。
Idle -> FirstTap -> WaitSecondTap -> Confirm/Reject | |
因此,原题不是单纯考“单轴加速度计怎么识别双击”,而是在考“低成本传感器 + 低功耗 MCU + 强干扰场景下,如何设计一个可验收的事件识别系统”。
总体架构
这个架构里,低功耗传感器中断只是候选事件入口,不直接等于双击事件。MCU 被唤醒后也不应长时间连续采样,而是只采一段足够覆盖敲击波形和第二击等待窗口的数据。真正的双击判断由短窗口波形特征、状态机、干扰抑制和业务上下文共同完成。
通用机制与芯片/开源实现的对应关系
很多三轴加速度计已经内置 tap/double tap、活动检测、FIFO 或自动低功耗切换功能;本题的限制是“最普通的单轴传感器”,所以要在 MCU 上软件化实现类似能力。参考这些芯片特性不是为了假设硬件已经具备功能,而是为了理解成熟实现通常会同时配置阈值、静默时间、最大双击间隔、唤醒中断和功耗状态切换。
低功耗入口如何设计
平时系统应处于粗筛状态,而不是一直高频采样。
低功耗入口建议分成三层。
传感器如果支持活动/非活动联动,可以让传感器在低功耗模式下检测活动,并通过中断唤醒 MCU。若传感器只提供最简单的模拟或数字数据输出,没有活动中断能力,则需要用更低频的 RTC 周期采样做粗筛,但功耗会更高,响应也会更差。
采样窗口如何设计
敲击外壳通常是短时冲击响应。它的典型表现不是持续大幅运动,而是一个陡峭峰值后接快速衰减的振铃。因此采样窗口要覆盖峰值、峰宽、衰减和双击间隔。
建议参数如下,实际需要按产品结构、传感器安装位置和外壳材料实测调整。
短窗口策略的功耗优势在于:高频采样不是常态,而是中断后的短时行为。平均功耗可以用以下方式估算:
I_avg = I_sensor_lp + N_wake_per_s * (I_sensor_hr * T_capture + I_mcu_active * T_compute) + I_sleep_leakage其中 N_wake_per_s 是每秒候选唤醒次数。误唤醒越多,平均功耗越高,所以粗筛阈值不能过低。粗筛阈值的目标不是尽量灵敏,而是在漏检和唤醒频率之间取得平衡。
预处理与特征提取
单轴数据可以记为 x[n]。预处理目标是去掉静态重力投影、佩戴姿态慢变和低频运动,只保留敲击瞬态。
推荐处理顺序如下。
raw x[n] -> 去直流/慢变基线 -> 高通或带通滤波 -> 限幅与异常点处理 -> 峰值检测 -> 特征计算一个低成本高通可以用一阶 IIR 实现:
baseline[n] = baseline[n-1] + alpha * (x[n] - baseline[n-1])x_hp[n] = x[n] - baseline[n]其中 alpha 要足够小,使 baseline 跟踪姿态和慢变运动,而不吞掉敲击瞬态。若 MCU 有足够余量,也可以用短阶 FIR/IIR 带通,把低频步态和高频噪声压掉。
建议提取以下特征。
peak_abs | ||
peak_width | ||
energy_short | ||
energy_low_ratio | ||
zero_cross_rate | ||
decay_time | ||
peak_count | ||
inter_tap_gap |
不要用单一峰值阈值替代这些特征。单轴传感器在跑步落地、线缆碰撞、牙齿咬合或外壳刮擦时都可能出现大峰值;峰形、时序和上下文比峰值本身更重要。
单击候选如何判定
单击候选可以用硬门限加评分的方式判断。硬门限用于快速拒绝明显不符合的波形,评分用于处理边界样本。
is_tap_candidate = peak_abs >= tap_peak_th && peak_width <= tap_width_max && energy_short >= tap_energy_th && decay_time <= tap_decay_max && low_ratio <= low_ratio_max && peak_count <= peak_count_max然后再计算置信度:
score = w1 * norm_peak + w2 * norm_energy + w3 * norm_decay + w4 * norm_zcr - w5 * norm_low_ratio - w6 * norm_periodic_score如果产品没有足够训练数据,优先使用规则状态机,不要一开始就上复杂模型。等产测和用户测试积累了足够样本后,可以把规则特征输入到一个很小的逻辑回归、决策树或查表分类器中。低功耗 MCU 上不建议把问题一开始就设计成大模型推理。
双击状态机如何设计
双击不是两个峰值过阈值这么简单。第一击后需要有静默约束,第二击需要落在合理间隔内,并且两次峰形都要像敲击。
建议状态参数如下。
tap_width_max | ||
quiet_min | ||
gap_min | ||
gap_max | ||
score_confirm_th | ||
refractory_ms |
状态机必须把 reject 原因记录下来,例如 REJECT_TOO_LONG、REJECT_PERIODIC、REJECT_LOW_FREQ、REJECT_CONTEXT、REJECT_TIMEOUT。这些原因对后续调参非常重要,否则现场误触只能看到一个失败结果,无法定位是阈值、状态机还是业务门控问题。
如何抑制跑步误触
跑步误触的典型问题是周期性冲击。落地冲击可能在单轴上产生很高峰值,但跑步不是孤立双击,而是连续、周期性、持续时间较长的振动序列。
抑制策略如下。
motion_suppress。 | ||
energy_low_ratio | ||
peak_count | ||
工程上可以维护一个活动评分:
motion_score = a * low_freq_energy + b * periodic_peak_score + c * continuous_energy_time + d * wake_frequency当 motion_score 高于阈值时,不是直接永久关闭识别,而是进入抑制状态:提高 tap_peak_th、缩短等待窗口、要求更高静默质量,或者仅在来电前几秒内开启识别。
如何抑制咀嚼误触
咀嚼误触在耳机、眼镜、头戴或贴近头部的设备上更常见。咀嚼的振动可能沿结构传到外壳,单轴上也可能出现明显峰值。但咀嚼通常具有持续性和节律性,不像两次孤立敲击后快速静默。
抑制策略如下。
peak_count | ||
peak_width、decay_time 和峰后静默。 | ||
需要注意,咀嚼和轻敲在某些结构上可能高度相似。单轴加速度计无法可靠识别“用户意图”,只能识别波形模式。因此文档、需求评审和测试报告里不要写“完全屏蔽咀嚼”,应写“在定义测试集和业务场景下,误触率低于目标阈值”。
自适应阈值如何做
固定阈值的问题是样机、量产机、佩戴松紧、结构胶、外壳材料和个体习惯都会改变波形幅值。阈值应随背景噪声和场景调整。
建议维护以下统计量。
noise_floor = 背景高通能量的滑动估计peak_baseline = 非触发窗口峰值的分位数估计wake_rate = 单位时间粗筛唤醒次数motion_score = 当前运动干扰评分user_sensitivity = 用户或产品档位阈值可以写成:
tap_peak_th = max(factory_min_peak, peak_baseline + k1 * noise_floor + k2 * motion_score)tap_energy_th = max(factory_min_energy, energy_baseline + k3 * noise_floor)score_th = base_score_th + k4 * motion_score自适应要有两个限制。
1. 只在非候选敲击窗口更新背景,避免把真正敲击学习成噪声。 2. 设置上下限,避免阈值越调越高导致漏检,或越调越低导致误触。
如果业务允许,可以把灵敏度分成高、中、低三档。来电态用中高灵敏度,运动态用低灵敏度,非电话态关闭或只保留很粗的事件记录。
业务门控必须参与识别
双击接听电话不是通用常开手势,而是强业务相关事件。业务门控越严格,误触越容易控制。
推荐门控条件如下。
很多误触不是算法本身完全解决的,而是靠业务状态降低损失。例如用户跑步时没有来电,算法即使检测到疑似双击,也不应触发接听动作。把手势限定在“来电可接听”这一窄场景,误触风险会显著下降。
MCU 实现建议
MCU 上建议使用定点实现,避免浮点和复杂频域计算。短窗口样本数很少,规则特征足够高效。
数据结构
#define TAP_MAX_SAMPLES 256U#define TAP_FEATURE_Q 15typedefenum { TAP_STATE_IDLE = 0, TAP_STATE_FIRST_TAP, TAP_STATE_WAIT_SECOND, TAP_STATE_CONFIRMED, TAP_STATE_REFRACTORY,} tap_state_t;typedefstruct {int16_t peak_abs;uint16_t peak_width_ms;uint32_t energy_short;uint16_t zero_cross_count;uint16_t decay_time_ms;uint16_t peak_count;uint16_t low_energy_ratio_q15;uint16_t score_q15;} tap_feature_t;typedefstruct {tap_state_t state;uint32_t first_tap_time_ms;uint32_t refractory_until_ms;int32_t baseline;uint32_t noise_floor;uint16_t motion_score_q15;} tap_detector_t;处理流程
accel_irq_handler() -> 记录唤醒时间 -> 启动高频采样定时器或传感器高 ODR -> 采满短窗口后投递 TAP_PROCESS 事件tap_process_window(samples) -> preprocess() -> extract_feature() -> update_motion_score() -> tap_state_machine() -> 输出 NONE / DOUBLE_TAP -> 恢复低功耗监听计算复杂度
若窗口为 256 点,每点只做一阶滤波、能量累加、峰值检测和少量比较,则一次识别通常是 O(N) 复杂度。对 Cortex-M0/M3/M4 这类 MCU 来说,这比持续 FFT 或神经网络推理更适合低功耗场景。
参数如何量化
参数不能只凭感觉设置,应先由产品目标反推。
P_false_target = 允许误触率,例如每用户每天小于 1 次P_miss_target = 允许漏检率,例如标准敲击样本检出率大于 95%T_response = 用户可接受响应延迟,例如小于 500msI_budget = 常驻平均电流预算然后建立测试集。
评价指标至少包括检出率、误触率、唤醒频率、平均功耗和响应延迟。只看识别准确率是不够的,因为低功耗识别系统的失败可能表现为功耗超标、响应慢或频繁误唤醒。
为什么不能承诺完美屏蔽
原因很直接:单轴传感器只输出一个方向上的加速度投影,它没有三维方向信息,也没有声音、压力、电容触摸或结构应变信息。如果干扰在该轴上的时间波形与真实敲击足够接近,算法没有额外信息可用。
可以做到的是:
1. 用波形特征降低非敲击冲击误判。 2. 用状态机降低振铃和单击误判。 3. 用运动抑制降低跑步、咀嚼等持续节律振动误判。 4. 用业务门控降低误触造成业务动作的概率。 5. 用测试数据定义误触率目标,而不是承诺绝对无误触。
需求评审时应把“完美屏蔽”改写为可验证指标,例如:
在定义佩戴方式和测试动作集合下,来电态双击检出率 >= 95%;跑步、咀嚼、说话、日常走动负样本误触率 <= X 次/小时;常驻平均电流增加 <= Y uA;双击触发响应延迟 <= Z ms。这比“完美屏蔽”更适合工程验收。
调试与量产验证
建议固件保留轻量日志能力,但不要长期记录原始高频数据。量产固件可只记录特征和 reject reason。
timestampwake_reasonpeak_abspeak_width_msenergy_shortlow_energy_ratiozero_cross_countdecay_time_mspeak_countmotion_scorestatereject_reasonbusiness_context调试阶段可以通过串口、RTT、BLE debug 或离线日志导出少量原始窗口数据。量产阶段只保留统计计数,避免功耗、存储和隐私风险。
参数更新建议采用灰度策略。先在实验室和小批量用户中收集误触与漏检样本,再更新阈值表或固件参数。不要只凭单个开发板上的手敲效果就固化量产阈值。
最终回答组织方式
回答这类题时,可以按以下顺序展开:
1. 先把问题抽象为“资源受限设备中的低功耗短时事件识别”,而不是只讨论某个传感器阈值。 2. 再说明约束边界:低维传感器信息不足,不能承诺数学意义上的完美屏蔽,只能工程化降低误触率。 3. 接着讲低功耗架构:外设低功耗粗筛,MCU 短窗口精采样,避免长期高频运行。 4. 然后讲信号处理:去直流、高通/带通、峰值、峰宽、能量、频带比例、过零率和衰减时间。 5. 再讲事件确认:用状态机或小分类器约束目标事件的时序、形态和置信度。 6. 补充干扰抑制:持续性、周期性、低频占比高或背景活动过强的窗口优先拒绝。 7. 最后讲业务门控和验收指标:只在业务相关状态下启用高灵敏识别,用检出率、误触率、功耗和延迟验收。
一句话概括:这类题的通用答案不是“某个动作怎么判”,而是“如何用弱传感器在强约束下构建一条低功耗、可解释、可调参、可验收的短时事件识别管线”;单轴双击接听电话只是这个框架下的一个具体实例。
参考链接
• Analog Devices ADXL362 Datasheet[1] • Bosch Sensortec BMA400 Datasheet[2] • STMicroelectronics LIS2DW12 Datasheet[3] • Arm CMSIS-DSP FIR filter documentation[4]
引用链接
[1] Analog Devices ADXL362 Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/adxl362.pdf[2] Bosch Sensortec BMA400 Datasheet: https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bma400-ds000.pdf[3] STMicroelectronics LIS2DW12 Datasheet: https://www.st.com/resource/en/datasheet/lis2dw12.pdf[4] Arm CMSIS-DSP FIR filter documentation: https://arm-software.github.io/CMSIS-DSP/latest/group__FIR.html
夜雨聆风