前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >☀️手把手教你Python+matplotlib模拟锁相放大器的原理以及工作过程☀️《❤️记得收藏❤️》

☀️手把手教你Python+matplotlib模拟锁相放大器的原理以及工作过程☀️《❤️记得收藏❤️》

作者头像
苏州程序大白
发布2021-09-26 11:33:05
1.4K0
发布2021-09-26 11:33:05
举报
文章被收录于专栏:用户8907256的专栏

☀️手把手教你Python+matplotlib模拟锁相放大器的原理以及工作过程☀️《❤️记得收藏❤️》

目录

🏳️‍🌈开讲啦!!!!🏳️‍🌈苏州程序大白🏳️‍🌈

在这里插入图片描述
在这里插入图片描述

🌟博主介绍

💂 个人主页:苏州程序大白 🤟作者介绍:中国DBA联盟(ACDU)成员,CSDN全国各地程序猿(媛)聚集地管理员。目前从事工业自动化软件开发工作。擅长C#、Java、机器视觉、底层算法等语言。2019年成立柒月软件工作室。 💬如果文章对你有帮助,欢迎关注、点赞、收藏(一键三连)和C#、Halcon、python+opencv、各大公司面试等一些订阅专栏哦 💅 有任何问题欢迎私信,看到会及时回复 👤 微信号:stbsl6,微信公众号:苏州程序大白 🎯 想加入技术交流群的可以加我好友,群里会分享学习资料

前言

我们先讲讲锁相放大器的基本结构示于下方图 ,包括信号通道、参考通道、相敏检测器 PSD 和低通滤波器 LPF 等。 各个模块的基本功能描述如下:

在这里插入图片描述
在这里插入图片描述
  • 1、信号通道: 对信号输入进行放大及滤波, 将微弱信号放大到足以推动相敏检测器工作的电平, 并且要滤除部分干扰和噪声。
  • 2、参考输入: 一般是等幅正弦或者方波信号, 它可以是从外部输入的某种周期信号,也可以是系统内原先用于调制的载波信号或用于斩波的信号。
  • 3、参考通道: 对参考输入进行放大或衰减, 以适应相敏检测器对幅度的要求。参考通道的另一个重要功能是对参考输入进行相位锁定及移相等处理,从而产生同频正弦波与余弦波,以提供给相敏检波器进行乘法运算。相敏检波器(PSD): 以参考通道提供的基准正弦与余弦分量作为输入, 对经过信号通道放大滤波的 进行相敏检波(乘法运算), 从而实现检波。
  • 4、 如下方图所示频谱迁移过程。将 的频谱由 处迁移到 处,再经 LPF 滤除噪声, 其输出 对 的幅度和相位都敏感,这样就达到了既鉴幅又鉴相(相位及幅度的测量)的目的。
在这里插入图片描述
在这里插入图片描述
  • 5、低通滤波器(LPF): 频带可以做得很窄, 所以可使锁相放大器达到较大的 SNIR。 锁相放大器的应用大致分为以下领域:测量噪声中的微弱信号:
  • 红外分光光度计,2次量子光分光分析,光声光谱仪,超导材料的评价,金属材料的张力试验,放大器的CMRR或IMRR测量。
  • 测量被测定体传输函数的微小变化:俄歇电子能谱,金属探测器,涡流探伤器。被测定体的矢量分析:RLC测量仪,电解-阻抗,电子束测量。

python实现模拟锁相放大器

首先引入需要用到的package,使用%matplotlib widget可以产生交互式的图片。

代码语言:javascript
复制
import numpy as np
from scipy.fftpack import fft
from scipy import signal as sg
from matplotlib import pyplot as plt

%matplotlib widget

matplotlib绘图

在本文中将会产生许多的图片,为了方便绘图编写一个展示信号的绘图函数。

代码语言:javascript
复制
def draw(x, y, title='', xlable='time(s)', ylable='amplitude', L=-3.8, H=3.8):
    '''
    draw

    Parameters
    ----------
        x : numpy array
            abscissa
        y : numpy array
            ordinate

    Returns
    -------
    '''
    # canvas settings
    plt.close()
    if L!=H:
        plt.ylim(L, H)
    plt.title(title)
    plt.xlabel(xlable)
    plt.ylabel(ylable)

    plt.plot(x, y)
    plt.show()

绘画正弦波

采用正弦波作为输入信号。另外,参考信号、噪声信号等都需要用到正弦信号,所以第一步将编写一个产生给定幅度、频率和相位的正弦信号的函数。

代码语言:javascript
复制
def g_sin(t=1, amp=1, f0=10, fs=500, phi=0):
    '''
    generate sinusoid

    Parameters
    ----------
        t   : float
            time length of the generated sequence
        amp : float
            amplitude
        f0  : float
            frequency of sinusoid in Hz
        fs  : float
            sampling rate per second
        phi : float
            initial phase in deg

    Returns
    -------
        anonymous : list[numpy array, numpy array]
            [abscissa, a sinusoid signal]
    '''
    T = 1/fs
    N = t/T
    x = 2*np.pi*np.arange(N)*T
    return [np.arange(0, t, T), amp*np.sin(f0*x+phi*np.pi/180)]


x, y = g_sin()
draw(x, y)
在这里插入图片描述
在这里插入图片描述

绘画方波

参考信号可以使用正弦波、方波等。在本实验中将使用方波,而方波的傅里叶级数为:

在这里插入图片描述
在这里插入图片描述

所以我们可以利用上面的正弦波函数,产生一个近似的方波,方波的阶数(即K)越大近似效果越好,K=50时就有很好的效果。 (PS:此处方波均指占空比为50%,正负对称的方波)

代码语言:javascript
复制
def g_square_wave(t=1, amp=1, f0=10, fs=500, K=50):
    '''
    generate square wave

    Parameters
    ----------
        t   : float
            time length of the generated sequence
        amp : float
            amplitude
        f0  : float
            frequency of sinusoid in Hz
        fs  : float
            sampling rate per second
        K   : int
            order of fourier series

    Returns
    -------
        anonymous : list[numpy array, numpy array]
            [abscissa, a square wave]
    '''
    T = 1/fs
    N = t/T
    x = 2*np.pi*np.arange(N)*T

    y = np.zeros(len(x))
    k = 2*np.arange(1, K)-1
    for i in range(len(x)):
        y[i] = amp*np.sum(np.sin(k*f0*x[i])/k)
    return [np.arange(0, t, T), 4*y/np.pi]


x, y = g_square_wave()
draw(x, y)
在这里插入图片描述
在这里插入图片描述

使用上述两个函数,可以叠加产生带有噪声的信号。

代码语言:javascript
复制
x, y1 = g_sin(amp=0.2, f0=30)
x, y2 = g_sin(amp=0.35, f0=3, phi=45)
x, y3 = g_square_wave(amp=0.1, f0=10)
draw(x, y1+y2+y3)
在这里插入图片描述
在这里插入图片描述

绘画频域分析

这些噪声在时域中难以分辨。不过信号与噪声不同,往往具有明显的频率特征,而噪声一般是与频率无关的,或者是在特定频率范围内的,所以在频域内可以很好的分辨出输入信号的各种成分。

使用快速傅里叶变换(FFT)从时域转化到频域,并且对振幅谱进行取半归一化。

代码语言:javascript
复制
def FFT(s, fs):
    '''
    fast fourier transform

    Parameters
    ----------
        s  : numpy array
            signal
        fs : float
            sampling rate per second

    Returns
    -------
    '''
    X  = fft(s)
    mX = np.abs(X)   # magnitude
    pX = np.angle(X) # phase

    draw(np.arange(int(fs/2)), mX[range(int(fs/2))]/fs, 
         'Input signal in frequency domain', 'frequency(Hz)', 'amplitude', 0, 0)


FFT(y1+y2+y3, 500)
在这里插入图片描述
在这里插入图片描述

绘画高斯白噪声

上面的信号添加的噪声还是正弦信号,而现实中比较常见的噪声是白噪声。下面的函数可以根据输入信号产生一个特定信噪比的白噪声。

信噪比的定义是:

在这里插入图片描述
在这里插入图片描述

在本实验中,功率 P P P可以用功 ‘ W = ∫ P d t = C ∫ A 2 d t `W=\int Pdt=C\int A^2dt ‘W=∫Pdt=C∫A2dt`代替,因为信号和噪声的积分时间是相同的。而信号的波形是采样得到的,所以 W W W可以用 ∑ x i 2 \sum x_i^2 ∑xi2​代替,于是有:

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
def wgn(x, snr):
    '''
    generate Gauss white noise
    
    Parameters
    ----------
        x   : numpy array
            signal
        snr : float
            signal-to-noise ratio
        
    Returns
    -------
        anonymous : numpy array
            Gauss white noise
    '''
    snr    = 10**(snr/10.0)
    xpower = np.sum(x**2)/len(x)
    npower = xpower / snr
    return np.random.randn(len(x)) * np.sqrt(npower)


noise = wgn(np.sin(np.arange(0, 1000000)*0.1), 6)
plt.close()
plt.subplot(211)
plt.hist(noise, bins=100)
plt.subplot(212)
plt.psd(noise)
plt.show()
在这里插入图片描述
在这里插入图片描述

模拟锁相放大器的工作过程

下面开始正式的模拟过程:

获得输入信号,输入信号由10Hz的目标信号和其他频率的正弦噪声以及白噪声组成

A、 增加正弦部分

代码语言:javascript
复制
x, y1  = g_sin(amp=0.1)
x, y2  = g_sin(amp=0.5, f0=50)
x, y3  = g_sin(amp=0.8, f0=3)
x, y4  = g_sin(amp=0.3, f0=200)
signal = y1+y2+y3+y4

B、增加白噪声部分

代码语言:javascript
复制
noise = wgn(signal, 10)
sn    = signal+noise
draw(x, sn)
在这里插入图片描述
在这里插入图片描述

C、 查看输入信号的频域信息

代码语言:javascript
复制
FFT(sn, 500)
在这里插入图片描述
在这里插入图片描述

获得参考信号,方波频率与目标信号相同,为10Hz

代码语言:javascript
复制
x, y   = g_square_wave(K=100)
square = y
draw(x, square)
在这里插入图片描述
在这里插入图片描述

3、前置放大×2倍

代码语言:javascript
复制
sn = sn*2
draw(x, sn)
在这里插入图片描述
在这里插入图片描述

4、输入信号进行带通滤波,除去/抑制部分噪声,增强锁相放大器的性能(动态储备和输出动态范围)

代码语言:javascript
复制
b, a = sg.butter(1, [0.02, 0.12], 'bandpass') # 5Hz - 30Hz
snq  = sg.filtfilt(b, a, sn)
draw(x, snq)
在这里插入图片描述
在这里插入图片描述

5、调谐放大输入信号×5,增大信噪比

代码语言:javascript
复制
b, a = sg.butter(1, [0.038, 0.042], 'bandpass') # 9.5Hz - 10.5Hz
sns  = sg.filtfilt(b, a, snq)
snq  = sns*4+snq
draw(x, snq)
在这里插入图片描述
在这里插入图片描述

6、PSD(相敏检波器)处理输入与参考信号(本质为乘法器)

代码语言:javascript
复制
snqx = snq*square
draw(x, snqx)
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
FFT(snqx, 500)
在这里插入图片描述
在这里插入图片描述

7、低通滤波,减少其他信号对直流分量的影响(等效噪声宽度很小)

代码语言:javascript
复制
b, a = sg.butter(3, 0.00004, 'lowpass') # 0 - 0.01Hz
sns  = sg.filtfilt(b, a, snqx)
draw(x, sns)
在这里插入图片描述
在这里插入图片描述

8、直流放大×5

代码语言:javascript
复制
sns = sns*5
draw(x, sns)
在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/09/24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ☀️手把手教你Python+matplotlib模拟锁相放大器的原理以及工作过程☀️《❤️记得收藏❤️》
  • 目录
  • 🏳️‍🌈开讲啦!!!!🏳️‍🌈苏州程序大白🏳️‍🌈
  • 🌟博主介绍
  • 前言
  • python实现模拟锁相放大器
  • matplotlib绘图
  • 绘画正弦波
  • 绘画方波
  • 绘画频域分析
  • 绘画高斯白噪声
  • 模拟锁相放大器的工作过程
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档