Está en la página 1de 5

1

4.2. Programacin de un filtro digital


Programar un filtro digital de tercer orden que reponde a la ecuacin:
y(n)= 0,12678 y(n-1) 0,52388 y(n-2) + 0,12678 y(n-3) + 0,15892 x(n) +
0,47676 x(n-1) + 0,47676 x(n-2) + 0,15892 x(n-3)

Esta expresin se ha obtenido con el programa Matlab para un filtro con las
siguientes especificaciones:
|H(f)|

Filtro de Chebyshev.
Frecuencia de muestreo (fm): 4 khz.
Frecuencia de pasabanda (fp): 1 Khz.
Rizado en la banda pasante: 0,5db.

Pasabanda
Banda de transicin

Parabanda
2
fp

fs

Se pide:
4.2.1. Configuracin del convertidor analgico digital.
4.2.3. Variables que se utilizarn para implementar el filtro.
4.2.4. Diseo de la rutina de interrupcin peridica con el periodo requerido por el filtro
de Tm= 1/fm.
4.2.1. Configuracin del convertidor analgico digital.
- Registro ADCON0= 0b01000001

(ADCS<1:0>=01, CHS<2:0>=000 (RA0/AN0), ADON=1)

- Registro ADCON1= 0b01000000 (ADFM=0 (justificado izquierda), ADCS2=1, VCFG<1:0>= 00)


4.2.3. Variables que se utilizarn para implementar el filtro.
Se utilizarn dos variables: xn e yn. Ambas sern dos vectores de 4 flotantes que
almecenarn los valores actuales y anteriores de la salida (y(n), y(n-1), y(n-2), y(n-3)) y de
la entrada (x(n), x(n-1), x(n-2), x(n-3)). La declaracin en ensamblador de estas dos
variables sera la siguiente:
float xn[4];
float yn[4]

//xn[0]=x(n), xn[1]=x(n-1), xn[2]=x(n-2), xn[3]=x(n-3)


//yn[0]=y(n), yn[1]=y(n-1), yn[2]=y(n-2), yn[3]=y(n-3)

Los coeficientes son valores constantes que se declararn como vectores fijos (irn
en memoria de programa no de variables). Se distinguirn entre los coeficientes de las
entradas (a) y de las salidas (b). El ensamblador de estos dos vectores sera el siguiente:
const float a[4]= {0.15892, 0.47676,
const float b[4]= {1.0
, 0.12678,

0.47676, 0.15892
-0.52388, 0.12678

};
};

Serie 74HCxx

4.2.4. Diseo de la rutina de interrupcin peridica con el periodo requerido por el


filtro de Tm= 1/fm.
Se utilizar el temporizador TMR0. El periodo de repeticin de la rutina ser Tm=
1/4khz= 250s. Se configura con el preescaler a 1:2, TMR0=6 .
static void interrupt rutinaInterrupcion(void)
{
//
//
//
//
//
//
//
//

--------------------------------------------------------------Temporizacin a 250us (Fosc=8Mhz, es el PIC16F88)


Tiempo= 4.Tosc.(256-TMR0).Preescalador
Si Tosc=0.125us (Fosc=8Mhz), TMR0=6
Tiempo= 4.(0.125us).(256-6).2= 250us

y Preescalador= 1:2 ->

---------------------------------------------------------------

// Interrupcin debida al desbordamiento de TMR0


if(TMR0IF)
{
GODONE=1;
// Dispara la conversin
while (GODONE==1) { }
// Espera a que termine (GO_DONE=0)
//--------filtro();
//--------TMR0
= 6;
TMR0IF = 0;

// Preparamos TMR0
// Bajamos la bandera. Evento: desbordamiento de TMR0

}
}

La rutina Filtro() recibir del registro ADRESH el valor digital de la nueva conversin
A/D del pin AN1 (los 8 bits de ms peso). Este valor es x(n) y se obtendr leyendo el
registro ADRESH. A partir de este valor esta rutina calcular el nuevo valor de y(n). La
conversin A/D de la seal as como el filtrado digital de dicha seal llamada a la rutina
Filtro- deben hacerse de forma peridica por lo que estas tareas han de realizarse desde la
interrupcin del TMR0I.
La rutina Filtro es la sucesin de ciertas multiplicaciones, sumas y restas para
resolver la ecuacin:
//================================
// filtro()
//================================
void filtro()
{
// -------------------------------------------// Actualizamos las entradas
// -------------------------------------------xn[3]= xn[2];
// x(n-3)= x(n-2)
xn[2]= xn[1];
// x(n-2)= x(n-1)
xn[1]= xn[0];
// x(n-1)= x(n)
xn[0]= ADRESH;
// x(n) = valor convertido (8 bits ms significativos)
// -------------------------------------------// Actualizamos las salidas excepto y(n) -> Objetivo de este algoritmo
// -------------------------------------------yn[3]= yn[2];
// y(n-3)= y(n-2)
yn[2]= yn[1];
// y(n-2)= y(n-1)
yn[1]= yn[0];
// y(n-1)= y(n)
yn[0]= b[1]*yn[1]+b[2]*yn[2]+b[3]*yn[3]+a[0]*xn[0]+a[1]*xn[1]+a[2]*xn[2]+a[3]*xn[3];
if (yn[0]<0.0) yn[0]=0.0;

// saturacin por abajo

// -------------------------------------------// Enviamos la seal filtrada y(n) al CD/A


// -------------------------------------------PORTB= (byte)yn[0];
pulsoRA2();
// Pulso en la entrada LE del DAC
}

Problema 16

Al ejecutar el programa se aprecia que la rutina de interrupcin requiere tiempos


superiores a los 3 ms para ejecutar el cdigo de la rutina filtro. Esto es debido a las libreras
para el manejo de flotantes que necesitan mucho cdigo. Si la interrupcin debe repetirse cada
250us, su contenido tendra que ejecutarse antes de ese tiempo y resulta que necesita cerca de
10 veces ms. Un solucin sera subir la frecuencia del reloj pero no es viable ya que habra
que multiplicarla por 10 (80Mhz) y el 16F88 admite hasta 20Mhz. La solucin pasa por
redondear los nmero flotantes y utilizar enteros.
Si se programa en ensamblador hay que tener presente varias cosas: (a) el juego de
instucciones no permite sumar y restar elementos de dos bytes, solo de un byte, y (b) no hay
intruccin para multiplicar por lo que habra que disear las multiplicaciones como sumas de
sumandos iguales. Esta opcin del ensamblador es viable pero costosa en tiempo ya que
habra que disear libreras en ensamblador para sumar elementos de 2 bytes as como para
las multiplicaciones.
La opcin elegida ser programar en C utilizando variables de tipo entero. Sin embargo, la
rutina de interrupcin sobrepasa los 250us si se utiliza la instruccin multiplicar enteros del
lenguaje C. Por tanto, las multiplicaciones se realizarn como sumas de elementos de la forma
ms ptima posible. Pongamos un ejemplo: disear con sumas la multiplicacin 61*dato.
- Una posibilidad sera sumar (dato+dato+ +dato) hasta 61 veces para
conseguir la multiplicacin. Computacionalmente es muy costoso y no interesa.
Sera ms rpida la instruccin de multiplicar en lenguaje C.
- Buscaremos el nmero potencia de 2 ms prximo a 61 que es 64.
- dato= dato << 6. Desplazando dato 6 posiciones a la izquierda se consigue
64*dato. Es decir, sera sumar 64 veces dato.
- Si al valor anterior le restamos 3 veces dato se tienen 61 sumas de la variable
dato, es decir, 61 * dato que era el objetivo.

Explicacin de cmo se operar algebraicamente para trabajar con coeficientes que


tienen decimales.
La salida digital del convertidor ser un nmero positivo de 8 bits (se ignorarn los dos
de menor peso) en el rango que va de 0 a 255. Este nmero ser proporcional a la tensin de
entrada analgica cuyo rango es de 0V a 5V. Obviamente, la salida debe ser la misma entrada
pero sin ruido por lo que la seal de entrada estar en el mismo rango de 0V a 5V.
La ecuacin que rige el comportamiento del filtro tiene coeficientes constantes con
valores decimales.
y(n)= 0,12678 y(n-1) 0,52388 y(n-2) + 0,12678 y(n-3) + 0,15892 x(n) +
0,47676 x(n-1) + 0,47676 x(n-2) + 0,15892 x(n-3)

Para convertir estos coeficientes a nmeros enteros se multiplicarn y dividirn los


trminos de la derecha de la expresin del filtro por un nmero que debera cumplir las
siguientes caractersticas:
- Debe ser lo mayor posible (mayor precisin) pero garantizando que cualquier
multiplicacin entre un coeficiente ahora es un valor entero- por su variable
no active el bit ms significativo (la multiplicacin ser sin signo).
- Es conveniente que sea potencia de 2 para que la divisin se pueda realizar
con un simple desplazamiento de posiciones a la derecha del resultado.

Serie 74HCxx

- El resultado de cada iteracin implica que la salida y(n) ser un dato similar al
de la entrada x(n) pero de 8 bits sin signo (positivo).
El mejor valor para las restricciones indicadas es 128. La ecuacin del filtro con
coeficientes enteros quedara de la siguiente manera:
y(n)=

1
( 16.y(n-1) - 67.y(n-2) + 16. y(n-3) + 20. x(n) + 61.x(n-1) + 61.x(n-2) + 20.x(n-3) )
128

expresado de forma genrica permite identificar sera:


y(n)=

1
(b1.y(n-1) - b2.y(n-2) + b3. y(n-3) + a0. x(n) + a1.x(n-1) + a2.x(n-2) + a3.x(n-3) )
128

Si se representa la curva caracterstica del filtro con los coeficientes originales y con los
coeficientes enteros se aprecia que es muy similar y no se ha perdido mucha informacin
debido a la discretizacin.
Frecuencia normalizada (Chebyshev)
20

-20

Amplitud - dB

-40

-60
Coeficientes
enteros
-80

-100

-120

Coeficientes
con
decimales

-140

-160

0.5

1.5

2.5

3.5

En la siguiente figura se muestra como quedara el resultado despus de sumar todos los
productos de la expresin de y(n) pero antes de dividirlo entre 128. Se sabe que dividir por un
nmero potencia de 2 equivale a tantos desplazamientos a la derecha del registro como valor
tenga la potencia. El nmero 128 es 27 lo que implica que dividir por l es lo mismo que
realizar 7 desplazamientos a la derecha de la variable que contiene el resultado.
0

Byte alto

Byte bajo
Resultado de 16 bits

El bit ms significativo es de signo y estar a 0 ya que se ha tenido precaucin de que


el resultado final sea positivo. Al realizar 7 desplazamientos a la derecha se obtendra el
resultado (8 bits sombreados) .

Problema 16

La rutina que realiza el producto -67*y(n-2) se muestra a continuacin. Se apoya en una


variable auxiliar de tipo int llamada aux y el se acumula este producto en la variable
resultado.
//================================
void MULx67(byte dato)
//================================
{
aux= (int)dato << 6;
// Desplazar 6 veces equivale a multiplicar por 64.
aux+= dato;
// Al resultado le sumamos 3 veces el dato y queda
aux+= dato;
// multiplicado por 67
aux+= dato;
resultado=resultado-aux; //Finalmente se resta ya que el coeficiente es -67
}

Estmulos para la simulacin.


Se utilizar una seal senoidal con un offset para que toda ella est dentro del rango 0V-5V
que son las tensiones de referencia del convertidor A/D. Se le aadir un ruido que se simula
por una senoide de pequea amplitud y de 2khz . Dado que el filtro digital elimina aquellas
frecuencias que superen la frecuencia de corte (1Khz), dicha seal superpuesta desaparecer a
la salida del filtro.
La seal de entrada ser la suma de dos senoides: (a) 50hz, offset=2V, amplitud=1V, y
(b) 2khz, offset=0V, amplitud= 0.1V. Para generar esta seal se utilizar un sumador no
inversor como el de la figura con todas sus resistencias de 1K para que la salida Vo= V1+V2.

También podría gustarte