2017-02-17 1 views
1

Récemment, j'ai essayé de faire des calculs FFT sur ma carte d'évaluation STM32F4-Discovery, puis de l'envoyer au PC. J'ai examiné mon problème - je pense que je fais quelque chose de mal avec les fonctions FFT fournies par le fabricant. J'utilise les bibliothèques CMSIS-DSP. Pour l'instant, j'ai généré des échantillons avec du code (si cela fonctionne correctement, je vais faire un échantillonnage par microphone).Bibliothèques DSP - RFFT - résultats étranges

J'utilise arm_rfft_fast_f32 que mes données vont être flotte dans l'avenir, mais les résultats que je reçois dans mon tableau de sortie sont fous (je pense) - Je reçois des fréquences inférieures à 0.

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

Voici mon code

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

avez-vous vérifié que votre entrée sa Les échantillons sont-ils corrects pour votre test? Aussi, quelle est la valeur de l_probek? Est-ce 512? –

+0

@DaveS Il semble calculer sur une onde sinusoïdale de test dans 'buffer_input'. – tofro

+0

Concernant cette ligne - Comment avez-vous déterminé l'amplitude de 15? buffer_input [i] = (float32_t) 15 * sin (2 * PI * freq * i * dt); –

Répondre

2

J'utilise arm_rfft_fast_f32 que mes données vont être flotteurs en l'avenir, mais les résultats que je reçois dans mon tableau de sortie sont fous (je pense) - Je reçois des fréquences inférieures à 0.

La fonction arm_rfft_fast_f32 ne retourne pas les fréquences, mais plutôt des coefficients complexes à valeur calculée à l'aide du Fast Fourier Transform (FFT) . Il est donc parfaitement raisonnable que ces coefficients soient négatifs. Plus précisément, les coefficients prévus pour votre seul cycle sin entrée de tonalité de test avec une amplitude de 15 seraient:

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] 

Notez que, comme indiqué dans le documentation les deux premières sorties correspondent aux coefficients purement réels X[0] et X[N/2] (vous devriez faire particulièrement attention à ce cas particulier dans votre prochain appel au arm_cmplx_mag_f32, voir le dernier point ci-dessous).

La fréquence de chacune de ces composantes de fréquence sont donnés par k*fs/N, où N est le nombre d'échantillons (dans le cas l_probek) et fs = 1/dt est la fréquence d'échantillonnage (dans le cas 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 
... 

Enfin, en raison de l'emballage spécial des deux premières valeurs, vous devez être prudent lors du calcul des grandeurs 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

Merci beaucoup SleuthEye. Merde, je commence à penser que je suis sans cervelle;) Aussi j'ai vissé la génération d'échantillons pour ma FFT. A pris le mauvais ** dt ** à la fréquence que j'ai choisi. Aussi ce matin, j'ai vérifié qu'il serait plus sage d'utiliser la fonction ** sinf ** pour générer des valeurs. – Jejh

+0

J'ai encore une question à vous poser: est-ce normal qu'après avoir appelé la fonction 'arm_rfft_fast_f3', mon tableau d'entrée soit changé? – Jejh

+1

Oui, en bref c'est comme ça que ça fonctionne. La réponse la plus longue est que 'arm_rfft_fast_f32' utilise [' arm_cfft_f32'] (https://www.keil.com/pack/doc/CMSIS/DSP/html/group__ComplexFFT.html # gade0f9c4ff157b6b9c72a1eafd86ebf80) qui fait un calcul sur place en utilisant le tampon d'entrée (modifiant ainsi l'entrée). – SleuthEye