2017-02-17 4 views
1

Недавно я пытался делать вычисления FFT на своей оценочной плате STM32F4-Discovery, а затем отправлять его на ПК. Я рассмотрел свою проблему - я думаю, что я делаю что-то неправильно с функциями FFT, предоставляемыми производителем.Библиотеки DSP - RFFT - странные результаты

Я использую библиотеки CMSIS-DSP. На данный момент я создавал образцы с кодом (если это работает правильно, я сделаю выборку с помощью микрофона).

Я использую arm_rfft_fast_f32 как мои данные будут поплавки в будущем, но результаты я получаю в моем выходном массиве душевнобольные (я думаю) - я получаю частоты ниже 0.

number_of_samples = 512; (l_probek in code) 
dt = 1/freq/number_of_samples 

Вот мой код

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

Подтвердили ли вы, что ваш вход са сферы правильны для вашего теста? Кроме того, какова ценность 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 как мои данные будут поплавки в будущие, но результаты, которые я получаю в моем выходном массиве душевнобольные (я думаю) - я получаю частоты ниже 0.

arm_rfft_fast_f32 функция не возвращает частоты, а скорее комплекснозначные коэффициенты вычисляются с использованием Fast Fourier Transform (FFT) , Таким образом, вполне разумно, чтобы эти коэффициенты были отрицательными. Более конкретно, ожидаемые коэффициенты для вашего однотактного sin Тестового входа тона с амплитудой 15 будут:

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, см. последний пункт ниже).

Частота каждого из этих частотных составляющих даются k*fs/N, где N является количество образцов (в вашем случае l_probek) и fs = 1/dt представляет частоту дискретизации (в вашем случае freq*l_probek):

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/2+1 величин:

// 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

Большое спасибо SleuthEye. Черт, я начинаю думать, что я безмозглый;) Также я прикрутил генераторные образцы для моего БПФ. Взял неправильный ** dt ** на частоту, которую я выбрал. Также этим утром я проверил, что было бы разумнее использовать функцию ** sinf ** для генерации значений. – Jejh

+0

У меня есть еще один вопрос к вам - это нормально, что после вызова функции '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

Смежные вопросы