TODOPIC

Microcontroladores PIC => dsPIC => Mensaje iniciado por: latha en 16 de Septiembre de 2008, 13:50:19

Título: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: latha en 16 de Septiembre de 2008, 13:50:19
ALGUIEN HA INTENTADO HACER LOS FILTROS FIR SIN USAR LAS LIBRERIAS DSP?????

SALUDOS DSD MALAGA.
Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: blackcat en 16 de Septiembre de 2008, 19:43:13
Yo solo con la libreria y funcionan bien ! ..  :?

Sin embargo, en el libro: Digital Filter Designer's Handbook: Featuring C Routines/Book and Disk vienen rutinas en C sobre filtros FIR
Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: vtasco en 17 de Septiembre de 2008, 22:58:53
creo que el tiempo de ejeecución subirá notoriamente, necesitas usar punto flotante?
Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: latha en 18 de Septiembre de 2008, 06:22:44
El tiempo de ejecucion y todo, la idea era configurar el direccionamiento circular pero puff,  es usar punteros y se va toda la transmision spi al carajo, lo intentare para probar con un array manual jaja, a ver como va eso.

Por cierto, como le digo a un puntero que me apunte a una direccion fisica, tipo 0xFF00, donde guardo los coef.??

Saludos.
Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: blackcat en 19 de Septiembre de 2008, 00:48:24
Mucha gente confunde punto flotante con precision ... el punto flotante se diseño para trabajar con rangos numéricos variables .. sin embargo el punto fijo, si tuviera la misma cantidad de bits que punto flotante .. 32bits, ofrecería la misma precisión pero con la desventaja que el rango numérico debe ser fijo .. es decir .. se define que las operaciones y resultados se ubican dentro de un rango ... por ejemplo .. el formato fractional Q15 es de -1 a 0.9999 .. algunas librerias de microchip estan introduciendo el punto fijo con 32 bits .. si no me equivoco, por ahi lo lei  ... otra desventaja es la representación con hexa .. y pues claro .. mucha gente utiliza punto flotante porque es mas bonito ..  :-) .. PERO hay que apoyar la velocidad de procesamiento que ofrece punto fijo respecto a punto flotante .. ademas punto fijo si es bien utilizado da excelentes resultados .. yo trabaje con punto fijo y todo bien .. ahora estoy con unos variadores de frecuencia que usan DSPs en punto fijo y son bastante buenos ..

Disculpa mi ignorancia pero no sé que quieres decir con dirección fisica.

En C todos los punteros se declaran con un asterisco *

Ejemplo:

int una_variable = 5;    // Un dato

int * ptr_una_variable = &una_variable // Puntero a una_variable, el simbolo & significa devolver puntero.

tambien hay punteros a punteros

int ** ptr_ptr_una_variable = &ptr_una_variable  // ptr_ptr_una variable es un puntero a un puntero que apunta a una_variable  :? observa el doble asterisco

Esto es muy util cuando se utilizan structs que tienen punteros ...

Ademas, hay punteros a funciones .. que son de gran ayuda cuando debes seleccionar entre varios algoritmos y evitar el uso de case

 
Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: latha en 19 de Septiembre de 2008, 06:21:24
Direccion fisica es la posicion de memoria donde guardo el dato, el espacio de datos x, y el espacio de datos y, para hacer el filtro fir, logro definir dichos espacios mediante instrucciones del tipo:

fractional _XBSS(128) xbuf[7]; para un fir de 7 coeficientes.
fractional __attribute__((space(ymemory), far, reverse(128))) ybuf[7]; para el buffer de muestras pasadas

Para acceder a estos datos hablamos de un array,, y entonces tengo que indexar, por lo que pierdo la potencia del buffer circular, o eso creo.

Si alguien sabe algo de esto, que me lo comente, lo del tipo de datos pues la libreria dsp usa fractional, yo no la uso, pero sigo con ellos por algo sera que lo usa.

Por cierto tambien configuro el CORCON y XMODSRT , etc pero no se si el espacio de memoria es realmente circular.

Donde podria ver los atributos para reservar memoria pues las lineas anteriores las saque de un ejemplo

Saludos dessde malaga.
Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: latha en 21 de Septiembre de 2008, 06:16:11
Buenos dias a todos¡, querria saber si alguien me podria dejar algun ejemplo de manejo de un array en el espacio de memoria X o Y con punteros, puesto que.... cuando accedo a esos datos mediate punteros, se me resetea el dspic, y la otra opcion que es acceder a los datos mediante el indexado, pues no se que formato poner, si pongo los coeficientes de modo 0xdf02, segun me los devuelve una aplicacion, al hacer las multiplicaciones del filtro fir, las muestras de salida son todo saturacion, como podria arreglar eso?, que formato deberia usar? y debo configurar el CORCON o algun otro registro?

A este ritmo me paso a ensamblador.

Gracias por leerme
Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: latha en 21 de Septiembre de 2008, 13:18:08
HOLA SOY BASTANTE PESADO, y cada vez dudas distintas....

tengo el siguiente texto para conseguir un eco pero muy rapido pues el Si3000 que le puse va a 12000Khz y
solo tengo 500 muestras para el buffer por la limitacion del espacio de memoria x.
Porque no me funciona esto, es decir porque no se reproduce nada de audio,si saco la entrada a la salida si se oie
la cancion que pongo de entrada.


extern int muestras[512];
int = 1;

int Programita( int Entrada)
{

int SalidaAnterior,Salida;

SalidaAnterior = muestras;
Salida = (( SalidaAnterior/2) + Entrada);
muestras= Salida;
i++;
if ( i==513)
{
i = 1
}


}
Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: learntofly en 25 de Septiembre de 2008, 04:31:23
Hola! Yo no se muchisimo sobre lenguaje C, pero los FIR los suelo escribir asi:

//variables ecuacion filtro//
float hn[5]={0.2,0.2,0.2,0.2,0.2}
float xk[5];
void VectorCero(float x[],int n)
{
   int i;
   for(i=0;i<n;i++)
      x=0.0;
}

void VectorDesplaza(float x[],int n)
{
   int i;
   for(i=n-1;i>0;i--)
      x=x[i-1];
}
void _ISR _ADCInterrupt()
{,
.
.
.//Filtro de media//
   desp xk[];
   desp yk[];
   xk[0]=nuevo;
   yk[0]=ProdEsc(xk, hn);
}
Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: latha en 25 de Septiembre de 2008, 11:56:29
tengo el siguiente codigo para un fir de 5 coeficientes para empezar donde solo uno de ellos es un uno , con lo que se debe oir por la salida la entrada realimentada.

Este es el codigo :

static float XBUFF[5];
const float COEF[5]={0.0, 1.0 , 0.0, 0.0, 0.0};
static int=0;

fractional CODIGOAUDIO( fractional Entrada)
{

Declaracion variables.

for(i=4;i>0;i--)
{

XBUFF =XBUFF[i-1];
}

EntradaF= (float) Entrada;
XBUFF[0]= EntradaF;

for (i=0;i<=4;i++){
Muestra_filtrada=(Muestra_filtrada + (COEF*XBUFF));
}
Salida =(fractional) Muestra_filtrada;
return Salida;
}

El problema esta en.... que cuando ejecuto esto se me escucha el audio pero muy muy muy bajo y con mala calidad, incluso si el return es de Entrada; pero lo curioso es que si elimino la linea: Muestra_filtrada= ,,,,,,,,,,,,,,,,,,,  y hago return Entrada si se oye perfectamente. Entonces el problema puede ser que llega otra muestra antes que se procesen esas 5 multiplicaciones...????
Si alguien se le ocurre algo, yo he pensado hacer ese for con instrucciones ensamblador, y si puede ser con un DO pero no se si se puede añadir ensamblador aqui.

Saludos y gracias

Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: blackcat en 25 de Septiembre de 2008, 23:06:04
No entiendo varias cosas ...

1.

Código: [Seleccionar]
for(i=4;i>0;i--)
{
    XBUFF =XBUFF[i-1];
}

Esto daria error en la compilación puesto que es el mismo registro y ademas es un arreglo ...  :?  ... supongo que es un desplazamiento de entradas.

2.
Código: [Seleccionar]
EntradaF= (float) Entrada;
XBUFF[0]= EntradaF;

Porque no simplemente XBUFF[0]= (float) Entrada;


3.

Código: [Seleccionar]
for (i=0;i<=4;i++)
{
   Muestra_filtrada=(Muestra_filtrada + (COEF*XBUFF));
}

Que funcionalidad tiene el FOR ??


4.  ... la pregunta del millon ....

Un filtro FIR no tiene "realimentación" .... esto es:      y[n]=b_0 x[n] + b_1 x[n-1] + ... + b_N x[n-N] ... es decir no utiliza resultados de salidas pasadas para calcular una salida (esto seria un IIR), se podria entender como un sistema a lazo abierto, es por esta razon, que un FIR es 100% estable ante toda entrada ...

Sin embargo, estas haciendo:  Muestra_filtrada=(Muestra_filtrada + (COEF*XBUFF));  haciendo una suposición y una correccion:

Código: [Seleccionar]
for (i=0;i<=4;i++)
{
   Muestra_filtrada=(Muestra_filtrada + (COEFF[i]*XBUFF[i]));
}

Si b[] es COEFF[] y x[] es XBUFF[] lo interpretaria de la siguiente manera:

y[n] = y[n-1] + y[n-2] + ... + y[n-N-1] + b_0 x[n] + b_1 x[n-1] + ... + b_N x[n-N]


Ese tipo de filtro no lo conozco (ni FIR, ni IIR) ... supongo que te equivocaste si pudieras hacer las correcciones ... te podria ayudar ...

Consejos:

1. Podes utiilzar matlab para corroborar tu filtro .. ahi podes ver la respuesta en frecuencia y en el tiempo y luego comparar los resultados ante señales de prueba como escalones e impulsos.

2.Tambien, utiliza la opcion de INSERTAR CODIGO ( simbolito de #) ... sino lo utilizas es posible que a la hora de publicar tu mensaje este quite algunos caracteres.

saludos!













Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: latha en 26 de Septiembre de 2008, 06:11:46
insertar codigo, que invento, me faltan caracteres por todo el codigo.
El primer for es para desplazar las entradas, falta el indice XBUFF [ i ]=XBUFF[i-1],con lo que consigo en XBUFF[4] la muestra de entrada de hace 5 pasos, y en XBUFF[0], la actual muestra de entrada.
Luego solo multiplico entradas ,puesto que solo guardo entradas en flotante, y el for es para hacer todas las multiplicaciones del filtro en este
caso son 5 pues hay 5 coeficientes, y el resultado se acumula en Muestra_filtrada, y solo es el coeficiente*muestra_entrada correspondiente.

Saludo y gracias
Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: jgpeiro06 en 13 de Octubre de 2008, 10:57:57
Llevo un par de semanas peleandome con los filtros FIR e IIR. Los filtros IIR no se si no los he implementado bien o no son estables por la cuantificacion o yo q se... pero los FIR si parecen funcionar bien.

este es el codigo:

int N = 3;                 // Filter order
int x[3+1];               // input and output signal buffer
const int h[3+1] = {  //FIR filter zeros coefficients
0.25 *32767,
0.25 *32767,
0.25 *32767,
0.25 *32767
};

// y[n] = SUM(h*x[n-i],i,0,N);
int FIR( int value, int *x, const int *h, unsigned char N )
{
   long sum = 0;
   int i;
   
   for( i = N ; i > 0 ; i-- )
      x = x[i-1];

   x[0] = value;

   for( i = 0 ; i <= N ; i++ )
      sum += (long)h * (long)x;

   return sum >> 15;
}

void main()
{
    int in, out;
    while(1)
    {
        in = readADC();
        out = FIR( in, &x[0], &h1[0], N );
        delay();
    }
}



Los coeficientes los genero con el con el FDATOOL del Matlab.
Ahi va el codigo para los IIR Direct Form I (OJO que es posible que no este bien implementado)

//IIR Direct Form 1: y[n] = SUM(a*y[n-i],i,1,N) + SUM(b*x[n-i],i,0,M);
int IIR_DF1( int value, int *x, int *y, const int *a, const int *b, unsigned char N )
{
//   ; N = filter order
//   ; x[N+1],y[N+1] = input and output signal buffer
//   ; a[N+1], b[N+1] = IIR filter poles and zeros coefficients
   long sum = 0;
   int i;

   for( i = N ; i>=0 ; i--)
   {
      x = x[i-1];
      y = y[i-1];
   }
   
   x[0] = value;
   
   for( i = 0 ; i <= N ; i++ )
      sum += (long)b * (long)x;
   for( i = 1 ; i <= N ; i++ )
      sum += (long)a * (long)y;   //¿sum -= (long)a * (long)y;   ?
   
   y[0] = sum >> 15;
   return y[0];
}


Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: jgpeiro06 en 13 de Octubre de 2008, 11:12:57
no se que xq pero el codigo no se ha copiado bien...
Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: latha en 14 de Octubre de 2008, 07:54:17
Hola a todos, tu filtro fir en numeros enteros esta correcto, pero a mi me gustaria usar el tipo fraccional aunque no se del todo si merece la pena, lo intento hacer en fraccional pero no hay manera, en la simulacion veo como los resultados son en enteros, si alguien ha hecho multiplicacines en fraccional 1.15 no me vendria mal que me enviase el proyecto , esto seguro que parte del fallo es que defino algo mal puesto que al ver el codigo ensamblador correspondiente usa las instrucciones mul y no la instruccion mpy que la cual se puede configurar en entero o fraccional puesto que la instruccion mul que me usa en el codigo ensamblado solo multiplica enteros y ahi esta todo el problema.
Gracias.

Respecto al filtro IIR es probable que no sea estable puesto que en princpio parece correcto el codigo.

Saludos desde Malaga.
Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: blackcat en 16 de Octubre de 2008, 01:11:57
Claro que si merece la pena ... la libreria C de filtros IIR y FIR  tarda unos cuantos microsegundos en comparación a la realizacion en punto flotante  ... las rutinas de la libreria estan muy bien optimizadas y se saca el máximo provecho al dsPIC .. recordemos que el dsPIC incorpora la funcion MAC y operaciones aritmeticas leyendo dos sitios de memoria al mismo tiempo (memoria X y Y) ..

En cuanto a la resolución ... se podria decir que es muy buena, yo lo he utilizado para control automático en sistemas de orden 8 y cascadas de sistemas en orden 2 y todo perfecto .. .. solo hay que tener claro que el rango de operacion debe ser entre -1 a 1 ..

Respecto a las multiplicaciones .. si es extraño como microchip no ha hecho una libreria de matematicas para multiplicaciones en fraccionario 1.15 ... por ahi andan unas rutinas de funciones trigonometricas pero hace mucha falta una de operaciones básicas ...  yo me hice mi propia rutinita de multiplicacion ... claro en ensamblador ...

Primero esta el archivito .s que contiene la rutina de multiplicacion:

Código: ASM
  1. ;
  2. ; file: mult16x16.s
  3. ;
  4.  
  5. .global _mult15
  6.  
  7. _mult15:
  8.  
  9. MUL.SS  W0, W1, W0
  10.  
  11. RLC     W0, W0
  12. RLC     W1, W1
  13.  
  14. MOV     W1, W0
  15.  
  16. return
  17. .end


Ahora si quiero colocarla en código C .. importo el archivo y declaro lo siguiente:

Código: [Seleccionar]
extern int mult15(int, int);

... un programita de ejemplo ...

Código: C
  1. extern int mult15(int, int);
  2.  
  3. void  main (void)
  4. {
  5.  
  6.         fractional numeroA = 0x7FFF;   // 1.0 en fraccional
  7.         fractional numeroB = 0x3FFF;   // 0.5 en fraccional
  8.         fractional resultado;
  9.  
  10.         resultado = mult15( numeroA, numeroB );
  11.  
  12.         while(1);
  13. }

El valor de resultado fue 0x3FFE ... un pequeño error pero asi es este formato ..  :?
Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: latha en 16 de Octubre de 2008, 06:10:44
Perdona mi ignorancia, pero con esa rutina no deberias multiplicar enteros con signo??, de todos modos voy a probar tal como lo tienes ahi, y luego en caso de necesidad usare la instruccion MPY con una previa carga del registro CORCON correspondiente.

Saludos desde Malaga. Raúl.
Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: jgpeiro06 en 16 de Octubre de 2008, 13:08:12
el codigo que te mande si que trabaja con fraccionales 1.15. Bueno, xa el compilador son enteros, pero se tratan como fraccionales. Las operaciones + y - con fraccionles son iguales que con enteros. es en las operaciones de multiplicacion y division donde cambia un poco la cosa.
Los fraccionales tienen un rango entre +1 y -1 entonces la multiplicacion de 2 numeros fraccionales no padra ser mayor que el mayor de los dos multiplicandos.

La ventaja de trabajar con enteros es que es totalmente independente de la plataforma, en mi caso es imprescindible xq estoy trabajando con pic24.

Código: C
  1. long sum = 0; int x[10], h[10];
  2. for( i = 0 ; i < 10 ; i++)
  3.     sum += (long)x[i] * (long)h[i];
  4. sum >>= 15;// "reescala el resultado a un rango entre +1 y -1", solo se realiza la ultima vez

las operacion long += long * long se hace en unos 10 ciclos y acceder a los indices y controlar las iteraciones en otros 20 asi que no me importa mucho el tiempo que tarde en hacer las multiplicaciones puesto que ya tarda bastante en acceder a los indices y demas.

Si miras el codigo equivalente a hacer las multiplicaciones en C no son mucho mas de 5 instrucciones. y escalar los resultados solo es necesario una vez al terminar el bucle....

En mi opinion es mas rentable optimizar el codigo utilizando las opciones del compilador y dejar un codigo clarito y portable en C, y si nuestra aplicacion es mas exigente utilizamos un dsPIC y las librerias que proporciona microchip.

Editado por Nocturno: he incluido Geshi en el código porque se veía mal
Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: blackcat en 16 de Octubre de 2008, 23:10:06
Perdona mi ignorancia, pero con esa rutina no deberias multiplicar enteros con signo??, de todos modos voy a probar tal como lo tienes ahi, y luego en caso de necesidad usare la instruccion MPY con una previa carga del registro CORCON correspondiente.

Saludos desde Malaga. Raúl.

Vamos a ver si entendi ... pero con solo poner int el compilador supone que es entero con signo ... es igual que poner signed int... para poner enteros sin signo se utiliza unsigned int ...

Esa rutina la utilizo mucho y siempre me ha funcionado .. aqui otros resultados:


numeroA = 0x8001 ... que es -1.0 en fraccional
numeroB = 0x3FFF ... que es 0.5 en fraccional

resultado fue: 0xC001 ... lo que corresponde a -0.5 ... ahora hagamos -0.5 x -0.5 .. deberia ser 0.25 .. que en fraccional es 0x1FFF .. entonces:

numeroA = 0xC001 ... que es -0.5 en fraccional
numeroB = 0xC001 ... que es -0.5 en fraccional

resultado fue: 0x1FFF .. como fue de esperar ... !! ...  :)


Recuerda que para pasar de flotante a fraccionario y viceversa .. podes usar las funciones:

Float2Fract y Fract2Float

de la libreria DSP de microchip ...

Mi idea en este caso es hacer las multiplicaciones con el menor código posible .. en total realizar la multiplicación y mover el resultado a resultado tardó 0.3us

Si tienes alguna mejora ... me gustaria tu sugerencia!

Saludos!!








Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: latha en 18 de Octubre de 2008, 10:32:33
hola a todos, el problema con tu rutina no era que no entendiese entre enteros con o sin signo, solo que la instruccion ensablador que usabas no diferenciaba de entero o fractional, hice la simulacion y no lo consegui, use la multiplicacion MPY y lo carge en el Acumulador A, para luego sacarlo fuera de la funcion en ensablador, y si logre la multiplicacion en flotante que tanto me costo, seguramente tengo algo mal definido y la instruccion MUL solo entendia de enteros.

Pongo aqui la rutina que es basicamente la tuya.

.global _multfractional

_multfractional

PUSH CORCON
MOV #0x0010,W3
MOV W3,CORCON
MOV W0,W4
MOV W1, W5
MPY W4*W5,A
SAC A,W0
POP CORCON
return
.end

Un saludo desde Malaga.

P.D: El filtro FIR con enteros y usando long para guardar el resultado con el posterior desplazamiento va de escandalo, pero para un filtro IIR donde los coeficientes ya no son todos del mismo orden necesitaba hacerlo en fractional para que todos los numeros sean menores que uno, y tampoco me servia usar flotantes puesto que con tres multiplicaciones en flotante, el paso de muestras entre el codec y el dspic a traves del bus SPI se me dejaba de funcionar.

Cuando acabe todo el proyecto no tengo problemas en mandar info a quien este interesado.
Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: blackcat en 18 de Octubre de 2008, 14:15:35
Entiendo que queres multiplicar datos en formato fractional esto es números desde -1 hasta 0.999969482 ... ahora para que los enteros?? el problema básico es que no encuentro una forma rápida y optimizada de realizar multiplicaciones ... revise y simule tu código y obtuve buenos resultados ... ese código tiene mas lógica...  lo que no me queda claro es para que habilitas la supersaturacion 9.31 ..

Seria interesante hacer multiplicaciones en Q16 ... microchip incorpora ya unas funciones para esto .. dejo un  ejemplo tomado del pdf 16-BIT LANGUAGE TOOLS
LIBRARIES
que se encuentra en la carpeta C:\Program Files\Microchip\MPLAB C30\docs de la version 8.14 de MPLAB

_Q16mac
Description: This function multiplies the two 32-bit inputs, x and y, and accumulates
the product with prod. The function takes care of saturating the result
in case of underflow or overflow.


 
Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: latha en 19 de Octubre de 2008, 07:22:26
HOLA, Activar la supersaturacion, pues sinceramente estaba tan cansado de configurar el CORCON que lo vi en un ejemplo y lo puse asi , jeje, lo unico interesante era hacer las multiplicaciones en fractional y con signo y sabia que con 0x0010 estaba conseguido eso.

El tema de los enteros fue en referencia a la ayuda aportada por un compañero solo comentaba que iva estupendamente para los FIR.

P.D: No tengo ese MPLAB ,¿como puedo acceder a esa info, sin tener esa version de MPLAB?.

Saludos desde Malaga.

Raúl.
Título: Re: FILTROS FIR SIN LIBRERIA , todo en c
Publicado por: blackcat en 19 de Octubre de 2008, 16:26:40
De igual forma ... se abre la carpeta donde esta el mplab y busca la carpeta de docs ...

Otro asunto es que no configure CORCON con el valor de 0x0010 .. lo deje como 0x0024 .. es decir el valor original y me funciona igual ...

En cuanto a la supersaturacion no la creo necesaria pues en "teoria" las multiplicaciones en de dos terminos en fractional no deberia saturar ...

Saludos!!