有用的噪声

在信号处理过程中,噪声通常被认为是无用的,甚至我们会想出很多方法来滤除信号中的噪声,提高信号的信噪比,比如带限滤波器、周期信号取平均等。然而噪声真的一无是处吗?下面通过一个例子,向你展示噪声不为人知的另一面!
1. ADC采样量化过程
我们所处的世界是连续的,而计算机却只能处理离散信号。为此,需要对连续信号进行离散化处理,这个过程靠模数转换器(Analogy-to-Digital Converter, ADC)来实现。
ADC最重要的参数包括:1)采样率 f s f_s fs,决定了ADC离散样点的时间精度,采样率越高,离散信号越逼近于原始连续信号;2)量化bit位数 N N N和参考电压 V r e f V_{ref} Vref,决定了ADC量化的电压精度,量化误差 Δ V \Delta V ΔV服从均匀分布 U ( − V r e f 2 N − 1 , V r e f 2 N − 1 ) U(-\frac{V_{ref}}{2^{N-1}},\frac{V_{ref}}{2^{N-1}}) U(2N1Vref,2N1Vref)。本文仅考虑电压量化精度。
在这里插入图片描述

图1. ADC量化误差示意图(虚斜线为模拟电压,阶梯实线为量化电压,两者相减为量化误差,量化误差呈现锯齿状)

下面首先通过一个仿真案例(仿真代码见附录1),直观了解量化的影响。利用高采样率的离散样点来模拟连续信号,每隔 Δ \Delta Δ个样点从高采样率的离散样点中取值以模拟采样过程,将采样得到的样点进行2/4/8bit的量化。从下图可以看出,量化bit数越小,量化阶梯现象越严重,可表征的电压精细度越差。
在这里插入图片描述

图2. 不同量化位数对比

2. 噪声赋能量化过程
若要用ADC采集一个幅度很小的信号,甚至小于ADC的一个量化单位,则量化后无法获取任何有效信息。如下图所示(代码见附录2),信号幅度为0.03V,小于ADC 的LSB=0.0625V,此时量化后的所有采样点均为0。
在这里插入图片描述

图3. 信号幅度小于LSB的情况示意图

现在在上图中的采样信号中加入RMS=0.03V的高斯噪声,再进行量化处理,并将量化后的信号进行低通滤波,得到下图所示结果。现在噪声提高了信号的幅度,超过了ADC的量化单元,是的量化后保留了部分有效信号的信息,再经过后续的滤波器消除噪声影响,可以部分恢复有效信号。
在这里插入图片描述

图4. 叠加噪声后量化的处理结果

综上所述,不能思维定式地认为噪声都是无用的,换个角度看,噪声也是宝!!


【附录1】:图2代码

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']  # 使用微软雅黑字体
plt.rcParams['axes.unicode_minus'] = False  # 处理负号显示异常

if __name__ == '__main__':
    f0 = 100
    fs = 100000
    delta = 10
    v_ref = 4
    bits = np.array([2, 4, 8])
    N = int(fs / 10)
    t = np.arange(0, N, 1) / fs
    sig = np.sin(2 * np.pi * f0 * t)     # 用高采样率模拟连续信号

    plt.figure()
    plt.plot(t, sig, 'b', linewidth=3)
    for i in range(len(bits)):
        lsb = v_ref / (2 ** bits[i])
        sampled_sig = sig[0::delta]  # 原始采样信号
        sampled_sig = (np.round(sampled_sig / lsb)) * lsb
        plt.plot(t[0::delta], sampled_sig, '.')
    plt.legend(['连续信号', 'ADC bit=2', 'ADC bit=4', 'ADC bit=8'])
    plt.show()

【附录2】:图3代码

if __name__ == '__main__':
    f0 = 100
    fs = 100000
    delta = 10
    v_ref = 4
    bits = 6
    N = int(fs / 10)
    t = np.arange(0, N, 1) / fs
    sig = 0.01 * np.sin(2 * np.pi * f0 * t)     # 用高采样率模拟连续信号

    plt.figure()
    lsb = v_ref / (2 ** bits)
    sampled_sig = sig[0::delta]  # 原始采样信号
    quantitative_sig = (np.round(sampled_sig / lsb)) * lsb
    plt.plot(t[0::delta], sampled_sig, 'b')
    plt.plot(t[0::delta], quantitative_sig, 'r.')
    plt.legend(['采样信号', '量化信号'])
    plt.show()

【附录3】:图4代码

import numpy as np
import matplotlib.pyplot as plt
import scipy.signal as signal
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']  # 使用微软雅黑字体
plt.rcParams['axes.unicode_minus'] = False  # 处理负号显示异常

if __name__ == '__main__':
    f0 = 100
    fs = 100000
    delta = 10
    v_ref = 4
    bits = 6
    N = int(fs / 10)
    t = np.arange(0, N, 1) / fs
    sig = 0.03 * np.sin(2 * np.pi * f0 * t)     # 用高采样率模拟连续信号
    lsb = v_ref / (2 ** bits)
    sampled_sig = sig[0::delta]  # 原始采样信号
    noise = np.random.normal(loc=0, scale=0.03, size=len(sampled_sig))
    sampled_sig = sig[0::delta] + noise
    quantitative_sig = (np.round(sampled_sig / lsb)) * lsb

    # 第信号进行滤波
    cutoff = f0 * 3
    nyquist_freq = fs / delta / 2
    normal_cutoff = cutoff / nyquist_freq
    b, a = signal.bessel(5, normal_cutoff, btype='low', analog=False)
    filtered_data = signal.lfilter(b, a, quantitative_sig)

    plt.figure()
    plt.plot(t[0::delta], sampled_sig, 'b')
    plt.plot(t[0::delta], quantitative_sig, 'g.')
    plt.plot(t[0::delta], filtered_data, 'k.')
    plt.plot(t[0::delta], sig[0::delta], 'r')
    plt.legend(['采样信号', '量化信号', '滤波信号', '理想信号'])
    plt.show()
  • 19
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值