2017-02-17 7 views
1

最近、私はSTM32F4-Discovery評価ボードでFFT計算を行い、それをPCに送信しようとしていました。私は私の問題を見てきました - 私は、私が製造元が提供するFFT関数に何か間違っていると思います。DSPライブラリ - RFFT - 奇妙な結果

私はCMSIS-DSPライブラリを使用しています。 今のところ私はコードでサンプルを生成しています(正しい場合はマイクでサンプリングします)。

私のデータは、将来的にフロートであることを行っていると私はarm_rfft_fast_f32を使用していますが、私は私の出力配列で取得結果は(と思う)非常識です - 私は0

number_of_samples = 512; (l_probek in code) 
dt = 1/freq/number_of_samples 
以下の周波数を取得していますここで

私のコードは私のデータがで山車あることを行っているとして、私はarm_rfft_fast_f32を使用してい

float32_t buffer_input[l_probek]; 
uint16_t i; 
uint8_t mode; 
float32_t dt; 
float32_t freq; 
bool DoFlag = false; 
bool UBFlag = false; 
uint32_t rozmiar = 4*l_probek; 

union 
{ 
    float32_t f[l_probek]; 
    uint8_t b[4*l_probek]; 
}data_out; 


union 
{ 
    float32_t f[l_probek]; 
    uint8_t b[4*l_probek]; 
}data_mag; 

union 
{ 
    float32_t f; 
    uint8_t b[4]; 
}czest_rozdz; 


/* Pointers ------------------------------------------------------------------*/ 
arm_rfft_fast_instance_f32 S; 
arm_cfft_radix4_instance_f32 S_CFFT; 
uint16_t output; 
/* ---------------------------------------------------------------------------*/ 
int main(void) 
{ 
    freq = 5000; 
    dt = 0.000000390625; 


    _GPIO(); 
    _LED(); 
    _NVIC();  
    _EXTI(0); 

    arm_rfft_fast_init_f32(&S, l_probek); 
    GPIO_SetBits(GPIOD, LED_Green); 

    mode = 2; 


    //----------------- Infinite loop 
    while (1) 
    { 
     if(true)//(UBFlag == true) 

        for(i=0; i<l_probek; ++i) 
        { 
         buffer_input[i] = (float32_t) 15*sin(2*PI*freq*i*dt); 
        } 

      //Obliczanie FFT 
      arm_rfft_fast_f32(&S, buffer_input, data_out.f, 0); 
      //Obliczanie modulow 
      arm_cmplx_mag_f32(data_out.f, data_mag.f, l_probek); 

      USART_putdata(USART1, data_out.b, data_mag.b, rozmiar); 
      //USART_putdata(USART1, czest_rozdz.b, data_mag.b, rozmiar); 
      GPIO_ToggleBits(GPIOD, LED_Orange); 
      //mode++; 
      //UBFlag = false; 

     } 

    } 
} 
+0

は、あなたの入力SAことを確認しましたmplesはあなたのテストに合っていますか?また、l_probekの値は?それは512ですか? –

+0

@DaveS彼は 'buffer_input'でテスト正弦波を計算しているようです。 – tofro

+0

この行について - 15の振幅はどのように決定しましたか? buffer_input [i] =(float32_t)15 * sin(2 * PI * freq * i * dt); –

答えて

2

です私は私の出力配列で取得し、将来が、結果は(と思う)非常識です - 私は、arm_rfft_fast_f32関数は周波数を返しませんが、かなり複雑な値係数がFast Fourier Transform (FFT)を使用して計算0

以下の周波数を取得しています。従って、それらの係数が負であることは完全に合理的である。より具体的には、15の振幅を使用してシングルサイクルsinテストトーン入力の期待係数は次のようになります

0.0,  0.0; // special case packing real-valued X[0] and X[N/2] 
0.0, -3840.0; // X[1] 
0.0,  0.0; // X[2] 
0.0,  0.0; // X[3] 
... 
0.0,  0.0; // X[255] 

documentationに示すように最初の二つの出力が純粋に実係数X[0]X[N/2]に対応します(後のarm_cmplx_mag_f32への呼び出しでこの特別なケースに特に注意する必要があります;以下の最後の点を参照してください)。

X[0] -> 0*freq*l_probek/l_probek =    0 
X[1] -> 1*freq*l_probek/l_probek = freq = 5000 
X[2] -> 2*freq*l_probek/l_probek = 2*freq = 10000 
X[3] -> 3*freq*l_probek/l_probek = 2*freq = 15000 
... 

これらの周波数成分の各々の周波数はNは(あなたのケースl_probekにおける)サンプルの数であり、fs = 1/dtは(あなたのケースfreq*l_probekに)サンプリングレートでk*fs/N、によって与えられます。 N/2+1大きさを計算するときに最後に、最初の2つの値の特殊な梱包のために、あなたは注意する必要があります。

// General case for the magnitudes 
arm_cmplx_mag_f32(data_out.f+2, data_mag.f+1, l_probek/2 - 1); 
// Handle special cases 
data_mag.f[0]   = data_out.f[0]; 
data_mag.f[l_probek/2] = data_out.f[1]; 
+0

本当にありがとうございます。私は頭がおかしいと思っています; また、私はFFT用のサンプルを生成しています。 私は選択した頻度に間違った** dt **をしました。 また、今朝、値を生成するために** sinf **関数を使用することが賢明であることを確認しました。 – Jejh

+0

もう1つの質問があります。普通のことですが、 arm_rfft_fast_f3関数を呼び出すと、入力配列が変更されます。 – Jejh

+1

はい、要するに、その機能の仕組みです。より長い答えは、 'arm_rfft_fast_f32'が[' arm_cfft_f32'](https://www.keil.com/pack/doc/CMSIS/DSP/html/group__ComplexFFT)を利用することです。html#gade0f9c4ff157b6b9c72a1eafd86ebf80)、これは入力バッファを使用してインプレース計算を行います(したがって入力を変更します)。 – SleuthEye