zoukankan      html  css  js  c++  java
  • FFT

    1. 关于FFT

    原文:https://blog.csdn.net/czyt1988/article/details/84995295

    FFT之后得到的那一串复数是波形对应频率下的幅度特征,注意这个是幅度特征不是幅值。

    获取频率:

    傅里叶变换并没对频率进行任何计算,频率只与采样率和进行傅里叶变换的点数相关。

    FFT变换完的第一个数对应0Hz,即直流分量。后面第二个复数对应的频率是0Hz+频谱分辨率,每隔一个加一次,直到$frac{N}{2}$个数,频谱分辨率$Delta f $计算公式如下:[Delta f{ m{ = }}frac{{Fs}}{N}]其中$Fs$为采样率,$N$为FFT的点数。

    获取幅值:

    假设原始信号的峰值为A,那么FFT的结果的每个点(除了第一个点直流分量之外)的模值就是A的$frac{N}{2}$倍。而第一个点就是直流分量,它的模值是直流分量的$N$倍。

    要得出真实幅值,需要把除了第1个点(i=1)以及最后一个点(i=N/2)除以N以外,其余点需要用求得的模除以$frac{N}{2}$。实际应用中,只有$i = 1$~$frac{N}{2}$是有用的。

    2. MATLAB

    参考:使用 FFT 进行频谱分析

    函数:

    function [Fre,Amp,Ph] = FFT(data,Fs,ampDB,isDetrend)
        % 快速傅里叶变换
        % data:波形数据
        % Fs:采样率
        % ampDB:逻辑值,是否进行对数变换,默认为false
        % isDetrend:逻辑值,是否进行去均值处理,默认为true
        % 返回[Fre:频率,Amp:幅值,Ph:相位(弧度)]
        if nargin<3
            ampDB=false;
            isDetrend=true;
        elseif nargin<4
            isDetrend=true;
        end
        n=length(data);
        if mod(n,2)==1
            n=n-1;
            data=data(1:n);
        end
        if isDetrend
            data=detrend(data);
        end
        Y = fft(data);
        %频率
        Fre=(0:n-1)*Fs/n;
        Fre=Fre(1:n/2);
        %幅值
        Amp=abs(Y(1:n/2));
        Amp([1,n/2])=Amp([1,n/2])/n;
        Amp(2:n/2-1)=Amp(2:n/2-1)/(n/2);
        if ampDB
            Amp=20*log(Amp);
            Amp(Amp<0)=0;
        end
        %相位
        Ph=angle(Y(1:n/2));
    end

    调用示例:

    %生成信号
    N = 256;
    Fs = 150;
    t = (0:N-1)./Fs;
    wave = 5 + 8*cos(2*pi*10.*t) ...
        + 4*cos(2*pi*20.*t + deg2rad(30)) ...
        + 2*cos(2*pi*30.*t + deg2rad(60)) ...
        + 1*cos(2*pi*40.*t + deg2rad(90)) ...
        + rand(1,length(t)) ...
        ;
    
    [Fre,Amp,~]=FFT(wave,Fs,false,false);
    plot(t,wave);

    局部放大:

    plot(Fre,Amp);

    3. Simulink

    以全波桥式整流电路(Full-Wave Bridge Rectifier)为例。

    在MATLAB命令窗口中运行ssc_bridge_rectifier即可打开示例。

    改为固定步长:

    仿真时间0.15s:

    示波器数据保存到工作区,命名为Vout:

    运行仿真:

    工作区分析:

    [FreV,AmpV,PhV]=FFT(Vout.signals.values(201:1501),1e4);
    plot(FreV,AmpV);
    xlim([0 1000]);

    powergui→Tools→FFT Analysis:

    选取对应的信号输入,开始时间,基频,周期等参数即可得到FFT分析结果,同时还有总谐波失真THD。

    可以看到此结果与前面的一致。

    4. R

    函数:

    FFT<-function(data,Fs,ampDB=FALSE,isDetrend=TRUE)
    {
      
      # 快速傅里叶变换
      # data:波形数据
      # Fs:采样率
      # ampDB:逻辑值,是否进行对数变换,默认为false
      # isDetrend:逻辑值,是否进行去均值处理,默认为true
      # 返回[Fre:频率,Amp:幅值,Ph:相位(弧度)]
      n=length(data)
      if(n%%2==1)
      {
        n=n-1
        data=data[1:n]
      }
      if(isDetrend)
      {
        data<-scale(data,center=T,scale=F)
      }
      library(stats)
      Y = fft(data)
      #频率
      Fre=(0:(n-1))*Fs/n
      Fre=Fre[1:(n/2)]
      #幅值
      Amp=Mod(Y[1:(n/2)])
      Amp[c(1,n/2)]=Amp[c(1,n/2)]/n
      Amp[2:(n/2-1)]=Amp[2:(n/2-1)]/(n/2)
      if(ampDB)
      {
        Amp=20*log(Amp)
        Amp[Amp<0]=0
      }
      #相位
      Ph=Arg(Y[1:(n/2)])
      result<-data.frame(Fre=Fre,Amp=Amp,Ph=Ph)
      return(result)
    }

    示例:

    #生成信号
    deg2rad<-function(a)
    {
      return(a*pi/180)
    }
    N = 256
    Fs = 150
    t = (0:(N-1))/Fs
    wave = 5 + 8*cos(2*pi*10.*t) + 
      4*cos(2*pi*20.*t + deg2rad(30)) + 
      2*cos(2*pi*30.*t + deg2rad(60)) + 
      1*cos(2*pi*40.*t + deg2rad(90)) + 
      rnorm(length(t))
    
    result=FFT(wave,Fs,isDetrend=FALSE)
    library(ggplot2)
    theme_set(theme_light())
    qplot(t,wave,geom="line")
    ggplot(data=result,aes(Fre,Amp))+geom_line()

    Shiny示例:https://dingdangsunny.shinyapps.io/FastFourierTransform/

  • 相关阅读:
    微信开发 之 开启开发模式
    微信公众号开发 之 编辑模式使用
    分析各种Android设备屏幕分辨率与适配
    【面向对象设计模式】 适配器模式 (二)
    重构 之 总结代码的坏味道 Bad Smell (一) 重复代码 过长函数 过大的类 过长参数列 发散式变化 霰弹式修改
    【Android 应用开发】Android资源文件
    java 创建并写入文件
    隐藏 HttpClient 在console的日志
    HOW TO CHANGE THE DEFAULT KEY-VALUE SEPARATOR OF A MAPREDUCE JOB
    java 时间戳转换
  • 原文地址:https://www.cnblogs.com/dingdangsunny/p/12573744.html
Copyright © 2011-2022 走看看