Estoy intentando implementar un filtro IIR de primer orden simple en una MCU (PIC24FJ32GA002), sin éxito hasta ahora. El filtro es un filtro de seguimiento de CC (filtro de paso bajo) cuyo propósito es rastrear el componente de CC de una señal de 1.5Hz. La ecuación en diferencias se tomó de una nota de aplicación de TI:
y (n) = K x (n) + y (n-1) (1-K)
con K = 1/2 ^ 8
Hice un script de MATLAB para probarlo y funciona bien en la simulación. Código utilizado:
K=1/2^8
b = K
a = [1 -(1-K)]
Fs=200; // sampling frequency
Ts=1/Fs;
Nx=5000; // number of samples
nT=Ts*(0:Nx-1);
fin=1.5; // signal frequency
randn('state',sum(100*clock));
noise=randn(1,Nx);
noise=noise-mean(noise);
xin=200+9*(cos(2*pi*fin*nT));
xin=xin+noise;
out = filter(b,a,xin);
Sin embargo, no puedo implementarlo en un microcontrolador PIC24F. Estoy representando los coeficientes en formato Q15 (1.15), almacenándolos en variables cortas y utilizando uno largo para las multiplicaciones. Aquí está el código:
short xn;
short y;
short b0 = 128, a1 = 32640; // Q15
long aux1, aux2;
// (...)
while(1){
xn = readADC(adc_ch);
aux1 = ((long)b0*xn) << 1;
aux2 = ((long)a1*y) << 1;
y = ((aux1 + aux2) >> 16);
delay_ms(5);
}
La conversión a largo se usa para extender la señal, por lo que la operación de multiplicación se realiza correctamente. Después de cada multiplicación, muevo un bit a la izquierda para eliminar el bit de señal extendida. Al sumar, cambio a la derecha 16 bits para obtener y en formato Q15.
Estoy depurando la MCU con Pickit2 y la ventana "Ver - > Ver" (MPLAB IDE 8.53) y probando el filtro con una señal de CC (cambio la señal de CC con un potenciómetro para probar diferentes valores). El ADC tiene una resolución de 10 bits y la MCU se suministra con 3.3V. Algunos resultados:
1V - > xn = 312 (correcto), yn = 226 (incorrecto)
1,5 V - > xn = 470 (correcto), yn = 228 (completamente incorrecto)
¿Qué estoy haciendo mal? ¿Alguna sugerencia sobre cómo implementar este filtro IIR en una MCU de 16 bits?
Muchas gracias de antemano :)