TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: cerebro en 16 de Julio de 2009, 00:40:06

Título: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: cerebro en 16 de Julio de 2009, 00:40:06
Como indica el titulo estoy tratando de de implementar una rutina que encontré que calcula la FFT en 16 puntos utilizando 10 multiplicaciones y 79 sumas, ya se que la capacidad del pic no es la mejor y que vienen librerías para FFT de la gama alta pero me pareció un buen desafió e interesantes para pequeños proyectos(de ahí lo de inventar la rueda  :mrgreen:).
 El problema es que no puedo ver la salida del micro  :(, no se si estoy utilizando mal la función printf o si es problema del cálculo con floats. Les dejo el código hasta el momento...

Código: C
  1. #include <18f4550.h>
  2. #fuses XTPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,NOVREGEN
  3. #use delay(clock=48000000)
  4.  
  5. #use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
  6.  
  7.  
  8.  
  9. #define SIN_2PI_16 0.38268343236508978
  10. #define SIN_4PI_16 0.707106781186547460
  11. #define SIN_6PI_16 0.923879532511286740
  12. #define C_P_S_2PI_16 1.30656296487637660
  13. #define C_M_S_2PI_16 0.54119610014619690
  14. #define C_P_S_6PI_16 1.3065629648763766
  15. #define C_M_S_6PI_16 -0.54119610014619690
  16.  
  17. /* INPUT: float input[16], float output[16] */
  18. /* OUTPUT: none */
  19. /* EFFECTS:  Places the 16 point fft of input in output in a strange */
  20. /* order using 10 real multiplies and 79 real adds. */
  21. /* Re{F[0]}= out0 */
  22. /* Im{F[0]}= 0 */
  23. /* Re{F[1]}= out8 */
  24. /* Im{F[1]}= out12 */
  25. /* Re{F[2]}= out4 */
  26. /* Im{F[2]}= -out6 */
  27. /* Re{F[3]}= out11 */
  28. /* Im{F[3]}= -out15 */
  29. /* Re{F[4]}= out2 */
  30. /* Im{F[4]}= -out3 */
  31. /* Re{F[5]}= out10 */
  32. /* Im{F[5]}= out14 */
  33. /* Re{F[6]}= out5 */
  34. /* Im{F[6]}= -out7 */
  35. /* Re{F[7]}= out9 */
  36. /* Im{F[7]}= -out13 */
  37. /* Re{F[8]}= out1 */
  38. /* Im{F[8]}=0 */
  39. /* F[9] through F[15] can be found by using the formula */
  40. /* Re{F[n]}=Re{F[(16-n)mod16]} and Im{F[n]}= -Im{F[(16-n)mod16]} */
  41.  
  42. /* Note using temporary variables to store intermediate computations */
  43. /* in the butterflies might speed things up.  When the current version */
  44. /* needs to compute a=a+b, and b=a-b, I do a=a+b followed by b=a-b-b.  */
  45. /* So practically everything is done in place, but the number of adds */
  46. /* can be reduced by doinc c=a+b followed by b=a-b. */
  47.  
  48. /* The algorithm behind this program is to find F[2k] and F[4k+1] */
  49. /* seperately.  To find F[2k] we take the 8 point Real FFT of x[n]+x[n+8] */
  50. /* for n from 0 to 7.  To find F[4k+1] we take the 4 point Complex FFT of */
  51. /* exp(-2*pi*j*n/16)*{x[n] - x[n+8] + j(x[n+12]-x[n+4])} for n from 0 to 3.*/
  52.  
  53.  
  54.   float data[16];
  55.   float output[16];
  56.   float zero;
  57. //  int k;
  58.  
  59.  
  60. void R16SRFFT(float input[16]) {
  61.  
  62.   float temp, out0, out1, out2, out3, out4, out5, out6, out7, out8;
  63.   float out9,out10,out11,out12,out13,out14,out15;
  64.  
  65.   out0=input[0]+input[8]; /* output[0 through 7] is the data that we */
  66.   out1=input[1]+input[9]; /* take the 8 point real FFT of. */
  67.   out2=input[2]+input[10];
  68.   out3=input[3]+input[11];
  69.   out4=input[4]+input[12];
  70.   out5=input[5]+input[13];
  71.   out6=input[6]+input[14];
  72.   out7=input[7]+input[15];
  73.  
  74.  
  75.  
  76.   out8=input[0]-input[8];   /* inputs 8,9,10,11 are */
  77.   out9=input[1]-input[9];   /* the Real part of the */
  78.   out10=input[2]-input[10]; /* 4 point Complex FFT inputs.*/
  79.   out11=input[3]-input[11];
  80.   out12=input[12]-input[4]; /* outputs 12,13,14,15 are */
  81.   out13=input[13]-input[5]; /* the Imaginary pars of  */
  82.   out14=input[14]-input[6]; /* the 4 point Complex FFT inputs.*/
  83.   out15=input[15]-input[7];
  84.  
  85.   /*First we do the "twiddle factor" multiplies for the 4 point CFFT */
  86.   /*Note that we use the following handy trick for doing a complex */
  87.   /*multiply:  (e+jf)=(a+jb)*(c+jd) */
  88.   /*   e=(a-b)*d + a*(c-d)   and    f=(a-b)*d + b*(c+d)  */
  89.  
  90.   /* C_M_S_2PI/16=cos(2pi/16)-sin(2pi/16) when replaced by macroexpansion */
  91.   /* C_P_S_2PI/16=cos(2pi/16)+sin(2pi/16) when replaced by macroexpansion */
  92.   /* (SIN_2PI_16)=sin(2pi/16) when replaced by macroexpansion */
  93.   temp=(out13-out9)*(SIN_2PI_16);
  94.   out9=out9*(C_P_S_2PI_16)+temp;
  95.   out13=out13*(C_M_S_2PI_16)+temp;
  96.  
  97.   out14=out14*(SIN_4PI_16);
  98.   out10=out10*(SIN_4PI_16);
  99.   out14=out14-out10;
  100.   out10=out14+out10+out10;
  101.  
  102.   temp=(out15-out11)*(SIN_6PI_16);
  103.   out11=out11*(C_P_S_6PI_16)+temp;
  104.   out15=out15*(C_M_S_6PI_16)+temp;
  105.  
  106.   /* The following are the first set of two point butterfiles */
  107.   /* for the 4 point CFFT */
  108.  
  109.   out8=out8+out10;
  110.   out10=out8-out10-out10;
  111.  
  112.   out12=out12+out14;
  113.   out14=out12-out14-out14;
  114.  
  115.   out9=out9+out11;
  116.   out11=out9-out11-out11;
  117.  
  118.   out13=out13+out15;
  119.   out15=out13-out15-out15;
  120.  
  121.   /*The followin are the final set of two point butterflies */
  122.   output[1]=out8+out9;
  123.   output[7]=out8-out9;
  124.  
  125.   output[9]=out12+out13;
  126.   output[15]=out13-out12;
  127.  
  128.   output[5]=out10+out15;        /* implicit multiplies by */
  129.   output[13]=out14-out11;        /* a twiddle factor of -j */                            
  130.   output[3]=out10-out15;  /* implicit multiplies by */
  131.   output[11]=output[11]-out14-out11;  /* a twiddle factor of -j */
  132.  
  133.  
  134.   /* What follows is the 8-point FFT of points output[0-7] */
  135.   /* This 8-point FFT is basically a Decimation in Frequency FFT */
  136.   /* where we take advantage of the fact that the initial data is real*/
  137.  
  138.   /* First set of 2-point butterflies */
  139.    
  140.   out0=out0+out4;
  141.   out4=out0-out4-out4;
  142.   out1=out1+out5;
  143.   out5=out1-out5-out5;
  144.   out2=out2+out6;
  145.   out6=out2-out6-out6;
  146.   out3=out3+out7;
  147.   out7=out3-out7-out7;
  148.  
  149.   /* Computations to find X[0], X[4], X[6] */
  150.  
  151.   output[0]=out0+out2;
  152.   output[4]=out0-out2;
  153.   out1=out1+out3;
  154.   output[12]=out3+out3-out1;
  155.  
  156.   output[0]=output[0]+out1;  /* Real Part of X[0] */
  157.   output[8]=output[0]-out1-out1; /*Real Part of X[4] */
  158.   /* out2 = Real Part of X[6] */
  159.   /* out3 = Imag Part of X[6] */
  160.  
  161.   /* Computations to find X[5], X[7] */
  162.  
  163.   out5=out5*SIN_4PI_16;
  164.   out7=out7*SIN_4PI_16;
  165.   out5=out5-out7;
  166.   out7=out5+out7+out7;
  167.  
  168.   output[14]=out6-out7; /* Imag Part of X[5] */
  169.   output[2]=out5+out4; /* Real Part of X[7] */
  170.   output[6]=out4-out5; /*Real Part of X[5] */
  171.   output[10]=-out7-out6; /* Imag Part of X[7] */
  172.  
  173.  
  174.   printf(" %2.2f %2.2f\n\r",output[0],zero);
  175.   printf(" %2.2f %2.2f\n\r",output[1],output[9]);
  176.   printf(" %2.2f %2.2f\n\r",output[2],output[10]);
  177.   printf(" %2.2f %2.2f\n\r",output[3],output[11]);
  178.   printf(" %2.2f %2.2f\n\r",output[4],output[12]);
  179.   printf(" %2.2f %2.2f\n\r",output[5],output[13]);
  180.   printf(" %2.2f %2.2f\n\r",output[6],output[14]);
  181.   printf(" %2.2f %2.2f\n\r",output[7],output[15]);
  182.   printf(" %2.2f %2.2f\n\r",output[8],zero);
  183.   printf(" %2.2f %2.2f\n\r",output[7],-output[15]);
  184.   printf(" %2.2f %2.2f\n\r",output[6],-output[14]);
  185.   printf(" %2.2f %2.2f\n\r",output[5],-output[13]);
  186.   printf(" %2.2f %2.2f\n\r",output[4],-output[12]);
  187.   printf(" %2.2f %2.2f\n\r",output[3],-output[11]);
  188.   printf(" %2.2f %2.2f\n\r",output[2],-output[9]);
  189.   printf(" %2.2f %2.2f\n\r",output[1],-output[8]);
  190. }
  191.  
  192.  
  193.  
  194.  
  195.  
  196. void main() {
  197.  
  198. //data 1 23 15 8 9 1 2 3 4 5 2 4 6 8 0
  199.  
  200.    zero=0;
  201.    data[0]=1;
  202.    data[1]=23;
  203.    data[2]=15;
  204.    data[3]=8;
  205.    data[4]=9;
  206.    data[5]=1;
  207.    data[6]=2;
  208.    data[7]=3;
  209.    data[8]=4;
  210.    data[9]=5;
  211.    data[10]=2;
  212.    data[11]=4;
  213.    data[12]=6;
  214.    data[13]=8;
  215.    data[14]=0;
  216.    data[15]=0;
  217.    
  218. //----------------------------------
  219.  
  220.    disable_interrupts(global);
  221.    disable_interrupts(int_timer1);
  222.    disable_interrupts(int_rda);
  223.    disable_interrupts(int_ext);
  224.    disable_interrupts(int_ext1);
  225.    disable_interrupts(int_ext2);
  226.    setup_spi(FALSE);
  227.    setup_psp(PSP_DISABLED);
  228.    setup_comparator(NC_NC_NC_NC);
  229.    setup_vref(FALSE);
  230.    port_b_pullups(FALSE);    
  231.  
  232. //---------------------------  
  233.  
  234.  
  235. for(;;){
  236.    
  237.  
  238.  R16SRFFT(data);
  239.  
  240.  delay_ms(500);
  241.   }
  242. }
  243.  
  244.  
  245.  
  246. /*
  247. 91 + 0i
  248. 26,358765205042054 - 18,59438622703722i
  249. -2,998370275568188 - 28,31592789979983i  
  250. -18,309016994374947 - 16,616988753597195i  
  251. -10,178425317543107 - 23,190667119105044i  
  252. -12,5 - 18,186533479473212i  
  253. -17,190983005625053 - 5,012552719206482i  
  254. -3,181969611930761 - 0,387281014208582i  
  255. -3,181969611930761 + 0,387281014208582i  
  256. -17,190983005625053 + 5,012552719206482i  
  257. -12,5 + 18,186533479473212i  
  258. -10,178425317543107 + 23,190667119105044i  
  259. -18,309016994374947 + 16,616988753597195i  
  260. -2,998370275568188 + 28,31592789979983i  
  261. 26,358765205042054 + 18,59438622703722i
  262. */


En la rutina ingresa un vector como dato y debería obtener la transformada en los puntos, en el caso que estoy planteando la transformada es la que esta al final del código para comprobar.
Les adjunto código, esquema y .cof.

Saludos!  :)
Título: Re: problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 16 de Julio de 2009, 00:52:19
Hola

No sabía que había forma de aproximar la FFT con operaciones más simples.

Intenta asignar los valores de data[] con números flotantes y no enteros.

Código: [Seleccionar]
data[2]=23.0;
Título: Re: problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: cerebro en 16 de Julio de 2009, 11:34:16
ya lo logre solucionar  :lol: me había olvidado de cambiar el clock a 48 Mhz en el proteus  :oops:, aunque ahora voy a tener que revisar la formula porque hay valores que ni se acercan a los que corresponde.
Gracias mig igual  :wink:
Título: Re: SOLUCIONADO- problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: cerebro en 16 de Julio de 2009, 13:12:24
 :-/ ya lo conseguí
estaba mal calculada la transformada!
estos son los verdaderos valores
 
Código: [Seleccionar]
91.0000
22.8459 -18.8713i
-2.9289 -34.7990i
-15.2006 -28.1561i
1.0000 -22.0000i
-6.3558 -12.9429i
-17.0711 - 4.7990i
-13.2895 + 8.3419i
-13.0000
-13.2895 - 8.3419i
-17.0711 + 4.7990i
-6.3558 +12.9429i
1.0000 +22.0000i
-15.2006 +28.1561i
-2.9289 +34.7990i
22.8459 +18.8713i
y esta es la salida del micro
(http://img190.imageshack.us/img190/4366/sinttulo1cto.jpg)

No sabía que había forma de aproximar la FFT con operaciones más simples.

el algoritmo implementado se llama Split-radix FFT.
 Ahora a jugar!  :D
Título: Re: problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 16 de Julio de 2009, 13:15:56
Perfecto Señor Cerebro. Un analizador de espectro de audio con 16 frecuencias ahora es posible y solo con un PIC.  8)
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 18 de Julio de 2009, 14:54:24
Una pregunta Cerebro, ¿de dónde tomaste el código fuente para la FFT Split radix? ¿O acaso tú lo escribiste?
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: cerebro en 18 de Julio de 2009, 15:21:30
 :(  yo no lo hice, mucho desgano y esas rutinas ya están hechas para que re-realizar algo. Lo más difícil es encontrar algo confiable  :mrgreen: por eso estuve comprobando el algoritmo.
Te dejo la pagina del autor   
FFT (http://www.mit.edu/~emin/source_code/fft/)

Saludos!

PD: será que estas por construir el analizador de espectros  :wink: ?
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 18 de Julio de 2009, 19:51:09
Gracias por el link.

Quiero construirlo y no es complicado una vez viendo que ya te funcionó. Solo hay que ajustar una frecuencia de muestreo, poner un filtro antialias, muestrear 16 puntos (que es lo que calcula la FFT que pones) y manos a la obra.

El problema es que no tengo generador de funciones, ni micrófono conmigo pero una vez regresando a clases... la split-radix fft será mi amiga  :D
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: cerebro en 18 de Julio de 2009, 21:52:33
 Si lo haces en una tarde  :), si querés ayuda con cualquier cosa avisame.
 Che se puede extender a más puntos (siempre y cuando sea multiplo de 4) pero no se como lo va a llevar el micro y una cosa más con proteus podes simular muchas partes (como para ir programando si querés) incluso mandarle al micro una señal wav.
  Saludos!!   

 
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 18 de Julio de 2009, 21:53:55
OK, voy a darle una revisada a esto porque la única FFT que he usado es la de Matlab.

Cualquier cosa ya te avisaré  :mrgreen:
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: cerebro en 23 de Julio de 2009, 01:03:26
bueno tampoco la vas a extrañar tanto porque la split es una variante del algoritmo Cooley-Tukey FFT  :) que es el que utiliza matlab para su calculo......
 
 hoy estaba pensando (raro raro...) en los viejos teléfonos, supuestamente transformaban la señal de señal de la voz y enviaban los coeficientes de la transformada de esta manera ahorraban en el envio de datos (según me comentaron...) capaz los que posean mas antigüedad conozcan del tema y nos comenten. Pero si es así, se podría armar un teléfono prehistórico con un pic  :shock: jajaj estaría buenísimo para investigar el teléfono TODOPIC  :D 
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 23 de Julio de 2009, 01:33:40
Pero no veo el ahorro en datos.

Si calculas la FFT de un arreglo de 16 muestras, obtendrás un arreglo de 16 muestras reales y 16 imaginarias, de las cuales se usan 8 y 8 ya que las demás son su espejo, siendo a final de cuentas 16 números... misma cantidad que la original.
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: cerebro en 23 de Julio de 2009, 15:47:38
parece que somos 2 los interesados en el tema  :D, de teléfonos se muy poco solo levanto el tubo y marco  :mrgreen:. Actualmente no tengo idea como harán la comunicación.  Pero supongamos que yo envio la señal acústica tal cual llega, el espectro del habla alcanza los 20 khz, de manera que tendría que estar mandando datos por lo menos a 40 kHz.
 A grandes rasgos, por la característica de resonancia de las vias superiores en el espetro del habla hay como montañas que se denominan formantes casi siempre son 3 (F0,F1,F2) presentes por ejemplo en la "a" "e" ....  y la "s" no presenta formantes, entonces los primeros implantes cocleares extraían estas 3 frecuencias y estimulaban en el lugar correspondiente a esa frecuencia en pacientes sordos. La persona escuchaba medio robotico pero escuchaba algo, actualmente se usan muchas estrategias y muchas bandas como 20 o más.   
 Si no mezcle mucho las cosas, la idea es extraer algunas bandas del espectro y enviar los coeficientes a una velocidad muy inferior por esta razón cae la cantidad de datos que tengo que enviar a costo de perder calidad en el sonido.........
 Tiene que funcionar  :lol:...................................bueno son cosas locas que se me ocurren de vez en cuando  :oops:
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 23 de Julio de 2009, 16:00:31
Un detalle... el espectro de frecuencias de la voz humana llega a los 4kHz. Cualquier otro ruido ya no es voz (un grito extremo o cualquier otra cosa). Por lo que hay que muestrear a 8kHz.

Para que un sordo escuche bien, sí hay que usar un espectro de 20Hz a 20kHz, pero si tu aplicación se orienta a transmitir voz entonces 8kHz es una buena velocidad de muestreo. De ahí que la codificación PCM @ 8 bits usa una velocidad de datos de 64kbps.

Aparte de PCM antes se usaban técnicas como la modulación delta.
http://en.wikipedia.org/wiki/Delta_modulation

Sobre lo que comentas de bajar la velocidad de transmisión lo entiendo así:

- Muestreas una señal, por ejemplo... 32 muestras (dominio del tiempo).
- Calculas la FFT de esas muestras obteniendo 32 muestras complejas (r + i)
- Usas solo las primeras 16 porque las siguientes son espejos
- Decimas esas 16 complejas a la mitad y obtienes 8 complejas
- Entonces ya habrás reducido de 32 muestras (dominio del tiempo) a 8 muestras complejas (16 números en total)

Pero creo que es más fácil muestrear 16 desde el principio sin decimarlas al final, ya después puedes interpolarlas para subirlas a 32.

Bueno, quién sabe... no sé si te entendí  :D
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: pablomanieri en 25 de Julio de 2009, 13:23:21
Me interesa mucho esto de calcular la fft con un pic. Lo voy a seguir de cerca
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: cerebro en 26 de Julio de 2009, 16:42:09
Un detalle... el espectro de frecuencias de la voz humana llega a los 4kHz. Cualquier otro ruido ya no es voz (un grito extremo o cualquier otra cosa). Por lo que hay que muestrear a 8kHz.

Para que un sordo escuche bien, sí hay que usar un espectro de 20Hz a 20kHz, pero si tu aplicación se orienta a transmitir voz entonces 8kHz es una buena velocidad de muestreo. De ahí que la codificación PCM @ 8 bits usa una velocidad de datos de 64kbps.


Je je 20 kHz como me afecta el alzeimer a los 25..... pero tampoco llega a los 4 khz te dejo una imagen de un espectrograma de la palabra "choice" que se  ve que va más alla de los 4 khz.

(http://img170.imageshack.us/img170/6033/sinttulo1p.jpg) 

algo así
(http://img195.imageshack.us/img195/2236/sinttulo12l.jpg)

Pd: continuará


Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 26 de Julio de 2009, 20:20:05
Touché.  :D

Por lo poco que he aprendido sobre transmisión de voz digital creo que es aceptable la anulación de las frecuencias mayores a 4kHz en una conversación. Definitivamente la voz humana va más allá de los 8kHz, pero para entender una conversación pienso que solo basta con señales de hasta 4kHz. El cerebro se encarga de llenar los vacíos de todas formas.

Entonces, ¿vas a hacer tu compresor de audio sin pérdida con un pic o solo estamos divagando al respecto?  :D

Ya nos dirás si 8kSps o más te harán falta.  :)

Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: cerebro en 27 de Julio de 2009, 20:54:12

Entonces, ¿vas a hacer tu compresor de audio sin pérdida con un pic o solo estamos divagando al respecto?  :D


 Tengo tantos proyectos inconclusos que si me pongo a tratar de hacer nuevos voy a dejar todo a medias, solo pensaba en voz alta al respecto mig. Seguro algo de esto le saco provecho para la parte de biomedica y algún día me falicita poder hacer algo con audio, además tengo que meterle a la facultad para terminar de una vez.....  :cry:  por el momento lo dejo en stand by.

Saludos!  :mrgreen:

pd:el duelo ese que ya sabes sigue en pie!  :D haber si le das a las teclitas  :D.....
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 28 de Julio de 2009, 00:06:45
Bueno pues cuando avances algo aquí seguirá el tema esperándote.

jajaja déjame practicar con el jamlegend que soy malísimo  :mrgreen:
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: micro_pepe en 11 de Octubre de 2009, 19:08:31
No entiendo muy bien el codigo, en ningun momento se usa el ADC, para muestrear la señal de audio se deberia usar no  :?

Un saludo.
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 11 de Octubre de 2009, 23:52:09
Hola, Cerebro usa el arreglo data[] como la señal a pasar a la FFT.

data[] serían las muestras tomadas de un ADC, pero aquí el ejemplo es para poner a prueba la función y no el ADC del pic.
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: micro_pepe en 13 de Octubre de 2009, 13:05:26
Hola, Cerebro usa el arreglo data[] como la señal a pasar a la FFT.

data[] serían las muestras tomadas de un ADC, pero aquí el ejemplo es para poner a prueba la función y no el ADC del pic.

OK, entendido.

Ahora si no recuerdo mal la teoria de señales, esa tabla que obtenemos de numeros complejos (la FFT) son componentes frecuenciales separadas 2*pi/N, donde N es el numero de muestras ?

Por otro lado esas componentes frecuenciales (las de la tabla) tendriamos que operarlas para encontrar su correspondiente frecuencia de la señal continua ?

Un saludo.
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 13 de Octubre de 2009, 20:21:07
No recuerdo cómo está el asunto de 2*pi/N, pero según entiendo el ejemplo de Cerebro, la delta F entre las componentes frecuenciales se calcula así:

Digamos que tenemos 8 muestras en el dominio del tiempo (N=8) y que la frecuencia de muestreo fue de 1kHz. Entonces la curva de respuesta de frecuencia tendrá las componentes en el eje X separadas por un delta F:

deltaF = 1000Hz / 8
deltaF = 125Hz

Entonces las 8 componentes en el eje X tendrían las siguientes frecuencias...

0Hz125Hz250Hz375Hz500Hz625Hz750Hz875Hz

Pero como sabemos las señales discretas tomadas a una frecuencia de muestreo n solo podrán mostrar señales útiles de n/2 Hz... es decir que solo serán utiles las señales en 0Hz, 125Hz, 250Hz y 375Hz... las demás solo serán un reflejo de las primeras cuatro.
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: micro_pepe en 14 de Octubre de 2009, 07:31:58
Entonces la magnitud de cada componente frecuencial ¿ es el modulo del numero complejo correspondiente resultado de la FFT ?

Un saludo.
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: cerebro en 14 de Octubre de 2009, 12:08:15
me había perdido  :), así es pepe calculando modulo de la FFT obtenes el espectro de magnitud de la repuesta en frecuencias. Espectro muy util para señales unidimensionales (sonido) pero no tanto para señales bidimensionales (ejem. una imagen) donde se privilegia el espectro de fase.

 Como explica santiago la resolución en frecuencias esta dada por Deltaf= fm/N y algo interesante es el principio de incertidumbre que establece
    Deltaf * Deltat = 1/N           // quiere decir que tanto la resolución en frecuencias como la resolución temporal y la cantidad de puntos están relacionadas no vamos a poder modificar ninguna sin afectar a las demás. 

Saludos

Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 14 de Octubre de 2009, 12:40:26
Para ver el contenido en amplitud de cada frecuencia debes seguir esta tablita que Cerebro incluyó...

Código: [Seleccionar]
#
/* Re{F[0]}= out0 */
#
/* Im{F[0]}= 0 */
#
/* Re{F[1]}= out8 */
#
/* Im{F[1]}= out12 */
#
/* Re{F[2]}= out4 */
#
/* Im{F[2]}= -out6 */
#
/* Re{F[3]}= out11 */
#
/* Im{F[3]}= -out15 */
#
/* Re{F[4]}= out2 */
#
/* Im{F[4]}= -out3 */
#
/* Re{F[5]}= out10 */
#
/* Im{F[5]}= out14 */
#
/* Re{F[6]}= out5 */
#
/* Im{F[6]}= -out7 */
#
/* Re{F[7]}= out9 */
#
/* Im{F[7]}= -out13 */
#
/* Re{F[8]}= out1 */
#
/* Im{F[8]}=0 */

Por ejemplo, el contenido de la componente de DC (0Hz) es el cuadrado de output[0] más el cuadrado de 0 y luego la raíz... es decir, el módulo.

El contenido de la componente a 125Hz sería...

sqrt(output[8]^2 + output[12]^2)
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: micro_pepe en 26 de Octubre de 2009, 13:38:07
Pongamos que entre otras componentes frecuenciales necesito conocer las de: 540Hz, 600Hz, 720Hz y 750Hz.

Como maximo puedo tener N=128. Entonces las de 540Hz y 600Hz las puedo conseguir con una fc=1280Hz:

1280/128=10Hz alcanzando como maximo 630Hz.

El problema esta en alcanzar las frecuencias de 720Hz y 750Hz. Pues una es multiplo de 60 y la otra de 50.

Se trata (quizas alguien intuya algo) de analizar señales de 50 y 60Hz, provenientes de convertidores de potencia (ac-dc, dc-ac, ac-ac) para hacer un voltimetro de verdadero valor eficaz. Por lo tanto existen unas frecuencias concretas multiplos de 50 y 60 que son necesarias de analizar.

¿Como puedo llegar a esas componentes frecuenciales?

Un saludo.
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 26 de Octubre de 2009, 14:20:48
Hola Pepe

Una frecuencia de muestreo múltiplo de 30Hz es común a todas las frecuencias que necesitas...

540Hz/30Hz = 18
600Hz/30Hz = 20
720Hz/30Hz = 24
750Hz/30Hz = 25

Por lo que si muestreas a 1500Hz conocerías las tres primeras frecuencias de tu lista, pero la de 750Hz no la podrías ver, verías la de 720Hz (por el asunto del espejo).

Muestrea 30Hz más rápido... 780Hz * 2 = 1560Hz para que puedas ver sin problemas la de 750Hz.

Si puedes tener solo 128 muestras solo obtendrás 64 componentes frecuenciales con una deltaf de...

1560Hz / 128 = 12.1875Hz

Esto implica que usando la Fast Fourier Transform nunca verás exactamente los valores en Hz que buscas mientras muestrees lentamente... calculemos la componente que más se acercaría a 540Hz por ejemplo...

540Hz / 12.1875Hz = 44.3

La componente 44 sería la más cercana a 540Hz, valiendo exactamente...

44 * 12.1875Hz = 536.25Hz

Así que el error sería de -3.75Hz... cosa que deberás evaluar en tu aplicación.

Veamos cuánta diferencia hay con la componente de 750Hz...

750Hz / 12.1875Hz = 61.53
62 * 12.1875Hz = 755.625Hz
Error = 5.625Hz

Yo la usaría sin tanta preocupación...  :mrgreen:

Por lo que un muestreo a 1560Hz con 128 muestras es suficiente para ver las componentes frecuenciales que buscas.
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 26 de Octubre de 2009, 20:20:37
Pepe, acabo de modificar una función FFT para C# y me di cuenta de que te di mal la explicación  :oops:

Para poder ver una frecuencia de hasta 750Hz solo es necesario muestrear al doble... a 1500Hz.

Por ejemplo, si tomamos 16 muestras, entonces obtendremos 9 componentes de frecuencia útiles... la frecuencia de DC, 7 frecuencias y la frecuencia Nyquist, sumando en total 9.

Aquí un documento de Matlab que lo explica correctamente.
http://www.mathworks.com/support/tech-notes/1700/1702.html

Así que corrigiendo... un muestreo a 1500Hz con 128 muestras es suficiente para ver las componentes frecuenciales que buscas.
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 30 de Enero de 2010, 00:03:12
Como extra a los resultados de Cerebro puedo confirmar que esta split radix se ejecuta correctamente en un PIC24 en CCS. Tarda 674us en entregar resultados corriendo el pic a 16MIPS.  :mrgreen:
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: Suky en 30 de Enero de 2010, 08:52:23
Como extra a los resultados de Cerebro puedo confirmar que esta split radix se ejecuta correctamente en un PIC24 en CCS. Tarda 674us en entregar resultados corriendo el pic a 16MIPS.  :mrgreen:

Excelente! Yo estaba por probarlo en un PIC24H en C30, si nadie se me adelanta les comento los resultados  ;-)


Saludos!
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 30 de Enero de 2010, 11:19:14
Podría augurar que se ejecutará en 360us aproximadamente  :mrgreen:
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: Suky en 30 de Enero de 2010, 16:04:20
Podría augurar que se ejecutará en 360us aproximadamente  :mrgreen:

 :? me parece que tendría que ser 270 us  :mrgreen:
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: Nocturno en 30 de Enero de 2010, 16:44:55
No creo que podáis hacer una extrapolación de 16MIPS a 40MIPS directamente porque los PIC24F y los PIC24H no son idénticos en cuanto a prestaciones, ¿no?.
No me toméis muy en serio pero creo recordar que los 24H tienen operaciones de multiplicación y división complejas que los acercan a los dsPIC.
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 30 de Enero de 2010, 16:48:55
Ahhhh 40MIPS... yo usé 30MIPS  :P

Quiero un PIC24H  :mrgreen:
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: Suky en 30 de Enero de 2010, 17:00:34
No creo que podáis hacer una extrapolación de 16MIPS a 40MIPS directamente porque los PIC24F y los PIC24H no son idénticos en cuanto a prestaciones, ¿no?.
No me toméis muy en serio pero creo recordar que los 24H tienen operaciones de multiplicación y división complejas que los acercan a los dsPIC.

Nop, no tienen operaciones con complejos. Algunas diferencias son, los PIC24 tienen USB y los PIC24H no, pero estos últimos tienen DMA y trabajan a 40 MIPS, entre otras cosas.

Ahhhh 40MIPS... yo usé 30MIPS  :P

Quiero un PIC24H  :mrgreen:

 :D :D Pero fallaste!!! Ahora hay que ver en realidad que sucede  :?

Saludos!
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: Suky en 30 de Enero de 2010, 17:36:43
Bueno, el simulador dice que necesita 11266 ciclos de reloj y a 40 MIPS en un PIC24HJ serían ~282us, compilado en C30.


Saludos!
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 28 de Marzo de 2010, 14:26:25
Hola

Estoy haciendo pruebas con el algortimo de la FFT split radix y un PIC32 corriendo a 80MIPS. La velocidad de cálculo en MPLAB SIM es de 76us aproximadamente, superando por mucho a la del PIC24 (casi 9 veces más rápido).

http://img138.imageshack.us/img138/3999/pic32fft.png
(http://img138.imageshack.us/img138/3999/pic32fft.th.png) (http://img138.imageshack.us/img138/3999/pic32fft.png)

Pero tengo un problema, coloqué el siguiente código...

Código: [Seleccionar]
while(1)
   {
   R16SRFFT(data, out);
   PORTWrite(IOPORT_B, i++);
   }

... el cual hace un toggle a un led conectado a B0. La frecuencia que debería medir en tal pin es de 6.5kHz (2 veces 74us), pero haciendo la medición con el pickit observo que la señal es mucho más lenta...

http://img696.imageshack.us/img696/3931/pickit.png
(http://img696.imageshack.us/img696/3931/pickit.th.png) (http://img696.imageshack.us/img696/3931/pickit.png)

No sé qué esté pasando. Al menos la velocidad de la FFT parece ser buena en simulación.
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: cerebro en 28 de Marzo de 2010, 15:16:56
 :? porque tan lento el calculo... será que esta corriendo a 80 MIPS el micro? como se puede chequear eso?
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 28 de Marzo de 2010, 15:21:09
En MPLAB SIM el cálculo toma 76us. El problema que tengo está en la salida de B0, que es más lenta que el cálculo (600us aprox.).  :(
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: BrunoF en 28 de Marzo de 2010, 15:38:40
Podes poner el desassembling list? para poder ver que codigo ASM genera cada linea?
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 28 de Marzo de 2010, 15:54:14
Podes poner el desassembling list? para poder ver que codigo ASM genera cada linea?

Aquí lo tienes Bruno.

Código: [Seleccionar]
69:                  while(1)
70:                     {
71:                     //PORTToggleBits(IOPORT_B, BIT_0);
72:                     R16SRFFT(data, out);
9D000864  27A40010   addiu       a0,sp,16
9D000868  0F400006   jal         0x9d000018
9D00086C  27A50050   addiu       a1,sp,80
73:                     PORTWrite(IOPORT_B, i++);
9D000870  02002821   addu        a1,s0,zero
9D000874  00002021   addu        a0,zero,zero
9D000878  0F4009F4   jal         0x9d0027d0
9D00087C  26100001   addiu       s0,s0,1
9D000880  1000FFF9   beq         zero,zero,0x9d000868
9D000884  27A40010   addiu       a0,sp,16
74:                     }
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 28 de Marzo de 2010, 23:22:33
Bueno, ya quedó solucionado el asunto del puerto B.

El problema estaba en que la memoria de programa de los PIC32 es lenta y para solucionarlo se debe usar la Prefetch Caché. El cálculo de la FFT tardaba mucho más tiempo en ejecutarse porque se cargaba directamente de la rom. Al escribir la siguiente línea:

Código: [Seleccionar]
int main()
{
    //STEP 1. Configure cache, wait states and peripheral bus clock
    // Configure the device for maximum performance but do not change the PBDIV
    // Given the options, this function will change the flash wait states, RAM
    // wait state and enable prefetch cache but will not change the PBDIV.
    // The PBDIV value is already set via the pragma FPBDIV option above..
    SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);

se carga el contenido de la rom en la caché antes de ejecutarse y posteriormente se ejecuta desde ella... habilitando así una más rápida ejecución.

Usando la caché la FFT toma 98u y sin caché 604us.

http://img31.imageshack.us/img31/6021/cachey.png
(http://img31.imageshack.us/img31/6021/cachey.th.png) (http://img31.imageshack.us/img31/6021/cachey.png)
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: AKENAFAB en 29 de Marzo de 2010, 00:22:06
Por la syntaxis noto que son bits de configuracion , eso es cierto???
O estoy confundiendo eso con el pragma del PPBDIV?

Le estas sacando jugo al pickit2 n_n
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: Suky en 29 de Marzo de 2010, 00:26:00
Bueno, ya quedó solucionado el asunto del puerto B.

El problema estaba en que la memoria de programa de los PIC32 es lenta y para solucionarlo se debe usar la Prefetch Caché. El cálculo de la FFT tardaba mucho más tiempo en ejecutarse porque se cargaba directamente de la rom. Al escribir la siguiente línea:

 :shock: Todos los días se aprende algo nuevo!  :lol: De cuanto es la cache del micro?
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 29 de Marzo de 2010, 00:31:55
Por la syntaxis noto que son bits de configuracion , eso es cierto???
O estoy confundiendo eso con el pragma del PPBDIV?

Le estas sacando jugo al pickit2 n_n

jeje

Es una función dentro de la función main(). Lo de la caché se configura cuando el pic32 ya está corriendo. La ayuda de C32 dice:

Citar
Remarks
The function sets the PB divider, the Flash Wait states and the DRM wait states to the optimum value. It also enables the cacheability for the K0 segment.

Se supone que cambia la velocidad del reloj de los periféricos, habilita la caché para agilizar la rom y la ram.

:shock: Todos los días se aprende algo nuevo!  :lol: De cuanto es la cache del micro?

Puff quién sabe... está medio en chino... esto es lo que dice la datasheet:

Código: [Seleccionar]
9.1Features
•16 Fully Associative Lockable Cache Lines
•16-byte Cache Lines
•Up to 4 Cache Lines Allocated to Data
•2 Cache Lines with Address Mask to hold
repeated instructions
•Pseudo LRU replacement policy
•All Cache Lines are software writable
•16-byte parallel memory fetch
•Predictive Instruction Prefetch
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: Suky en 29 de Marzo de 2010, 00:45:05
:shock: Todos los días se aprende algo nuevo!  :lol: De cuanto es la cache del micro?

Puff quién sabe... está medio en chino... esto es lo que dice la datasheet:

Código: [Seleccionar]
9.1Features
•16 Fully Associative Lockable Cache Lines
•16-byte Cache Lines
•Up to 4 Cache Lines Allocated to Data
•2 Cache Lines with Address Mask to hold
repeated instructions
•Pseudo LRU replacement policy
•All Cache Lines are software writable
•16-byte parallel memory fetch
•Predictive Instruction Prefetch

  :rayito: :z)

 :D
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 29 de Marzo de 2010, 00:52:51
Esta función es la más interesante... Predictive Instruction Prefetch. El PIC predice por dónde va a pasar el programa y qué bloques de código van a ejecutarse y los vuelca a la caché antes de que suceda. :rayito:  :mrgreen:
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: cerebro en 29 de Marzo de 2010, 08:55:27
 :shock: que interesantes datos nos pasas mig, che es muy grande el salto de un 18F a un PIC32? puedo llegar a morir en el intento?
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: BrunoF en 29 de Marzo de 2010, 13:39:30
Perdona santiago, pero olvidaba que eran PIC32, por lo que tuve que familizarizarme con su instruction set, cosa que llevo mas tiempo que tu solucion...
Título: Re: SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: migsantiago en 29 de Marzo de 2010, 18:30:38
:shock: que interesantes datos nos pasas mig, che es muy grande el salto de un 18F a un PIC32? puedo llegar a morir en el intento?

Si sabes lenguaje C... te has salvado.  ;-) Es fácil, sólo que hay que leer mucho.

Perdona santiago, pero olvidaba que eran PIC32, por lo que tuve que familizarizarme con su instruction set, cosa que llevo mas tiempo que tu solucion...

No te preocupes Bruno.   :mrgreen:

No sé si realmente alguien domine el ASM de los PIC32... su ASM es diferente al de los PIC16 y 18. Según leo es un estándar MIPS32, y es de pocas instrucciones (RISC).

http://www.mips.com/media/files/MD00565-2B-MIPS32-QRC-01.01.pdf
Título: Re:SOLUCIONADO-problemas con FFT con 18f4550, queriendo inventar la rueda.
Publicado por: fer650 en 13 de Septiembre de 2017, 23:11:56
Hola, se que este tema tiene varios años pero recién ahora lo encuentro.
Estoy tratando de ingresar al mundo del FFT y me pareció buena la idea de empezar con un PIC18 que son los que más uso.
Hice algunas pruebas con el código que subió Cerebro y como los resultados me parecían ilógicos revisé el artículo original pero tampoco logré mejoras.
Estoy utilizando la entrada del ADC del micro y la leo cada 100uSeg (10.000 veces por segundo)
Para ver si la lectura está bien la envío a la salida PWM y con un filtro pasa bajo tengo de nuevo una senoidal.
Después muestro en un display las output[0], output[1], etc pero los valores son muy cambiantes aunque la frecuencia de entrada sea fija.
Preguntas:
- Funciona ese código?
- El valor de output
Perdonen mi ignorancia en matemáticas y afines.
Desde ya muchas gracias.