信号补零对信号频谱的影响

简介: 信号补零对信号频谱的影响

前言

本文对信号补零前与补零后分别做 FFT,对频谱进行分析。

先抛出结论:

补 1 次零相当于在原始频谱图中每两个频率之间插入1个频率值,补 2 次零相当于在原始频谱图中每两个频率之间插入 2 个频率值,并且原始频率值的位置及其幅值保持不变。因此, 补零会使频谱图中的频率点的数量增加,从而使得频谱图更加的光滑连续,但是补零不能对频谱图中的频率分辨率、频率值以及幅值有所改善。


一、 什么是补零

FFT 运算点数(M) > 采样点数(N)时,fft(xn,M) 函数对信号 xn 进行尾补零操作即在该信号尾部添加多个值为 0 的数据点以使信号总点数 N 增至 FFT 运算所需点数M

二、案例

image.png

三、补零前仿真及分析

直接对这 1000 个数据点做 FFT

1、补零前 MATLAB 源码

%% [预处理]
clc;   % 清除命令窗口
clear; % 清除工作空间的变量和函数
clf;   % 清除当前图形
%% [采样参数]
fs = 100e6;         % 采样频率 (Hz)  
ts = 1/fs;          % 采样周期 (s)
N  = 1000;          % 采样点数 (个)
n  = 0:N-1;         % 采样点索引
t  = n*ts;          % 采样时间轴
%% [未补零 被采信号 && 绘制时域波形]
fa = 1e6;           % 信号 a 的频率
fb = 1.05e6;        % 信号 b 的频率
xn = cos(2*pi*fa*t) + cos(2*pi*fb*t);   % 被采信号 = 信号a + 信号b
figure(1);
plot(t, xn);
axis([0 10e-6 -inf inf]);  % x 轴范围设置成[0,10us],y 轴范围最小值和最大值都为无穷
title('xn 时域图');
ylabel('幅度/V');
xlabel('时间/s');
%% [未补零 被采信号 && 绘制频谱图]
M = 1000;                   % FFT 运算点数
X = fft(xn, M);             % FFT 输出值
X = [X(1)/N,X(2:M)*2/N];    % 幅度轴,对FFT输出值进行归一化处理,得到幅度轴上的值。
k = 0:M-1;                  % 频率点索引
f = fs*k/(M-1);             % 频率轴
figure(2);
plot(f, abs(X));
axis([0.5e6 1.5e6 0 1.5]);  % x 轴范围设置成[0.5e6,1.5e6],y 轴范围设置成[0,1.5]
title('xn 频谱图');
ylabel('X(f)');
xlabel('频率/Hz');

2、仿真及结果分析

①、x n x_nxn 时域图

②、x n x_nxn 频谱图

image.png

四、补零后仿真及分析

对数据补零,增加 FFT 点数,比如补 6000 个零,做 7000 个点的 FFT。

1、补6000个零且1000采样点

①、 MATLAB 源码

%% [预处理]
clc;   % 清除命令窗口
clear; % 清除工作空间的变量和函数
clf;   % 清除当前图形
%% [采样参数]
fs = 100e6;         % 采样频率 (Hz)  
ts = 1/fs;          % 采样周期 (s)
N  = 1000;          % 采样点数 (个)
n  = 0:N-1;         % 采样点索引
t  = n*ts;          % 采样时间轴
%% [被采信号 && 绘制时域波形] 
fa = 1e6;           % 信号 a 的频率
fb = 1.05e6;        % 信号 b 的频率
xn = cos(2*pi*fa*t) + cos(2*pi*fb*t);   % 被采信号 = 信号a + 信号b
figure(1);
plot(t, xn);
axis([0 10e-6 -inf inf]);  % x 轴范围设置成[0,10us],y 轴范围最小值和最大值都为无穷
title('xn 时域图');
ylabel('幅度/V');
xlabel('时间/s');
%% [尾补零 被采信号 && 绘制时域波形]
xnwei=[xn zeros(1,6000)]; % 补6000个零
M = length(xnwei);          % FFT 运算点数
X = fft(xnwei, M);          % FFT 输出值
X = [X(1)/N,X(2:M)*2/N];    % 幅度轴,对FFT输出值进行归一化处理,得到幅度轴上的值。
k = 0:M-1;                  % 频率点索引
f = fs*k/(M-1);             % 频率轴
figure(2);
plot(f, abs(X));
axis([0.5e6 1.5e6 0 1.5]);  % x 轴范围设置成[0.5e6,1.5e6],y 轴范围设置成[0,1.5]
title('补零后共7000个数据点做FFT的频谱');
ylabel('X(f)');
xlabel('频率/Hz');

②、仿真及结果分析

可以看到信号频谱变得平滑了,但是仍然无法区分1MHz1.05MHz

这里就要引出一个波形分辨率的概念,虽然补零了,提高了频谱分辨率,但是无法提高波形分辨率

2、波形分辨率

发现频率成分无法被区分开,第一反应就是:频率分辨率不够,那么,如何提高频率分辨率呢?首先要清楚,这里存在两种类型的频率分辨率。


image.png

image.png

所以要想提高波形分辨率,必须提高信号数据本身的长度

3、补6000个零且7000采样点

采样 7000 个信号数据做 FFT,还是补 6000 个零 ,做 13000 个点的 FFT

①、 MATLAB 源码

%% [预处理]
clc;   % 清除命令窗口
clear; % 清除工作空间的变量和函数
clf;   % 清除当前图形
%% [采样参数]
fs = 100e6;         % 采样频率 (Hz)  
ts = 1/fs;          % 采样周期 (s)
N  = 7000;          % 采样点数 (个)
n  = 0:N-1;         % 采样点索引
t  = n*ts;          % 采样时间轴
%% [被采信号 && 绘制时域波形] 
fa = 1e6;           % 信号 a 的频率
fb = 1.05e6;        % 信号 b 的频率
xn = cos(2*pi*fa*t) + cos(2*pi*fb*t);   % 被采信号 = 信号a + 信号b
figure(1);
plot(t, xn);
axis([0 10e-6 -inf inf]);  % x 轴范围设置成[0,10us],y 轴范围最小值和最大值都为无穷
title('xn 时域图');
ylabel('幅度/V');
xlabel('时间/s');
%% [尾补零 被采信号 && 绘制时域波形]
xnwei=[xn zeros(1,6000)]; % 补6000个零
M = length(xnwei);          % FFT 运算点数
X = fft(xnwei, M);          % FFT 输出值
X = [X(1)/N,X(2:M)*2/N];    % 幅度轴,对FFT输出值进行归一化处理,得到幅度轴上的值。
k = 0:M-1;                  % 频率点索引
f = fs*k/(M-1);             % 频率轴
figure(2);
plot(f, abs(X));
axis([0.5e6 1.5e6 0 1.5]);  % x 轴范围设置成[0.5e6,1.5e6],y 轴范围设置成[0,1.5]
title('采样点7000且补零后共13000个数据点做FFT的频谱');
ylabel('X(f)');
xlabel('频率/Hz');

②、仿真及结果分析


image.png

image.png

这是因为在1.05MHz 那个地方刚好有个频点,也就是出现了所谓的频谱泄漏,还是数据长度不够,但这时是可以通过补零来达到目的。再补零 1000 个点,做 14000 点的 FFT。

4、补7000个零且7000采样点

采样 7000 个信号数据做 FFT,补 7000 个零 ,做 14000 点的 FFT

①、 MATLAB 源码

%% [预处理]
clc;   % 清除命令窗口
clear; % 清除工作空间的变量和函数
clf;   % 清除当前图形
%% [采样参数]
fs = 100e6;         % 采样频率 (Hz)  
ts = 1/fs;          % 采样周期 (s)
N  = 7000;          % 采样点数 (个)
n  = 0:N-1;         % 采样点索引
t  = n*ts;          % 采样时间轴
%% [被采信号 && 绘制时域波形] 
fa = 1e6;           % 信号 a 的频率
fb = 1.05e6;        % 信号 b 的频率
xn = cos(2*pi*fa*t) + cos(2*pi*fb*t);   % 被采信号 = 信号a + 信号b
figure(1);
plot(t, xn);
axis([0 10e-6 -inf inf]);  % x 轴范围设置成[0,10us],y 轴范围最小值和最大值都为无穷
title('xn 时域图');
ylabel('幅度/V');
xlabel('时间/s');
%% [尾补零 被采信号 && 绘制时域波形]
xnwei=[xn zeros(1,7000)];   % 补7000个零
M = length(xnwei);          % FFT 运算点数
X = fft(xnwei, M);          % FFT 输出值
X = [X(1)/N,X(2:M)*2/N];    % 幅度轴,对FFT输出值进行归一化处理,得到幅度轴上的值。
k = 0:M-1;                  % 频率点索引
f = fs*k/(M-1);             % 频率轴
figure(2);
plot(f, abs(X));
axis([0.5e6 1.5e6 0 1.5]);  % x 轴范围设置成[0.5e6,1.5e6],y 轴范围设置成[0,1.5]
title('采样点7000且补零后共14000个数据点做FFT的频谱');
ylabel('X(f)');
xlabel('频率/Hz');

②、仿真及结果分析

image.png


五、补零的好处

  • 使数据 N 为 2 的整次幂,便于使用 FFT
  • 补零后,其实是对 DFT 结果做了插值,克服“栅栏"效应,使谱外观平滑化。我把“栅栏"效应形象理解为,就像站在栅栏旁边透过栅栏看外面风景,栅栏会挡住比较多风景,此时就可能漏掉较大频域分量,但是补零以后,相当于你站远了,风景就看的越来越清楚了。
  • 由于对时域数据的截短必然造成频谱泄露,因此在频谱中可能出现难以辨认的谱峰,补零在一定程度上能消除这种现象。

对信号进行头补零或尾补零再得到的幅频响应相等,相频响应不同

补零会使频谱图中的频率点的数量增加,从而使得频谱图更加的光滑连续,但是补零不能对频谱图中的频率分辨率、频率值以及幅值有所改善。

  • 补零(Zero-padding)是在FFT计算中向输入信号序列的末尾添加零值,从而增加信号的长度。这样做的主要目的是在频域中插入更多的零频率样本,以获得更好的频谱分析图。
  • 补零可以在一定程度上改善频谱图的可视化效果,使频谱图在频率轴上呈现更平滑的外观。这是因为补零增加了离散傅里叶变换(DFT)点数,从而在频率轴上产生更多的插值点。然而,这并不意味着补零改善了频率分辨率或精确性。
  • 频率分辨率由采样率和FFT长度决定,而补零并不改变采样率。补零只是对现有的采样点进行插值,不会增加频率分辨率。实际上,补零只是在现有的频率分辨率上插入了更多的点,而不是提高了分辨率本身。
  • 频率值和幅值也不会因为补零而改变。补零只是在现有的频率轴上插入了更多的点,对原有的频率值和幅值进行了插值。这些插值点的值是通过对原始采样点进行插值计算得到的,而不是通过补零本身引入的信息。
  • 如果希望改善频率分辨率或精确性,需要增加采样率或使用更长的FFT长度。

六、资源自取

信号补零对信号频谱的影响

目录
相关文章
|
机器学习/深度学习 自然语言处理 算法
Transformer 模型:入门详解(1)
动动发财的小手,点个赞吧!
14114 1
Transformer 模型:入门详解(1)
雷达波形之一——LFM线性调频波形
雷达波形之一——LFM线性调频波形
1336 1
|
机器学习/深度学习 移动开发 JavaScript
ZC序列理论学习及仿真(一)
ZC序列理论学习及仿真
3464 0
|
机器学习/深度学习
ZC序列理论学习及仿真(三)
ZC序列理论学习及仿真
830 0
|
Linux
【Linux】System V信号量详解以及semget()、semctl()和semop()函数讲解
System V信号量的概念及其在Linux中的使用,包括 `semget()`、`semctl()`和 `semop()`函数的具体使用方法。通过实际代码示例,演示了如何创建、初始化和使用信号量进行进程间同步。掌握这些知识,可以有效解决多进程编程中的同步问题,提高程序的可靠性和稳定性。
716 19
|
7月前
|
算法 数据安全/隐私保护 异构计算
基于FPGA的BPSK+costas环实现,包含testbench,分析不同信噪比对costas环性能影响
本作品基于FPGA实现了BPSK调制解调通信系统与Costas环载波同步,使用Verilog语言完成设计并提供Testbench验证。相比之前版本,优化了环路滤波器以使Costas环收敛曲线接近理论值,并新增AWGN信道模块,支持调整SNR分析噪声对锁定性能的影响。通过Vivado2019.2仿真验证,结果准确无误。核心程序包含信号调制、加性高斯白噪声生成及解调部分,适用于学习载波同步与BPSK通信原理。Costas环结构包括本地振荡器、相位解调器、环路滤波器等组件,用于估计和追踪接收信号的相位偏移,实现精确解调。
301 4
|
算法 数据安全/隐私保护
基于LS算法的OFDM+QPSK系统信道估计均衡matlab性能仿真
基于MATLAB 2022a的仿真展示了OFDM+QPSK系统中最小二乘(LS)算法的信道估计与均衡效果。OFDM利用多个低速率子载波提高频谱效率,通过循环前缀克服多径衰落。LS算法依据导频符号估计信道参数,进而设计均衡器以恢复数据符号。核心程序实现了OFDM信号处理流程,包括加性高斯白噪声的加入、保护间隔去除、快速傅立叶变换及信道估计与均衡等步骤,并最终计算误码率,验证了算法的有效性。
491 2
|
机器学习/深度学习 数据采集 人工智能
从零构建:深度学习模型的新手指南###
【10月更文挑战第21天】 本文将深入浅出地解析深度学习的核心概念,为初学者提供一条清晰的学习路径,涵盖从理论基础到实践应用的全过程。通过比喻和实例,让复杂概念变得易于理解,旨在帮助读者搭建起深度学习的知识框架,为进一步探索人工智能领域奠定坚实基础。 ###
332 3
|
Linux C++
Linux c/c++之makefile的基础使用
Linux下C/C++项目中makefile的基本使用,包括基础、进阶和高级用法,以及如何创建和使用makefile来自动化编译过程。
190 0
Linux c/c++之makefile的基础使用