3、噪声分析与建模:点钞机常见噪声源
做点钞机传感器融合,说白了就是跟噪声打仗。我做了这么多年嵌入式,见过太多方案在实验室跑得挺好,一上产线就崩。为什么?噪声没摸透。
这一章,咱们就专门聊聊噪声。你得先认识它,才能干掉它。
3.1 点钞机三大噪声源
我个人习惯,把点钞机的噪声分成三类。你想想看,钞票在机器里高速飞过,机械在转,电磁在辐射,纸币本身还在抖。这三股力量搅在一起,传感器信号能干净才怪。
3.1.1 机械振动噪声
这是最直接的噪声源。电机一转,皮带一拉,滚轮一压,整个机架都在微幅振动。
- 来源:电机转子不平衡、齿轮啮合冲击、皮带张紧波动
- 频率范围:通常在 50Hz ~ 500Hz 之间
- 特性:周期性、窄带,跟电机转速强相关
我在项目中遇到过一件事。有一款点钞机,每次数到第50张左右就开始误报。查了三天,最后发现是电机在某个转速下跟机架产生了共振。嗯,这里要注意:机械振动噪声往往不是白噪声,它有明显的频率峰值。
关键点:机械振动噪声的频率 = 电机转速 × 机械结构固有频率的谐波。你可以在电机轴上贴个加速度计,先测出这个底噪。
3.1.2 电磁干扰(EMI)
这个更隐蔽。点钞机里既有电机驱动的大电流,又有传感器的小信号。电磁干扰就像隔壁装修的电钻声,你不屏蔽它,它就往你的信号里钻。
- 来源:电机换向火花、开关电源纹波、数字电路高频时钟
- 频率范围:从几十kHz到几百MHz,跨度极大
- 特性:脉冲型、宽带,常表现为尖峰噪声
我曾经吃过一次亏。用了一款便宜的霍尔传感器,没做差分走线,结果电机一启动,ADC读数直接跳了20个LSB。后来加了共模扼流圈和屏蔽罩,才压下去。
避坑指南:我曾经以为软件滤波能搞定所有EMI,后来发现高频干扰会直接让ADC饱和。硬件上该加的去耦电容、屏蔽罩,一个都不能省。
3.1.3 纸币抖动噪声
这个最头疼。纸币不是刚体,它是软的。新旧程度、湿度、褶皱程度都不一样。钞票在传送带上高速移动时,会上下左右随机抖动。
- 来源:纸币材质不均匀、空气阻力、滚轮压紧力波动
- 频率范围:1Hz ~ 20Hz,低频为主
- 特性:非平稳、随机性强,跟纸币状态高度相关
你想想看,一张皱巴巴的旧钞和一张崭新的钞票,抖动特性完全不一样。这就是为什么很多点钞机对新钞识别率高,旧钞就翻车。
3.2 噪声统计特性分析
搞清楚了噪声来源,接下来要量化它。我习惯用统计工具来分析噪声的脾气。
3.2.1 时域统计特征
最简单的办法,先抓一段传感器静置时的数据,算几个基本统计量。
| 统计量 | 含义 | 点钞机中的典型值 |
|---|---|---|
| 均值(Mean) | 直流偏置 | 通常接近0(经过高通后) |
| 标准差(Std) | 噪声能量大小 | 机械振动:5~15 mV |
| 峰峰值(Peak-to-Peak) | 最大波动范围 | EMI干扰:可达50 mV以上 |
| 均方根(RMS) | 有效噪声功率 | 纸币抖动:2~8 mV |
我个人习惯,先算标准差。如果标准差超过传感器满量程的1%,那硬件上就得先处理,别指望纯软件滤波。
3.2.2 频域分析:功率谱密度(PSD)
时域只能告诉你噪声有多大,频域才能告诉你噪声在哪。我常用的工具是FFT,然后画功率谱密度图。
// 伪代码:计算噪声的功率谱密度
#define FFT_SIZE 1024
float buffer[FFT_SIZE];
// 采集一段无信号时的传感器数据
for (int i = 0; i < FFT_SIZE; i++) {
buffer[i] = read_adc() - baseline;
}
// 执行FFT
fft(buffer, FFT_SIZE);
// 计算功率谱
for (int i = 0; i < FFT_SIZE/2; i++) {
psd[i] = (buffer[i].real * buffer[i].real +
buffer[i].imag * buffer[i].imag) / FFT_SIZE;
}
做完FFT,你会看到什么?
- 机械振动:在电机基频及其谐波处出现尖峰
- EMI:在开关频率处出现宽峰,或者全频段抬升
- 纸币抖动:低频段(<20Hz)能量集中,形状像1/f噪声
小技巧:我建议你在点钞机空转时采集一段数据做PSD,这就是你的「噪声指纹」。后续设计滤波器时,直接对着这个指纹来切。
3.2.3 概率分布分析
噪声的分布形态决定了你用哪种滤波算法最合适。
- 高斯分布:热噪声、散粒噪声。均值滤波或卡尔曼滤波效果好。
- 均匀分布:量化噪声。过采样+平均可以改善。
- 拉普拉斯分布:脉冲噪声、EMI尖峰。中值滤波更合适。
我遇到过最坑的情况:噪声看起来像高斯,但尾巴特别长。后来一查,是电机换向时偶尔产生的脉冲干扰。用均值滤波根本压不住,换了中值滤波才搞定。
3.3 噪声建模实战
理论说完了,咱们来点实际的。我一般会在仿真阶段先建一个噪声模型,这样算法调参不用总跑硬件。
3.3.1 合成噪声模型
把三种噪声叠加起来,模拟真实场景。
// 噪声合成模型
typedef struct {
float mechanical_amp; // 机械振动幅值
float mechanical_freq; // 机械振动基频
float emi_amp; // EMI脉冲幅值
float emi_probability; // EMI出现概率
float flutter_amp; // 纸币抖动幅值
} NoiseModel;
float generate_noise(NoiseModel *model) {
float noise = 0;
// 1. 机械振动:正弦波 + 谐波
noise += model->mechanical_amp * sin(2 * PI * model->mechanical_freq * t);
noise += 0.3 * model->mechanical_amp * sin(2 * PI * 2 * model->mechanical_freq * t);
// 2. EMI:随机脉冲
if (rand() / RAND_MAX < model->emi_probability) {
noise += model->emi_amp * (rand() / RAND_MAX);
}
// 3. 纸币抖动:1/f噪声(用随机游走近似)
static float flutter_state = 0;
flutter_state += (rand() / RAND_MAX - 0.5) * 0.1;
flutter_state *= 0.99; // 泄漏积分器
noise += model->flutter_amp * flutter_state;
return noise;
}
实战建议:先用这个模型跑一遍你的滤波算法,调好参数再上硬件。我至少省了30%的调试时间。
3.3.2 噪声耦合路径分析
噪声怎么进到传感器信号里的?搞清楚路径,才能对症下药。
| 噪声类型 | 耦合路径 | 典型抑制手段 |
|---|---|---|
| 机械振动 | 结构传导 → 传感器基座 | 减震垫、低通滤波 |
| 电磁干扰 | 空间辐射 → 信号线 | 屏蔽、差分走线、共模扼流圈 |
| 纸币抖动 | 机械耦合 → 传感器检测面 | 机械压紧、自适应滤波 |
嗯,这里要注意:有时候噪声不是单一路径进来的。比如电机振动会带动线缆晃动,线缆切割磁场又产生感应电动势。这种二次耦合最烦人。
3.4 本章小结
噪声分析不是一锤子买卖。我每次换一款点钞机,或者换一种纸币,都会重新做一遍噪声摸底。
- 先时域:看噪声有多大,有没有明显异常
- 再频域:找噪声集中在哪些频率
- 后统计:看噪声是什么分布,选对滤波算法
下一章,咱们就拿着这些噪声模型,开始设计真正的滤波器。你想想看,知道了敌人长什么样,打起来是不是心里有底多了?