Autor Tema: resultado de FFT  (Leído 8415 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado oscarjf

  • PIC10
  • *
  • Mensajes: 10
resultado de FFT
« en: 15 de Julio de 2008, 06:40:33 »
estoy usando el ejemplo de microchip para una FFT, soy nuevo en este asunto de los dsp, y segun el codigo, el resultado es guardado en la direccion 0x1C00 de la ram del dspic, hize una onda senoidal con el dspworks, y los resultados que salen los comparo con matlab, salen muy parecidos, ej, en matlab me sale 3.xxx en el dspic sale 1, luego en matlab sale 6, en el dsp sale 5, pero luego dan numeros inmensos que ya no entiendo porque salen, segun matlab debio de salir un numero cercano al 100, y en el dspic me sale 1070, tengo que realizar alguna conversion?, aqui esta el codigo fuente

#include <p30Fxxxx.h>
#include "dsp.h"
#include "fft.h"

/* Device configuration register macros for building the hex file */
_FOSC(CSW_FSCM_OFF & XT_PLL8);          /* XT with 8xPLL oscillator, Failsafe clock off */
_FWDT(WDT_OFF);                         /* Watchdog timer disabled */
_FBORPOR(PBOR_OFF & MCLR_EN);           /* Brown-out reset disabled, MCLR reset enabled */
_FGS(CODE_PROT_OFF);                    /* Code protect disabled */


/* Extern definitions */
extern fractcomplex sigCmpx[FFT_BLOCK_LENGTH]       /* Typically, the input signal to an FFT  */
__attribute__ ((section (".ydata, data, ymemory"),    /* routine is a complex array containing samples */
aligned (FFT_BLOCK_LENGTH * 2 *2)));            /* of an input signal. For this example, */
                     /* we will provide the input signal in an */
                     /* array declared in Y-data space. */
/* Global Definitions */
#ifndef FFTTWIDCOEFFS_IN_PROGMEM
fractcomplex twiddleFactors[FFT_BLOCK_LENGTH/2]    /* Declare Twiddle Factor array in X-space*/
__attribute__ ((section (".xbss, bss, xmemory"), aligned (FFT_BLOCK_LENGTH*2)));
#else
extern const fractcomplex twiddleFactors[FFT_BLOCK_LENGTH/2]   /* Twiddle Factor array in Program memory */
__attribute__ ((space(auto_psv), aligned (FFT_BLOCK_LENGTH*2)));
#endif

float salida;
int   peakFrequencyBin = 0;            /* Declare post-FFT variables to compute the */
unsigned long peakFrequency = 0;         /* frequency of the largest spectral component */

int main(void)
{
   int i = 0;
   fractional *p_real = &sigCmpx[0].real ;
   fractcomplex *p_cmpx = &sigCmpx[0] ;


#ifndef FFTTWIDCOEFFS_IN_PROGMEM               /* Generate TwiddleFactor Coefficients */
   TwidFactorInit (LOG2_BLOCK_LENGTH, &twiddleFactors[0], 0);   /* We need to do this only once at start-up */
#endif

   for ( i = 0; i < FFT_BLOCK_LENGTH; i++ )/* The FFT function requires input data */
   {               /* to be in the fractional fixed-point range [-0.5, +0.5]*/
      *p_real = *p_real >>1 ;      /* So, we shift all data samples by 1 bit to the right. */
      *p_real++;         /* Should you desire to optimize this process, perform */
   }               /* data scaling when first obtaining the time samples */
                  /* Or within the BitReverseComplex function source code */

   p_real = &sigCmpx[(FFT_BLOCK_LENGTH/2)-1].real ;   /* Set up pointers to convert real array */
   p_cmpx = &sigCmpx[FFT_BLOCK_LENGTH-1] ; /* to a complex array. The input array initially has all */
                  /* the real input samples followed by a series of zeros */


   for ( i = FFT_BLOCK_LENGTH; i > 0; i-- ) /* Convert the Real input sample array */
   {               /* to a Complex input sample array  */
      (*p_cmpx).real = (*p_real--);   /* We will simpy zero out the imaginary  */
      (*p_cmpx--).imag = 0x0000;   /* part of each data sample */
   }

   /* Perform FFT operation */
#ifndef FFTTWIDCOEFFS_IN_PROGMEM
   FFTComplexIP (LOG2_BLOCK_LENGTH, &sigCmpx[0], &twiddleFactors[0], COEFFS_IN_DATA);
#else
   FFTComplexIP (LOG2_BLOCK_LENGTH, &sigCmpx[0], (fractcomplex *) __builtin_psvoffset(&twiddleFactors[0]), (int) __builtin_psvpage(&twiddleFactors[0]));
#endif

   /* Store output samples in bit-reversed order of their addresses */
   BitReverseComplex (LOG2_BLOCK_LENGTH, &sigCmpx[0]);

   /* Compute the square magnitude of the complex FFT output array so we have a Real output vetor */
   SquareMagnitudeCplx(FFT_BLOCK_LENGTH, &sigCmpx[0], &sigCmpx[0].real);//  <---- segun yo eso ya te lo convertia y te lo arrojaba en 0x1C00 por lo que indica el   
       puntero
   

        while (1);   /* Place a breakpoint here and observe the watch window variables */
}

Desconectado vtasco

  • PIC12
  • **
  • Mensajes: 72
Re: resultado de FFT
« Respuesta #1 en: 16 de Julio de 2008, 01:25:48 »
Hola, recuerda que la libraría DSP que entrega microchip, funcionan con numeros del tipo 'fractional' , que va de
-1 hasta casi 1, además, la función FFT, necesita que los valores de la señal que se va a analizar, estén comprendidos entre -0.5 y0.5.

Todo esto hace que el resultado esté escalado, no seva a corresponder directamente con los valores que se obtienen de matlab.

Lo que yo hice, fue comparar la gráfica del resultado calculado con mplab y tb con matlab. Siempre tuve la misma forma, claro que la que entrega la función fft del dsPIC bastante escalada.

Dejo acá una imágen de ejemplo para que te hagas una idea. Corresponde a una señal cuadrada.
http://vtasco.googlepages.com/comparativa-FFT_sqr.png
Saludos
« Última modificación: 16 de Julio de 2008, 01:35:21 por vtasco »

Desconectado oscarjf

  • PIC10
  • *
  • Mensajes: 10
Re: resultado de FFT
« Respuesta #2 en: 20 de Julio de 2008, 19:21:15 »
pero no hay manera de reescalar se pudiera decir al valor original?

Desconectado vtasco

  • PIC12
  • **
  • Mensajes: 72
Re: resultado de FFT
« Respuesta #3 en: 21 de Julio de 2008, 16:03:37 »
Hola, según  el documento DS51456D (16 bit language tools), la salida está escalada por el factor
1 / (sqrt(2N))
.

saludso

Desconectado anibalismo

  • PIC10
  • *
  • Mensajes: 10
resultados 100% comprobados ;)
« Respuesta #4 en: 11 de Mayo de 2010, 16:21:46 »
Diganme pragmatico, pero a veces hay que dar demasiadas vueltas para conseguir info de fft que funcione :s

mi post llueve sobre mojado, y es para confirmar los resultados publicados por vtasco, y aparte, incluir el proyecto, y una imagen de lo que vi :D

La rutina de hace la fft de una señal cuadrada que está en el achivo twiddlefactors... a veces me pasa que cuando exporto archivos a ZIP el mplab no incluye algunas cosas. si a alguien le falta algo, escriba y se lo envio de nuevo!!!

Por cierto, la fft me hace falta para hacer un detector de actividad de voz :s que es un nombre bastante feo para una rutina que distingue entre cuando una persona habla, y cuando no :D si alguien quiere un poco de info de esto, acá DAV.pdf

el codigo está más abajo adjunto, y la imagen en cuestion es:



espero que a alguien le sirva como a mi!!! gracias muchachos!!! cualquier duda acerca de la fft con dspic posteen :) estamos para compartir!!!

Ahh... y los comentarios del codigo estan en formato doxygen, pero todavia no lo domino muy bien :)
« Última modificación: 11 de Mayo de 2010, 16:26:58 por anibalismo »

Desconectado anibalismo

  • PIC10
  • *
  • Mensajes: 10
Re: resultado de FFT
« Respuesta #5 en: 12 de Mayo de 2010, 14:53:47 »
Me quede probando la rutina ayer, y este resultado me dio para una señal senoidal :D

Desconectado vtasco

  • PIC12
  • **
  • Mensajes: 72
Re: resultado de FFT
« Respuesta #6 en: 13 de Mayo de 2010, 01:07:32 »
que bien, aplicaste alguna ventana?

Desconectado anibalismo

  • PIC10
  • *
  • Mensajes: 10
Re: resultado de FFT
« Respuesta #7 en: 13 de Mayo de 2010, 12:21:14 »
Hola Vtasco!   :-/

No entendi tu ultimo comentario  :( ... me podrias explicar mejor lo de la ventana?

Desconectado vtasco

  • PIC12
  • **
  • Mensajes: 72
Re: resultado de FFT
« Respuesta #8 en: 13 de Mayo de 2010, 22:12:08 »
hola:

cuando se obtiene la fft de una señal, se suele aplicar lo que se llama 'ventana' (hanning, hamming y otras),  la más básica es la ventana cuadrada, y entrega la misma ponderación a todas las muestras, en cambio las otras ventanas, ponderan con un nivel menor las muestras del principio y del final del vector.

Se hace esto porque cuando la señal a analizar no tiene una cantidad de ciclos entera dentro del vector a analizar,  aparece ruido espectral, el que tiende a bajar con la aplicación de las ventanas.

C30 tiene funciones para generar varios tipos de ventana y también funciones para aplicarlas al vector.


http://es.wikipedia.org/wiki/Ventana_(función)


Desconectado anibalismo

  • PIC10
  • *
  • Mensajes: 10
Re: resultado de FFT
« Respuesta #9 en: 26 de Mayo de 2010, 14:24:44 »
Hola vtasco, no, no utilize una ventana. Creo que esa respuesta que me dio estaba mal, por razones que todavia no rengo muy claras. Creo que es algo que tiene que ver con los twiddle factors (de nuevo, no estoy seguro de que sea eso)

Pero acá hay otra grafica que creo que si es la que deberia ser ;)



Digo que creo que son los twiddle factors, porque hice una rutina que mas o menos es asi:

   vector=seno(varios valores entre 0 y 2*PI)

   ciclo(true)
   {
       calcula twiddle factors()
       calcula fourier(vector)
       incrementa contador de ciclo
   }

Cuando el contador del ciclo es par, da el resultado que está arriba, un impulso en la mitad de la frecuencia de muestreo. Cuando el ciclo es impar, da el resultado raro, que habia publicado antes, y por el cual supongo que Vtasco pregunto si lo habia pasado por una ventana...

alguien?

Desconectado vtasco

  • PIC12
  • **
  • Mensajes: 72
Re: resultado de FFT
« Respuesta #10 en: 26 de Mayo de 2010, 23:31:44 »
no entiendo bien a qué te refieres con contador de ciclo, viendo tu seudocódigo, creo que estás  calculando los twidlle factors cada vez que obtienes la fft, no es necesario, sólo pierdes tiempo, puedes generarlos una sóla vez y dp multiplicar.

Fíjate bien en los ejemplos que están disponibles en microchip.


Desconectado edwinferia

  • PIC10
  • *
  • Mensajes: 4
Re: resultado de FFT
« Respuesta #11 en: 11 de Agosto de 2010, 14:35:42 »
Hola oscarjf la informacion que publica vtasco es completamente valida, sobre las consideraciones para el formato del argumento de entrada de la FFT, para reescalar nuevamente la informacion simplemente se corren log2(N)  bits a la izquierda. p ejemplo yo use esta rutina para resscalar nuevamente mi informacion con una FFT de 256 puntos.

Código: [Seleccionar]
fractcomplex *pointer1 = &sigCmpx_out[0] ;
         for ( i = 0; i < 256; i++ )
               {
                    (*pointer1).real = (*pointer1).real<<8;
                    (*pointer1).imag = (*pointer1).imag<<8;
                    (*pointer1++);
               }
 


espero te sirva de algo
« Última modificación: 11 de Agosto de 2010, 14:40:00 por edwinferia »

Desconectado Renatox_

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 541
    • máquinas cnc
Re: resultado de FFT
« Respuesta #12 en: 29 de Enero de 2014, 15:09:17 »
Buen día a todos,

Estoy corriendo el ejemplo CE018_FFT_DSPlib sin modificarlo que viene incluido en el XC16 que por lo que veo es el mismo código que viene en el C30.

La entrada en una onda cuadrada de frecuencia 1khz, N=256pts, amplitud=1 en Q15, frecuencia de muestreo=10khz. Observo que la salida se guarda en sigCmpx.real.

Entonces junto todas las partes reales de este vector y lo llevo al Matlab. Aquí uso la función fft y los coeficientes los genero con dspworks

En matLab uso X=fft(x); donde x=onda cuadrada con valores 1(0x7FFF) y -1(0x8001) tal como esta en el vector de entrada del ejemplo CE018.

Grafico los resultados y obtengo esto del Matlab y Mplab respectivamente:



No se parece en nada, La segunda mitad del espectro sale muy diferente me parece que es por la frecuencia de Nyquist, pero la primera mitad los armónicos de 1khz y 3khz no se ven.

Alguien ha simulado este ejemplo tal como está? se obtiene el resultado correcto?

saludos
Renato
control de movimiento