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 本章小结

噪声分析不是一锤子买卖。我每次换一款点钞机,或者换一种纸币,都会重新做一遍噪声摸底。

  • 先时域:看噪声有多大,有没有明显异常
  • 再频域:找噪声集中在哪些频率
  • 后统计:看噪声是什么分布,选对滤波算法

下一章,咱们就拿着这些噪声模型,开始设计真正的滤波器。你想想看,知道了敌人长什么样,打起来是不是心里有底多了?