Autor Tema: [Proyecto] Vúmetro con pantalla LED  (Leído 463 veces)

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

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2141
Re:[Proyecto] Vúmetro con pantalla LED
« Respuesta #15 en: 12 de Mayo de 2017, 23:28:58 »
Código: C
  1.        
  2. for(i=0;i<128;i+=2)
  3.         {
  4.                 FFT_ADCvalues[i]=(q15_t)((int16_t)(DMA_ADCvalues[i/2]-2048)<<4);
  5.                 FFT_ADCvalues[i+1]=(q15_t)0;
  6.         }
  7.         arm_cfft_q15(&arm_cfft_sR_q15_len64, FFT_ADCvalues, 0, 1);
  8.         arm_cmplx_mag_q15(FFT_ADCvalues, MAG_of_fft, 64);
  9.  

La funcion arm_cfft_q15 necesita como entrada las muestras del ADC en formato Q15. Por otra parte el vector de entrada de la FFT es para cada punto un (real, imaginario). La entrada es todo real, por eso el lazo for primero.
Luego se hace la FFT, la cual devuelve 64 puntos (real, imaginario).
Finalmente la ultima funcion calcula la magnitud (sqrt(real*real+imaginario*imaginario)) y esos son los valores a usar (creo que hay que dividir por 64 tambien).

El tema es que no me funciona, la salida MAG_of_fft termina siendo el primer valor 511 y el resto todos ceros... estoy buscando informacion por todos lados, pero no lo tengo muy claro aun...

Saludos!
-
Leonardo Garberoglio

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2141
Re:[Proyecto] Vúmetro con pantalla LED
« Respuesta #16 en: 13 de Mayo de 2017, 17:46:44 »
Bueno, estoy aprendiendo algo nuevo... Punto Fijo!

Como esto no me está funcionando como es eperado no me queda otra que estudiar bien como funciona!
Las librerías de DSP de las CMSIS estan programadas en punto flotante, para ser usada preferentemente con FPU por hardware, luego hay versiones para punto fijo Q1.31 y Q1.15. El tema es que no tenía idea como funcionaban esos formatos de punto fijo.
La primer referencia, wikipedia:
https://en.wikipedia.org/wiki/Q_(number_format)

Nuestro Q15 no es otra cosa que un typedef a un int16_t, por lo que el contenedor de nuestro Q15 es un número de 16 bits CON signo.
Entonces los que vale es:
Rango: [ -20 , 20-2-15 ] = [ -1 , 0,999969482421875 ]
Pero com ose representan los números?
Bien, el primer bit es de signo. 1 -> números negativos. 0-> números positivos.
Luego los numeros positivos cada bit arrancando del 15 hacia el bit 0 valen 2-n en este caso b15->n=1, b14-> n=2.
O sea:
0.99 = 0111 1111 1111 1111
0.75 = 0110 0000 0000 0000b
0.5 = 0100 0000 0000 0000b
0.25 = 0010 0000 0000 0000b
0    = 0b

Entonces lo que en número binarios comunes van del 0 al 0111 1111  1111 1111(32767o 0x7FFF) es el recorrido de 0 a 0.99999

Con los negativos es un poco menos intuitivo. Pero sería así
-1      = 1000 0000 0000 0000b
-0.75 = 1010 0000 0000 0000b
-0.5   = 1100 0000 0000 0000b
-0.25 = 1110 0000 0000 0000b

O sea que cuántos más 1 hay, mas chico es el número entonces vamos desde  1111 1111 1111 1111  (-0.0 o 0xFFFF) hasta 1000 0000  0000 0000(-1 ó 0x8000)

Luego para pasar de un número flotante a q15 hay que multiplicar por 215 y redondear al entero más cercano.

Sabido esto podemos hacer un programita de testeo de todo esto más la FFT.

La idea es crear un seno de 1.5Khz (1562Hz en realidad), muestreado a 10KHz en formato flotante (funcion sin de math.h) Luego pasarla a q15, hacer la FFT y calcular la magnitud de los resultados. Recordar que la salida de la FFT es en formato complejo (real, imaginario) y para obtener un valor "usable" hay que calcular la magnitud (y la fase si se quiere):

Código: C
  1.         float fltSinWave[64];
  2.         q15_t q15SinWave[64];
  3.         q15_t q15FFT[128];
  4.         q15_t MAG_of_fft[64];
  5.         uint32_t F=1562;
  6.         uint32_t Fs = 10000;
  7.         uint8_t i;
  8.         for(i=0;i<64;i++)
  9.         {
  10.                 // Seno discreto FLOTANTE
  11.                 fltSinWave[i] = (sin(2*M_PI*i*F/Fs));
  12.                 // Seno discreto en Q15
  13.                 q15SinWave[i] = (q15_t)(fltSinWave[i] * (1<<15));
  14.         }
  15.         // Preparo el array de la FFT
  16.         for(i=0;i<128;i+=2)
  17.         {
  18.                 q15FFT[i] = q15SinWave[i/2];
  19.                 q15FFT[i+1] = 0;
  20.         }
  21.         // Calculo la FFT
  22.         arm_cfft_q15(&arm_cfft_sR_q15_len64, q15FFT, 0, 1);
  23.         // Calculo la magnitud de cada punto
  24.         arm_cmplx_mag_q15(q15FFT, MAG_of_fft, 64);
  25.  

Corriendo esta parte en el uC obtengo:
fltSinWave
0, 0.831295013, 0.924119771, 0.196014598, -0.706217647, -0.981090546, -0.38442421, 0.553740382, 0.999996841, 0.557918906, -0.3797791, -0.980105221

q15SinWave
0, 27239, 30281, 6423, -23141, -32148, -12596, 18144, 32767, 18281, -12444, -32116

Aquí podemos verificar que 0.83129 en float es 27239 en q15. 27239 en binario es 0110 1010 0110 0111. Componiendo en q15 tenemos: 0.5 + 0.25 + 0.0625 + 0.015625 +.... sumando solo esos bits tenemos 0,828125 por lo que podemos verificar que el formato es el correcto.

El siguiente paso es armar un array con el doble de puntos necesario para la FFT.
Finalmente calculamos la FFT y la magnitud de cada bin.

La señal que creamos tiene 1562Hz por una razon. Si calculamos la resolucion de la FFT: Fs/Nfft = 10.000/64 = 156.25 Hz. Por lo que el centro de cada bin estará en un múltiplo de 156.25. En este caso 1562 (.5). En que bin deberíamos encontrar el pico de la FFT? 1562 / 156 = 10.
Cuando voy al visor de expresiones en el IDE obtengo esto para MAG_of_fft:
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8191, 0 <repeats 43 times>

Como ven tengo toda la potencia de la señal en el bin 10  :-/

Entonces ahora ya tengo funcionando la FFT y el cálculo de magnitud. Solo resta acomodar los datos del ADC en un q15. Eso queda para dentro de un rato.

Saludos

-
Leonardo Garberoglio

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2141
Re:[Proyecto] Vúmetro con pantalla LED
« Respuesta #17 en: 13 de Mayo de 2017, 18:02:11 »
Un punto que falta resolver es que el resultado de la FFT dió 8191. En binario es 0001 1111 1111 1111 si tomo ese número como q15 y lo paso a decimal el número que obtengo es 0.249969482.
La FFT aplicada a un seno nos debe devolver la Vp. En este caso el seno va de 1 a -1 por lo que la Vp = 1 y yo debería obtener como espectro de potencia 1 y no 0.25

Mirando la funcion arm_cmplx_mag_q15 encuentro esta nota:

"The function implements 1.15 by 1.15 multiplications and finally output is converted into 2.14 format."

Entonces la salida esta en otro formato, siendo los primeros 2 bits parte entera + signo y los 14 restantes decimales. Una forma de pasar de q2.14 a q1.15 simplemente hacemos un shift a la izquierda. Entonces el número en q1.15 es 0011 1111 1111 1110 que es aproximadamente 0.5... Hay algún factor más que me está faltando para llegar a 1. Voy a investigar la FFT para ver si cambia de formato.

Saludos!
-
Leonardo Garberoglio

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2141
Re:[Proyecto] Vúmetro con pantalla LED
« Respuesta #18 en: 13 de Mayo de 2017, 18:59:06 »
Finalmente puedo probar simulando en el uC los datos como entrarían por el ADC, es decir, con un offset de 2048 cuentas. Con esto puedo probar la forma de pasar esos datos a q15.
Para ello hago este código de testeo:

Código: C
  1.         float fltSinWave[64];
  2.         q15_t q15SinWave[64];
  3.         uint16_t uintSinWave[64];
  4.         q15_t q15FFT[128];
  5.         q15_t q15MAG[64];
  6.         uint32_t F=1562;
  7.         uint32_t Fs = 10000;
  8.         uint8_t i;
  9.         for(i=0;i<64;i++)
  10.         {
  11.                 // Seno discreto FLOTANTE
  12.                 fltSinWave[i] = (sin(2*M_PI*i*F/Fs));
  13.                 // Seno discreto en uint16_t Así es como lo leería el ADC si le metiera un senos de +- 1.65V
  14.                 uintSinWave[i] = (uint16_t)((fltSinWave[i] * 2048) + 2048);
  15.                 // Esta es la propuesta para obtener el Q15
  16.                 q15SinWave[i] = (q15_t)((uintSinWave[i] - 2048) << 4);
  17.         }
  18.  
  19.         // Preparo el array de la FFT
  20.         for(i=0;i<128;i+=2)
  21.         {
  22.                 q15FFT[i] = q15SinWave[i/2];
  23.                 q15FFT[i+1] = 0;
  24.         }
  25.         // Calculo la FFT
  26.         arm_cfft_q15(&arm_cfft_sR_q15_len64, q15FFT, 0, 1);
  27.         // Calculo la magnitud de cada punto
  28.         arm_cmplx_mag_q15(q15FFT, q15MAG, 64);
  29.  

Entonces, primero creo un seno en flotante, de -1 a 1. Luego lo paso a un array de uint16, primero multiplicando por 2048 y luego sumando el offset. Ese es el seno más grande que puede entrar.
El resultado de ese array es: 2048, 3750, 3940, 2449, 601, 38, 1260, 3182, 4095, 3190, 1270, 40.... Como vemos arranca en 2048.
Luego hago una transformacion sugerida, la cual es restar los 2048 de offset para que quede un número int16 y luego subir los 4 bits que faltan a la izquierda.
Los siguientes puntos son iguales al anterior, prepar el array de la FFT y luego hago FFT y saco magnitud.

Probando esto, obtengo el mismo resultado que trabajando todo con q15, entonces ya tengo la forma de pasar de valores del ADC a formato q15, hacer la FFT y calcular la magnitud de forma correcta (excepto por un "x2" que me falta encontrar).

Saludos
-
Leonardo Garberoglio

Desconectado vixctor

  • PIC12
  • **
  • Mensajes: 98
Re:[Proyecto] Vúmetro con pantalla LED
« Respuesta #19 en: 13 de Mayo de 2017, 19:52:14 »
Excelente, ya casi tienes esa parte, ahora si podrás notar los resultados...

Fijate que me recordaste algo: Cuando desarrolle lo de la FFT, pase por muchas cosas parecidas, como era frustrante ver que no salian los resultados o los signos de las operaciones...
 
Precisamente termine creando tablas de frecuencias como la que hiciste, para corroborar que salieran bien los bines de la FFT.

Luego, cuando la senoidal jalaba perfectamente, probaba con una tabla de onda cuadrada y otra triangular y pfff, de nuevo, datos falsos, componentes erroneas y regresar de nuevo a corregir el código, etapa por etapa de la FFT...

Quizas el proceso fue mucho más frustrante para mi de que lo que ha sido para ti, debido a que no use una libreria como tal para la FFT. En aquel entonces, la única librería que tenía microchip estaba plagada de errores, así que ni para jugar con ella.

Lo que termine haciendo fue leer muchísimo e implementarla en ensamblador, y eso de los números y los signos, que  si había que escalarlos al final... y luego hacer un algoritmo super eficiente y rápido para obtener la raíz cuadrada y sacar la magnitud etc... fue mucho dolor de cabeza pero el conocimiento queda y al final vale la pena...

Saludos.

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2141
Re:[Proyecto] Vúmetro con pantalla LED
« Respuesta #20 en: 14 de Mayo de 2017, 09:58:27 »
Este es un test interesante, es largo el video pero explica mucho:



Como realizas el cómputo de lo que muestras?
Porque hay 2 efectos que son vistosos, pero ireales.
El primero es que hay una "latido" en los bines, es como si fuesen "bailando" con una frecuencia de 0.5Hz o algo así
El segundo es que nunca tienes bines puros, siempre tienes perdida (frequency leckage) alrededor del bin y simpre es la misma cantidad, en ves de tener un bin tiene una "campana". Eso no parece real. A medida que la frecuencia va subiendo, llega un punto que pasa por la frecuencia central de un bin de la FFT, en ese momento deberías tener un baston perfecto. Luego entre 2 frecuenicas centrales hay un efecto que creo es frequency leackage que hace que el espectro valla pasando de un bin al siguiente "desparramando" un poco el espectro...

No digo que el resultado que muestras no sea lindo, todo lo contrario, es muy vistos. Pero debe tener algo de procesamiento adicional porque no me parece real y no me permite comparar con lo que yo obtengo.

Saludos!
-
Leonardo Garberoglio

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4255
    • Picuino
Re:[Proyecto] Vúmetro con pantalla LED
« Respuesta #21 en: 14 de Mayo de 2017, 13:33:18 »
Me suscribo.

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2141
Re:[Proyecto] Vúmetro con pantalla LED
« Respuesta #22 en: 14 de Mayo de 2017, 15:15:01 »
Este proyecto terminó siendo una gran fuente de aprendizaje. Entre post y post y decenas de cosas que aparecen y enzeñan algo.

Voy a tratar de ordenar los pensamientos y escrivir lo más claro posible.

El primer punto que nunca estudié es que iba a pasar cuando el refresco de la pantalla (SPI + DMA1) compita por el bus con el muestreo de mediana velocidad (ADC + DMA1). En mi caso el micro (STM32F103RB) posee un solo módulo DMA y 7 canales. Cada canal puede manejar un periferico distinto. Pero la RAM es una sola y puede ser un problema si el SPI quiere LEER la RAM para escrivir en el SPI y a la vez el ADC quiere ESCRIVIR la RAM con los datos del ADC.

En los micros ARM hay muchas fuentes de interrupcion y a veces un mismo módulo funcional puede utilizar mas de 1 interrupcion. Por ejemplo, el módulo de muestreo y almacenaje tiene un TIMER (el nro 3) que cada 1/40.000 = 2.5uSeg interrumpe (en mi caso solo para hacer un toggle en un led y verlo en el analizador lógico) y a la vez dispara al ADC para su conversion. A la vez el DMA está configurado para mover datos del ADC a la RAM. Se configura un buffer de 256 puntos y el DMA se encarga de moverlos, cuando llega a la muestra 256 vuelve a empezar de 0 pisando los datos previos. Para usar los datos el DMA tiene una interrupcion por "buffer mitad lleno" (en este caso se dará cada 3.2mseg). En esa interrupcion debemos poner el código que procese las primeras 128 muestras. Tambien posee una IRQ por transferencia completa, en la que deberemos poner el codigo que procesa las segundas 128 muestras. Pero que pasa si el tiempo que tardamos en procesar es mayor a 2.5useg? Puede pasar que, como estamos dentro de una interrupcion, la del DMA, no se pueda ejecutar la del TIMER 3. En este caso, el problema es menor, ya que como el disparo del timer3 hacia el ADC no es por software, aunque la IRQ no se dé, el disparo se hará igual por hardware, pero no tendría el toggle del LED que sí está por software.

Todo esto se resuelve con las PRIORIDADES de las interrupciones. Generalmete en los PIC solo hay 1 o 2 prioridades, en los cortex M hay un sistema de prioridades mucho más avanzado. Pudiendo hacer grupos con subprioridaes entre otras cosas.

Fijar las prioridades en los ARM es algo que siempre me pega en la cabeza y cuando algo complejo no funciona, muchas veces viene por aquí el tema.

Quiero mostrar entonces un poquito este tema.

Primero condiguro el TIM3 para que dispare cada 2.5useg. Con un reloj de 64MHz obtengo eso con un prescaler de 0 y un counter de 1600. Lo configuro como disparo del ADC y para que interrumpa. En la ISR pongo el toggle de un LED para medirlo con el analizador.
Configuro tambien el ADC, para que convierta con el disparo de TIM3, sin interrupcion por conversion finalizada, pero con DMA. En el DMA configuro la interrupcion con prioridad mayor que el TIM3 (mayot priotidad se consigue con un número menor en el registro).
Luego pongo el código de la FFT dentro de la interrupcion por medio buffer lleno.

Corro el programa y veo el analizador:

VU-10.png
*VU-10.png
(102.17 kB . 1323x715 - visto 44 veces)


Luego paso la interrucion del timer a mayor prioridad que la del DMA y veo esto:

VU11.png
*VU11.png
(81.44 kB . 1679x520 - visto 44 veces)


Bien, teniendo en cuanta esto, en la proxima veremo como definir las prioridades para que todo funcione de la mejor forma posible.

Saludos
« Última modificación: 14 de Mayo de 2017, 15:32:36 por elgarbe »
-
Leonardo Garberoglio

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2141
Re:[Proyecto] Vúmetro con pantalla LED
« Respuesta #23 en: 14 de Mayo de 2017, 15:59:29 »
Configurando el refresco de la pantalla LED

Ahora veamos que pasa con la pantalla LED.
Lo primero que quiero es un refresco de 60 cuadros por segundo. Esto es, barrer la pantalla completa cada 16.666mSeg. Esta pantalla tiene 16 filas por lo que cada fila requiere 1.041mSeg
Para el barrido vertical uso el TIM1, configurado para que interrumpa cada 1.041 mseg. A 64MHz lo consigo con un prescaler de 64 y un counter de 1041. En cada pedido de interrupcion se actualiza se pone en blanco la pantalla, se actualiza la fila actual, se prepara el DMA para que transmita todos los datos y se sale de la interrupcion. Cuando el DMA transmite todo los datos interrumpe y en dicha interrupcion hacemos el pulso de LAT y quitamos la señal de blank. En este caso no hay problemas con la prioridad de la interrupcion, ya que cuando la del DMA quiere interrumpir, el TIMer ya termino su ISR. Por lo tanto pueden tener la misma prioridad.

Veamos los tiempos que conseguimos con ese refresco:

VU12.png
*VU12.png
(73.11 kB . 1305x532 - visto 43 veces)


Si hago un zoom en una sola transmision vemos:

VU13.png
*VU13.png
(86.28 kB . 1448x536 - visto 44 veces)


Con 60 Hz tengo una imagen bien estable. Con 30Hz se ven un pequeño flikering...

Saludos
-
Leonardo Garberoglio

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2141
Re:[Proyecto] Vúmetro con pantalla LED
« Respuesta #24 en: 14 de Mayo de 2017, 16:29:10 »
Todo Junto

Ahora veamos como juntar el muestreo + el procesamiento + el refresco del cartel.

El primer punto son la prioridades.
El evento de mayor prioridad es el muestreo del ADC. Ese evento está garantizado por hardware, nada que haga en software me va a afectar el muestreo. Pero si yo quiero ver cuando el timer me dispara al ADC, debo ponerlo que interrumpa y dicha interrupcion debe ser la mas alta. Le pondré prioridad 1 al TIM3.
El procesamiento se da en la interrupcion por DMA del ADC y debo darle prioridad porque es un evento rápido y el tiempo de procesamiento es lento. a 40KHz tengo una interrupcion cada 128 muestras -> cada 3.2mseg. Como vimos en la imagen anterior el procesamiento parece durar 170 useg (ya veremos como verificar esto a la perfeccion). Le daremos al DMA1 canal 1 la prioridad 2. Luego tengo el refresco de pantalla, el cual parece ser el más sobrado de tiempo, por lo que le dare la prioridad 3, tanto al timer1 como al DMA1 canal 5:

VU14.png
*VU14.png
(31.86 kB . 651x662 - visto 43 veces)


Bien, si probamos ahora el sistema completo obtengo:

VU15.png
*VU15.png
(81.05 kB . 1665x557 - visto 43 veces)


Como vemos todo parace funcionar de maravillas.

Finalmente, este es el resultado en la pantalla, de un barrido en frecuncia con el Vumetro recientemente configurado y optimizado para Fs=40KHz


Ahora creo que estamos mucho mejor y ya con los tiempos de procesamiento medidos podemos ver que cosas se pueden mejorar.

Saludos!
-
Leonardo Garberoglio

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2141
Re:[Proyecto] Vúmetro con pantalla LED
« Respuesta #25 en: 19 de Mayo de 2017, 21:14:20 »
Estoy analizando circuitos para amplificar un poco la señal de audio de entrada.

Que les parece esta opción?

VU16.png
*VU16.png
(47.41 kB . 954x510 - visto 34 veces)


No estoy seguro la amplitud de la señal de un reproductor de mp3 o la salida de audio de un celular... Tendría que hacer una medicion para ajustar la ganancia y quizá poner un preset para ajustar diferentes tipos de señal...

Saludos
-
Leonardo Garberoglio

Desconectado vixctor

  • PIC12
  • **
  • Mensajes: 98
Re:[Proyecto] Vúmetro con pantalla LED
« Respuesta #26 en: 19 de Mayo de 2017, 21:48:25 »
Citar
Como realizas el cómputo de lo que muestras?
Porque hay 2 efectos que son vistosos, pero ireales.
El primero es que hay una "latido" en los bines, es como si fuesen "bailando" con una frecuencia de 0.5Hz o algo así
El segundo es que nunca tienes bines puros, siempre tienes perdida (frequency leckage) alrededor del bin y simpre es la misma cantidad, en ves de tener un bin tiene una "campana". Eso no parece real. A medida que la frecuencia va subiendo, llega un punto que pasa por la frecuencia central de un bin de la FFT, en ese momento deberías tener un baston perfecto. Luego entre 2 frecuenicas centrales hay un efecto que creo es frequency leackage que hace que el espectro valla pasando de un bin al siguiente "desparramando" un poco el espectro...

No digo que el resultado que muestras no sea lindo, todo lo contrario, es muy vistos. Pero debe tener algo de procesamiento adicional porque no me parece real y no me permite comparar con lo que yo obtengo.

Saludos!

Efectivamente has notado ese efecto, lo cual solo es notorio ante a aquellos que dominan el tema de FFT y saben como deberían de ser las señales...

Ocurren 3 cosas:

La PRIMERA es qué mi FFT es de 128 muestras para tener un vector final de 64 (la FFT entrega 128 pero la mitad es SIMETRICA).
Lo que ocurre ahí es que la pantalla es de 256 pixeles, en donde dejo 1 espacio de separación entre bines, pero me faltarían 64 bines más para acompletarla...

Entonces, lo que estoy haciendo, es "extrapolar" bines intermedios para precisamente rellenar los bines faltantes y tener 128 barras qué graficar...

Bien podría haber capturado mejor una FFT de 256 muestras de ADC y graficar las 128 que entrega, pero eso rompe dos puntos a mi consideración importantes:

1.- Una FFT de 256 muestras tiene más operaciones butterfly, lo cual NO es el doble de la FFT de 128 muestras sino más, al ser estas una potencia de 2.
Eso haría que se rompiera el paradigma del tiempo REAL y capturara menos FFTs o perdiera muestras de audio, lo cual se vería reflejado en los agudos...

2.- Después de años de hacer analizadores de espectro, la verdad es que, la FFT, al tener precisamente (como mencionas), bines MUY DEFINIDOS, solo cuando cambia la amplitud entre ellos cuando la frecuencia tiende a cambiar (levemente) entre ellos, lo cual se asemeja mucho a filtros pasabanda de ALTISIMO Q...

Eso es PRECISO pero no ESTETICO, pues cuando ves una versión de un "analizador de espectros" hecha con N filtros pasabandas y multiplexores, puedes notar que SIEMPRE entre los "bines" de esos analizadores hay una continuidad, dado el bajo Q de los filtros pasabanda....

A simple vista, puedes SABER cuando un analizador de espectros está hecho a matemática pura FFT o esta hecho con filtros pasabanda, e incluso por la forma de onda hasta puedes determinar qué tanta calidad o factor de mérito Q tienen sus filtros...

Entonces, el intercalar "bines" extrapolados, crea precisamente ese efecto, qué no se vea como una FFT pura y dura, y sí con un toque más estético (simulando filtros pasabanda)...

La SEGUNDA cosa qué ocurre es que la amplitud de mi FFT NO es lineal...
Esto es porque si te das cuenta, cuando metes audio a bajo volumen no se aprecian bien determinadas frecuencias y a alto volumen tiende a "aplanarse" debido a que estas cerca de la saturación del ADC...

Entonces, del vector de muestras qué obtengo como resultado de la FFT, aplico un filtro exponencial (antilogaritmico) que me permita ver mas la señal como un VUMETRO de audio, que como un medidor lineal...

Esa por ejemplo, es otra diferencia de cuando ves un VUMETRO hecho con el viejo y conocido LM3914 (lineal) versus el LM3915 (logaritmico)

La TERCERA cosa qué has notado, es ese vaiven generaro, el cual puedes ver en tu FFT también, (se nota menos por ser lineal y no tener extrapolaciones).
Este fenomeno o tremulo ocurre cuando la señal capturada termina en un valor diferente de 0, es decir, que si sampleas una señal senoidal, y su periodo no coincide con el numero EXACTO de muestras capturadas, lo que verás es que la FFT calcula ese valor como un pequeño desplazamiento en DC y que tiende a afectar a las frecuencias adjacentes y en conjunto a todas.

Se nota mucho cuando pones señales periódicas y hay varias maneras de MITIGAR ese efecto (ventana hamming, GAUS, Cuadrática etc) pero no tiene caso aplicar una ventana de amplitud a las muestras de audio pues éstas NUNCA van a ser periódicas...

Desconectado vixctor

  • PIC12
  • **
  • Mensajes: 98
Re:[Proyecto] Vúmetro con pantalla LED
« Respuesta #27 en: 19 de Mayo de 2017, 22:18:41 »
Citar
El primer punto que nunca estudié es que iba a pasar cuando el refresco de la pantalla (SPI + DMA1) compita por el bus con el muestreo de mediana velocidad (ADC + DMA1). En mi caso el micro (STM32F103RB) posee un solo módulo DMA y 7 canales. Cada canal puede manejar un periferico distinto. Pero la RAM es una sola y puede ser un problema si el SPI quiere LEER la RAM para escrivir en el SPI y a la vez el ADC quiere ESCRIVIR la RAM con los datos del ADC.

Bueno, a lo mejor en un ARM la tienes más fácil pero ahora imaginate hacer eso en un PIC...

El método qué propones es util y funciona, quizás porque en este caso solamente tienes 2 eventos: Capturar (y procesar) y Graficar...

Lo resuelves estableciendo el orden de las interrupciones, cosa qué es más "fácil" de hacer en un ARM dado sus multiples prioridades de interrupción pero no en un PIC...

En mi caso, en el PIC, lo procesos de la captura de muestras de audio, FFT, y graficación, en realidad son SECUNDARIOS pues el propósito principal del PIC, es estar leyendo el archivo de audio desde una tarjeta uSD y llenar el buffer de RAM del decodificador VS1063a, o sea, el objetivo PRIMARIO de mi sistema es reproducir audio, sin PAUSAS, por eso es qué la FFT e incluso graficación son solo procesos secundarios...

Habiendo explicado esto, lo que hice para resolver el problema fue lo siguiente:

Uso un solo timer MAESTRO, el cual está a 64 hz (para refrescar la pantalla a 64 FPS en lugar de 60).  Esto es porque es más fácil usar un refresco de tiempo en potencias de 2 que en decimal...

Ahora bien, lo que hago, es que ese timer dispara el evento de capturar muestras, y durante ese intervalo de tiempo, capturo y proceso todos los bloques de muestras y FFT posibles, tal qué en 64 Hz, puedo tener un máximo de 4 FFTs capturadas y guardando los picos de señal máximos...

pero no se cumple a rajatabla el que SIEMPRE tenga 4 FFTs, pues ocurre que además debo de graficar, tal que a veces de esas 4 partes de tiempo, ocupo 3 para FFT y 1 para graficar, lo cual hace que capture el audio 3/4 = 75% del tiempo y 1/4 (25%) del tiempo grafique los bines (más gráficos, el string de la canción rote etc)....

Ocurre también, que debo de leer el archivo de audio de la tarjeta uSD y enviarlo al decodificador VS1063A

Entonces, lo que hice, fue hacer un toogle cada 64 hz, lo cual me devuelve 32 hz...

En el primer periodo de 32 Hz, lo uso para FFT y graficación, en 32 Hz caben 8 FFT, pero debido a la graficación, de esas 8/8 ocupo 7/8 = 87.5 % del audio capturado y 1/8 en graficarlo, eso es mejor al 75% obtenido usando 3/4 partes del tiempo si usara solo 64 Hz para hacer todo...

En el segundo periodo de 32 hz, solo capturo audio y FFT pero uso el resto del tiempo para rellenar el buffer de audio del VS1063 y así no tener pausas en la reproducción...

Originalmente el tiempo era de "refresco" del VS1063A era de 1/8 luego paso a 1/16... 1/32, la razón es que si bien se puede "llenar el tanque" del VS1063a cuando este ha consumido todo el buffer de audio, es mejor rellenar su tanque cuando está al 70% de capacidad...

La analogía: Pasarías más tiempo en la gasolinera llenando el tanque por completo (45 lts) que solo rellenando ese cachito que le haga falta (10 o 15 lts)...

Jugar con los tiempos fue un dolor de cabeza y acomodarlos aun más, para qué todos los procesos corrieran sin interrupciones, se capturaran el mayor número posibles de muestras de audio, y si bien nunca voy a tener el 100% del tiempo de audio capturado, el tener al menos casi el 90% ya es mucha ganancia...

En resumen: Puedes acomodar tus procesos de graficación y FFT si los vuelves "sincronos" y distribuyes el tiempo en partes fraccionarias (en telefonía celular se llama TDMA) en lugar de dejar tus procesos asíncronos y que se resuelvan por interrupciones...

Desconectado vixctor

  • PIC12
  • **
  • Mensajes: 98
Re:[Proyecto] Vúmetro con pantalla LED
« Respuesta #28 en: 19 de Mayo de 2017, 22:23:38 »
Estoy analizando circuitos para amplificar un poco la señal de audio de entrada.

Que les parece esta opción?

 - Adjunto no válido -

No estoy seguro la amplitud de la señal de un reproductor de mp3 o la salida de audio de un celular... Tendría que hacer una medicion para ajustar la ganancia y quizá poner un preset para ajustar diferentes tipos de señal...

Saludos

El primer ADC, que usas para partir la alimentación en 2 es inecesario, puedes ahorrartelo y poner un divisor de voltaje directo en la entrada NO inversora del op amp que amplifica...

Los valores que usé Yo para el  op amp que amplifica son:

Rin = 680 ohms

R retroalimentacion = 2.8K

Cap In = 220 nanofaradios (evitará que satures siempre los bajos)

Cap retroalimentación = 1 nf

Es importante tener un "baja impedancia" de entrada en el amplificador pues así como lo tienes el capacitor de entrada de 10 uf quedará con mucha carga residual de DC...

Saludos...

Desconectado vixctor

  • PIC12
  • **
  • Mensajes: 98
Re:[Proyecto] Vúmetro con pantalla LED
« Respuesta #29 en: 19 de Mayo de 2017, 22:37:54 »
Por cierto, hace tiempo (8 años ya  :D) cuando hice mis primeros analizadores de espectro con la FFT pura y dura, así es como se veía...



Lo cual si bien era la representación fiel y matemática de la señal de audio NO me gustaba...

El circuito estaba hecho con 2 PICS 18F452 (ya obsoletos)

1 PIC generaba los gráficos en VIDEO y el otro PIC estaba encargado de la captura y procesado de la FFT...

Después fue cuando le añadí todos esos "artilugios" no reales pero estéticos...

PD: Viendo como se veía en aquellos años parecieran graficos de pasto mal cortado...  :-)




 

anything