用MATLAB的FFT函数对已测时域数据进行傅立叶变换

2023-12-19 07:20

本文主要是介绍用MATLAB的FFT函数对已测时域数据进行傅立叶变换,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

用MATLAB的FFT函数对已测时域数据进行傅立叶变换

一、原理

FFT:快速傅立叶变换
1.相关代码用法

Y = fft(X) 
%计算X的离散傅立叶变换,实质是返回一个向量或多个向量的傅立叶变换Y = fft(X,n) 
%n指定Y的长度,如果未指定,默认X的长度与Y的长度相等Y = fft(X,n,dim) 
%如果X是矩阵,则fft(X,n,2)返回每行的n点傅里叶变换

2.示例代码的理解

比较时域和频域中的余弦波。
指定信号的参数,采样频率为 1kHz,信号持续时间为 1 秒。

Fs = 1000;                % Sampling frequency
T = 1/Fs;                 % Sampling period
L = 1000;                 % Length of signal
t = (0:L-1)*T;            % Time vector

注释:L代表采样个数,t是一个离散向量,代表每隔采样时间T进行一次采样,总共采L次样,所以总的时间区间为(0:L-1)*T。

创建一个矩阵,其中每一行代表一个频率经过缩放的余弦波。结果 X 为 3×1000 矩阵。第一行的波频为 50,第二行的波频为 150,第三行的波频为 300。

x1 = cos(2*pi*50*t);          % First row wave
x2 = cos(2*pi*150*t);         % Second row wave
x3 = cos(2*pi*300*t);         % Third row wave
X = [x1; x2; x3];

x1,x2,x3是由离散序列t产生的离散向量,X是三个行向量组成的矩阵,其列的长度取决于定义的L的长度。

在单个图窗中按顺序绘制 X 的每行的前 100 个项,并比较其频率。

for i = 1:3subplot(3,1,i) %把画图空间分成三行一列,在第i行进行画图plot(t(1:100),X(i,1:100))title(['Row ',num2str(i),' in the Time Domain'])
end

出于算法性能的考虑,fft 允许用尾随零填充输入。在这种情况下,用零填充 X 的每一行,以使每行的长度为比当前长度大的下一个最小的 2 的次幂值。使用 nextpow2 函数定义新长度。

n = 2^nextpow2(L);
% 举个例子,如果x等于100,则y=7,因为27次方==128,而128是所有大于100的,二的整数次幂数字中最小的一个dim = 2;
%指定dim参数沿X的行(即对每个信号)使用fft。dim=2时沿行返回每个离散序列的傅立叶变换Y = fft(X,n,dim);P2 = abs(Y/L); 
% 计算双侧频谱 P2
P1 = P2(:,1:n/2+1);	
% 将P2的前半段信号赋给P1,P1即是我们关心的部分
P1(:,2:end-1) = 2*P1(:,2:end-1);
%计算每个信号的双侧频谱和单侧频谱。for i=1:3subplot(3,1,i)plot(0:(Fs/n):(Fs/2-Fs/n),P1(i,1:n/2))title(['Row ',num2str(i),' in the Frequency Domain'])
end
%在频域内,为单个图窗中的每一行绘制单侧幅值频谱。

3.理解学习
参考资料:Matlab中fft函数的使用与原理

(1)Fn = (n-1)* Fs /N

Fn是第n点所表示的真实频率值。当然,n只取前一半的点就足够了。这样,可以达到的频率分辨率即为Fs/N。

(2)幅值的处理

作FFT分析时,幅值大小与输入点数有关,要得到真实的幅值大小,需要将变换后的结果除以N。且由于零频在双边谱中本没有被一分为二,所以对于零频外的点还有乘以2,得到的才是真实的频率幅值。

(3)基频

​若分析数据时长为T,则分析结果的基频就是f0=1/T,分析结果的频率序列为[0:N-1]*f0

二、运用

从实验室里的NI里导出了一个时域波形的数据,是对正弦信号进行采样保持后从采样保持器里输出的信号,实验目的是对时域的数据进行fft处理的到频谱图,然后与NI频谱分析仪里面的频谱图进行对比,观察是否一致。

待处理数据是时间区间为[24.890153,24.910153],采样信号频率为1000Hz,被采样信号频率为100Hz的正弦信号

总的时间区间的长度为 t = 24.91 - 24.89 = 0.02 s
采样频率为1000Hz,采样周期T = 0.001 s
故在这个时间长度里总共能进行L = 0.02/0.001 + 1 = 21次采样
但是总共导出了2500个数据,从这2500个数据中等间隔抽出21个数据,作为傅立叶变换的离散序列。2500/20 = 125。(如果t = 0.2s要考虑:根据抽样保持的特殊性,可以选择每隔12.5*k,然后在excel中截去小数向上取整数 (=CEILING(A1,1))来选取每一个离散点,即=CEILING(A1,1),然后总的操作方法就是在excel表格里面输入:=OFFSET(A$1,CEILING(ROW(A1)*12.5,1),),然后再让时间区间里面的每个时间点减去起始记录时间时间24.91,得到新的时间区间为[0,0.2] )

得到第13列为时间离散序列t,14列为对应的采样值。

请添加图片描述

对应的代码如下

clc;clear;close all;
load('EP01')x1 = EP01(1:21,13);
y1 = EP01(1:21,14);  %需要做傅立叶变换的一组数据
N = 21;   %信号的长度,能不能等价于待处理的数据有多少个
Fs = 1000;yk=fft(y1);      % 傅立叶变换
P2 = abs(yk/N); 
% 计算双侧频谱 P2
P1 = P2(1:N/2+1);	
% 将P2的前半段信号赋给P1,P1即是我们关心的部分
P1(2:end-1) = 2*P1(2:end-1);
%计算每个信号的双侧频谱和单侧频谱。
plot(0:round(Fs/N):round(Fs/2-Fs/N),P1(1:N/2))title('FFT变换')
legend('matlab进行输出信号的fft变换')
xlabel('频率/Hz')
ylabel('归一化幅度')

得到的频谱图如下
请添加图片描述

如果再经过一个低通滤波器,应该会有更完美的频谱特性。

接下来对采样保持输出器的信号做频谱分析。经过采样保持器后的波形如下:
在这里插入图片描述

同理:
NI的采样频率为Ts = 125000
N = 2500
代入代码即可

clc;clear;close all;
load('EP01')
x = EP01(1:400,11);
y = EP01(1:400,12);
% y = EP01(1:2500,9);x1 = EP01(1:2500,10);
y1 = EP01(1:2500,9);  %需要做傅立叶变换的一组数据
N = 2500;   %信号的长度,能不能等价于待处理的数据有多少个
Fs = 125000;subplot(211);   %分为两行一列在第一个位置画图
plot(x,y)
% xlim([24.89,24.91])
grid on 
legend('采样保持器的输出信号的频域波形')
xlabel('频率/Hz')
ylabel('dB')yk=fft(y1);      % 傅立叶变换
P2 = abs(yk/N); 
% 计算双侧频谱 P2
P1 = P2(1:N/2+1);	
% 将P2的前半段信号赋给P1,P1即是我们关心的部分
P1(2:end-1) = 2*P1(2:end-1);
%计算每个信号的双侧频谱和单侧频谱。
subplot(212);plot(0:round(Fs/N):round(Fs/2-Fs/N),abs(P1(1:N/2)))
% plot(x1,abs(yk));
xlim([0;40000])
title('FFT变换')
legend('matlab进行输出信号的fft变换')
xlabel('频率/Hz')
ylabel('归一化幅度')

画出来的频谱图和实际导出来的不太一样,找到原因了后续改正。

在这里插入图片描述

这篇关于用MATLAB的FFT函数对已测时域数据进行傅立叶变换的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/511347

相关文章

SpringBoot分段处理List集合多线程批量插入数据方式

《SpringBoot分段处理List集合多线程批量插入数据方式》文章介绍如何处理大数据量List批量插入数据库的优化方案:通过拆分List并分配独立线程处理,结合Spring线程池与异步方法提升效率... 目录项目场景解决方案1.实体类2.Mapper3.spring容器注入线程池bejsan对象4.创建

PHP轻松处理千万行数据的方法详解

《PHP轻松处理千万行数据的方法详解》说到处理大数据集,PHP通常不是第一个想到的语言,但如果你曾经需要处理数百万行数据而不让服务器崩溃或内存耗尽,你就会知道PHP用对了工具有多强大,下面小编就... 目录问题的本质php 中的数据流处理:为什么必不可少生成器:内存高效的迭代方式流量控制:避免系统过载一次性

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

MyBatis-plus处理存储json数据过程

《MyBatis-plus处理存储json数据过程》文章介绍MyBatis-Plus3.4.21处理对象与集合的差异:对象可用内置Handler配合autoResultMap,集合需自定义处理器继承F... 目录1、如果是对象2、如果需要转换的是List集合总结对象和集合分两种情况处理,目前我用的MP的版本

GSON框架下将百度天气JSON数据转JavaBean

《GSON框架下将百度天气JSON数据转JavaBean》这篇文章主要为大家详细介绍了如何在GSON框架下实现将百度天气JSON数据转JavaBean,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录前言一、百度天气jsON1、请求参数2、返回参数3、属性映射二、GSON属性映射实战1、类对象映

C# LiteDB处理时间序列数据的高性能解决方案

《C#LiteDB处理时间序列数据的高性能解决方案》LiteDB作为.NET生态下的轻量级嵌入式NoSQL数据库,一直是时间序列处理的优选方案,本文将为大家大家简单介绍一下LiteDB处理时间序列数... 目录为什么选择LiteDB处理时间序列数据第一章:LiteDB时间序列数据模型设计1.1 核心设计原则

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

Python Counter 函数使用案例

《PythonCounter函数使用案例》Counter是collections模块中的一个类,专门用于对可迭代对象中的元素进行计数,接下来通过本文给大家介绍PythonCounter函数使用案例... 目录一、Counter函数概述二、基本使用案例(一)列表元素计数(二)字符串字符计数(三)元组计数三、C

Java+AI驱动实现PDF文件数据提取与解析

《Java+AI驱动实现PDF文件数据提取与解析》本文将和大家分享一套基于AI的体检报告智能评估方案,详细介绍从PDF上传、内容提取到AI分析、数据存储的全流程自动化实现方法,感兴趣的可以了解下... 目录一、核心流程:从上传到评估的完整链路二、第一步:解析 PDF,提取体检报告内容1. 引入依赖2. 封装