问题出现在模型之前
电机正在振动,一个小设备尝试识别异常。系统记录到 300 赫兹峰值,也就是每秒三百次振荡。能因此断定电机真的存在这种振动吗?未必:采样不合适时,700 赫兹分量可能留下完全相同的数字轨迹。如果没有其他信息,即使非常准确的 AI 模型也无法区分以同样数字呈现的两种原因。
本文的问题是:把物理信号送入嵌入式系统,也就是集成在设备中的计算机时,如何保留有用信息?我们从两条简单波形开始,证明它们为何变得无法区分,再构造一个在减少样本之前使用的滤波器。同时考察代价:延迟、内存和运算。所有信号及数值结果均为合成、可复现的内容;没有测量电机、开发板或 EL-AI 产品。
采样意味着隔一段时间看一次
加速度计可以产生随时间变化的信号。模数转换器,常缩写为 ADC,将它表示为离散时刻采集的数字。若采样率 f_s 为每秒 1,000 个样本,就是每毫秒观察一次。两次观察之间发生的事情没有被直接保留。问题不仅是每个数字有多少位:即使数字无限精确,观察过于稀疏也会让动态过程的描述产生歧义。
为隔离这一现象,使用单位幅度、初相位为零的余弦振荡。频率 f 表示每秒周期数,t 是秒为单位的时间,n 是整数样本索引。代入 t = n/f_s,就只在可用时刻计算波形。这里圆括号表示连续时间,方括号表示数字序列;它们不改变传感器物理,只明确我们在观察什么。
两种频率,同一序列
令 f_s = 1,000 Hz,比较 f = 700 Hz 与 f = 300 Hz。一毫秒内,第一条波走 0.7 圈,第二条走 0.3 圈。余弦对正负相反的角度取相同值,加上整数圈也不改变结果。正是这两个性质,而不是软件缺陷,让样本相同。下面的推导对每个整数 n 都成立,不只是图中几个点。
这就是混叠:不同物理频率在采样序列中具有同一身份。对 1,000 个样本进行数值核对,最大差约为 1.27 × 10⁻¹²,来自计算机有限精度;数学上差为零。改变初相位可能改变混叠的符号或相位,但不会消除一般性的歧义。如果引入外部假设,比如已知不存在高于 400 Hz 的频率,就能排除部分解释。然而这是额外信息,并非从这些样本恢复的信息。
f_s/2 称为奈奎斯特频率。要无混叠表示任意带限信号,最高频率必须低于该阈值;恰在边界上,某些相位会出问题。不过,“有用信号是 300 Hz”不等于“全部信号都低于 500 Hz”。超过阈值的干扰和谐波仍会进入转换器。因此真实系统也必须了解并限制那些原本不想测量的成分。
为什么事后滤波可能已经太迟
假设已经以 1 kHz 采集,再应用保留 300 Hz 的数字滤波器。它也会保留来自 700 Hz 的贡献,因为后者已经叠到同一组样本上。若去掉 300 Hz,就会一起去掉两种解释。区别一旦丢失,滤波器无法判断原来是哪一种。因此保护必须放在产生歧义的操作之前:首次采样要在 ADC 前,后续降低数字采样率也要预先处理。
本实验改为从每秒 4,000 个样本开始:300 和 700 Hz 都低于 2,000 Hz,仍可区分。随后只想给模型每秒 1,000 个样本。每四个保留一个,称为 M = 4 的抽取。不先滤波就这样做,会重现前面的问题。中间滤波器必须削弱在新采样率下会变得模糊的成分,同时保留所需频带。
构造一个可核查的滤波器
使用 FIR,即有限冲激响应滤波器:每个输出是有限个近期样本的加权和。权重 h[k] 表示每个样本的贡献。这不是训练出的神经网络,而是明确选择低通响应,保留慢一些的振荡并削弱快一些的振荡。求和公式同时说明计算和成本。L = 129 个系数时,直接求值需要 129 次乘法及相加。
第一行滤波,第二行每四个输出保留一个,m 是新序列索引。系数从理想低通的 sinc 形状开始,截取 129 个值,再用 Hann 窗平滑边缘。加窗可以减小部分响应波纹,但代价是过渡并非瞬间完成。最后将所有权重除以其总和,使恒定输入在初始瞬态结束后保持原有水平。
64 用来居中响应,它是首尾系数之间 128 个间隔的一半。f_c 是设计的截止参数,并不保证到 400 Hz 都原样通过、再往上就立刻消失。有限滤波器有过渡带。因此必须检查例子中各频率的实际响应,以及完整曲线。文末代码使用 NumPy 的归一化 sinc 定义;如果改了约定却不改公式,就会得到另一种滤波器。
结果:虚假的峰不再占主导
构造输入:有用的 300 Hz 分量幅度为 0.2,不希望出现的 700 Hz 分量幅度为 1。幅度经过归一化,不赋予实际加速度单位。不滤波就抽取,两者会重叠,使 300 Hz 峰的幅度变成 1.2。软件可能误认为有用振动比预期大了六倍。这个结果依赖所选相位,其他相位也可能使两者部分抵消。
滤波后,300 Hz 处增益为 0.998531,几乎保留全部有用分量。700 Hz 处约为 0.0000131684。以分贝表示,该特定频率的响应为 −97.61 dB;这里分贝计算是幅度比的 20 log₁₀。这不意味着整个阻带都有该衰减,曲线中不同谷值和峰值并不相同。滤波并抽取后,在合成信号中测得 300 Hz 幅度约为 0.199693,接近原来的 0.2。
| 量 | 计算值 |
|---|---|
| f_s → f_out | 4000 → 1000 Hz |
| |H(300 Hz)| | 0.998531446 |
| |H(700 Hz)| | 0.0000131684 |
| A300: x[4m] | 1.200000000 |
| A300: y[4m] | 0.199693121 |
| (L−1)/(2f_s) | 16 ms |

为让比较可核查,我们在 4 kHz 下生成 5,000 个样本,执行因果卷积,再以四为步长选取索引 256 到 4252,恰好得到 1,000 个输出。从 256 开始避开了滤波器的启动瞬态,本序列中它最多持续 128 个输入样本。对这一秒数据,用 300 Hz 正弦投影估计幅度,等价于对应的离散傅里叶变换系数。窗口包含整数个周期;这里没有研究频率不对齐引起的频谱泄漏。
隐含成本:等待与保存样本
系数对称,因此滤波器具有线性相位,在有用频带内引入 (L−1)/2 个样本的群延迟。L = 129、f_s = 4 kHz 时,即 64 个样本,也就是 16 ms。需要快速反应的识别器必须将它纳入总时间预算。这不意味着 CPU 运算需要 16 ms;信号时间延迟与处理器计算这些和所需的时间不同。
若每块处理 128 个输入,收齐一块需要 32 ms。块开头的样本比接近结尾的样本等待更久;不能把这种等待与群延迟混为一谈。此外还有传输、模型计算和可能的排队。这里没有测量设备平均延迟或百分位,只识别了设计中的两个确定性贡献。缩小块可减少收集等待,却可能增加调用和传输开销。
CMSIS-DSP FIR 抽取器文档规定:B 个输入一块时,状态需要 L + B − 1 个值。本例若使用每个四字节的 float32,状态为 1,024 字节,系数 516,输入 512,32 样本输出 128。如果四个数组都放 RAM,共 2,180 字节;若系数位于只读存储器,三个显式缓冲区则需要 1,664 字节。栈、结构体、对齐、DMA 和 AI 模型均未计入,这不是应用峰值 RAM 测量。
按直接求和只计算保留输出,每通道每秒约需 129,000 次乘累加:129 个系数乘 1,000 个输出。若先算出全部 4,000 个输出再丢掉四分之三,运算数会是四倍。运算量不等于耗时,向量指令、对称性、缓存和实现都会改变实际成本。为清晰起见,本 NumPy 实验计算完整卷积;没有在 Cortex-M 上执行 CMSIS 内核。
真实开发板上还要检查什么
首先要检查模拟通路。4 kHz 采样并不能防住所有频率,高于 2 kHz 的成分可能已经折叠进数字输入。传感器、内部滤波器和外部滤波器必须一起考虑。不能假定加速度计自动集成了合适滤波器。ADC 饱和、机械安装不当还会产生与混叠不同的问题,本文数字滤波器无法解决它们。
然后要在实际精度下做数值验证。本文结果使用 float64;系数转换成 float32 或定点整数后,并不保证 700 Hz 仍有 −97.61 dB 衰减。应重新计算响应,检查溢出与饱和,并在保持滤波状态的前提下验证块边界。每块都清零状态会反复产生瞬态,恰在我们想提高信号可靠性时改变信号。
最后,要用训练与部署一致的采集链评估模型决策。滤波器变化会改变幅度、相位及延迟,模型也可能恰好学到了某种伪影。试验应记录已知输入频率、传感器设置、时钟、版本及代码,再在平台上测量延迟和功率。这是建议协议,不报告未经测量的功率、每次推理能耗或诊断准确率。
结论:解释信息之前,先保护信息
开头的 300 Hz 峰不足以确认真实振动。现在原因清楚了:观察时刻的选择可能抹去物理区别,下游 AI 若无额外假设就无法重建它。在构造的例子中,先在 4 kHz 下滤波,再降到 1 kHz,可以保留有用成分并削弱污染它的成分。代价可用延迟、缓冲区和运算量描述,但硬件性能仍待验证。因此,设计嵌入式 AI,也包括设计物理世界如何变成数据。
来源、代码与复现条件
MIT 6.300 — Sampling and Aliasing, Spring 2026.
Arm CMSIS-DSP — Finite Impulse Response Decimator, main documentation.
Analog Devices — Filter Basics: Anti-Aliasing.
来源说明采样、抗混叠保护和抽取器接口。CMSIS 的 main 页面是会变化的文档,查阅日期为 2026 年 9 月 25 日,不是我们测过性能的内核版本。滤波器、信号与比较均在附件实验中构造。下面片段计算增益和延迟,压缩包另含卷积、幅度估计及绘图。使用 Python 3.14.0、NumPy 2.5.3、Matplotlib 3.11.2,无随机数。本编辑分析不意味着 EL-AI 已有嵌入式产品或实际安装。
import numpy as np
fs, fc, taps = 4000, 400, 129
k = np.arange(taps)
h = (2*fc/fs) * np.sinc((2*fc/fs)*(k-64)) * np.hanning(taps)
h /= h.sum()
for f in (300, 700):
gain = abs(np.sum(h*np.exp(-2j*np.pi*f*k/fs)))
print(f, round(float(gain), 9))
print("delay_ms", 1000*64/fs)
代码、数据与说明 · JSON. 教学计算使用 Python 3.14.0,图使用 Matplotlib 3.11.2。分析由 AI 辅助,不声称经过同行评审或人工审核。原创 ImageGen 封面仅作示意,不记录 EL-AI 人员、场所或实际安装。来源查阅于 2026 年 9 月 25 日。

