【问题标题】:How to Inverse FFT in Arduino如何在 Arduino 中逆 FFT
【发布时间】:2015-08-13 04:45:33
【问题描述】:

我正在尝试使用 Arduino FFT library 根据以下代码过滤一些数据以进行 FFT(快速傅立叶变换)

/*
fft_adc_serial.pde
guest openmusiclabs.com 7.7.14
example sketch for testing the fft library.
it takes in data on ADC0 (Analog0) and processes them
with the fft. the data is sent out over the serial
port at 115.2kb.
*/

#define LOG_OUT 1 // use the log output function
#define FFT_N 256 // set to 256 point fft

#include <FFT.h> // include the library

void setup() {
  Serial.begin(115200); // use the serial port
  TIMSK0 = 0; // turn off timer0 for lower jitter
  ADCSRA = 0xe5; // set the adc to free running mode
  ADMUX = 0x40; // use adc0
  DIDR0 = 0x01; // turn off the digital input for adc0
}

void loop() {
  while(1) { // reduces jitter
    cli();  // UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i < 512 ; i += 2) { // save 256 samples
      while(!(ADCSRA & 0x10)); // wait for adc to be ready
      ADCSRA = 0xf5; // restart adc
      byte m = ADCL; // fetch adc data
      byte j = ADCH;
      int k = (j << 8) | m; // form into an int

      k -= 0x0200; // form into a signed int
      k <<= 6; // form into a 16b signed int
      fft_input[i] = k; // put real data into even bins
     // Serial.print(millis());
     // Serial.print("input ");
     // Serial.print(i);
    //  Serial.print(" = ");
      Serial.println(k);
      fft_input[i+1] = 0; // set odd bins to 0
      delay(0.1);
    }
    fft_window(); // window the data for better frequency response
    fft_reorder(); // reorder the data before doing the fft
    fft_run(); // process the data in the fft
    fft_mag_log(); // take the output of the fft
    sei();
    Serial.println("start");

   for (byte i = 0; i < FFT_N/2; i++) {
     if(i<10 || i>20)
     {
       fft_log_out[i] = 0;
     }

     Serial.println(fft_log_out[i]);
   }    
  }
}

像这样应用过滤器后:

if(i<10 || i>20)
     {
       fft_log_out[i] = 0;
     }

然后我需要对 FFT 数据进行反演 fft_log_out[]

我寻找了一个逆 FFT 函数(特别是在 http://wiki.openmusiclabs.com/wiki/FFTFunctions 中),但在任何地方都找不到。

那么如何在 Arduino 中获得逆 FFT?

【问题讨论】:

  • 这不是你想要的,只是一个建议。为什么不使用离散滤波器呢?那会更快、更“实时”。

标签: arduino fft ifft


【解决方案1】:

逆FFT可以利用正向变换得到:

for (int i = 0 ; i < 512 ; i += 2) {
  fft_input[i] =  (fft_input[i] >> 8);
  fft_input[i+1] = -(fft_input[i+1] >> 8);
}
fft_reorder();
fft_run();
// For complex data, you would then need to negate the imaginary part
// but we can skip this step since you have real data.

但请注意,您的过滤代码存在一些问题。

首先,前向 FFT 的结果是带有幅度和相位信息的复数。使用fft_mag_log 只取幅值,仅靠幅值不足以恢复原始信号。因此,您应该使用留在fft_input 数组中的完整 FFT 输出作为过滤代码的输入。

其次,实值数据的 FFT 产生具有厄米对称性的频谱。要获得实值滤波输出,您必须保持这种对称性。 因此,您不应将频谱上半部分的值完全归零:

for (byte i = 0; i < FFT_N; i+=2) {
  if (! ((i>=20 && i<=40) || (i>=FFT_N-40 && i<=FFT_N-20)))
  {
    fft_input[i] = 0;
    fft_input[i+1] = 0;
  }
}

第三,过滤将彼此独立地应用于每个数据块,始终假设先前的输入为零。这通常会导致块边界处的不连续性。为避免这种情况,您应该考虑使用overlap-add method

【讨论】:

  • 我想过滤特定的“频率”,但据我所知 [fft_input[i] = 0] 意味着过滤特定的“时间”
  • Arduino 将 FFT 的输出放回fft_input,所以fft_input[i]=0 FFT 运行后会过滤特定频率。
  • 我遵循上 Inserver FFT 代码,但我无法恢复原始信号代码 :(
  • 请注意,全圆 FFT 涉及按 1/FFT_N 缩放。如果您从弱信号开始,它们可能会在此过程中缩小太多。您可以尝试在正向 FFT 之前对信号进行归一化以使用满量程,然后在反向 FFT 之后将它们按相同的比例缩小。
猜你喜欢
  • 1970-01-01
  • 2012-04-30
  • 2015-11-15
  • 1970-01-01
  • 1970-01-01
  • 2018-07-12
  • 1970-01-01
  • 2013-05-22
  • 2018-03-16
相关资源
最近更新 更多