Estoy tratando de implementar un filtro de parada de banda (muesca) en un microcontrolador dsPIC33EP64GS506
para filtrar un 100 Hz
componente de una señal de entrada. El problema aquí es que mi microcontrolador no tiene una unidad de punto flotante, así que tengo que usar una aritmética de punto fijo, pero para ser más preciso, uso aritmética de enteros. El tiempo de muestra del sistema es
. Aquí explico mi problema en detalle, y las preguntas están al final de la publicación. Encuentre adjunto un código MATLAB para ejecutar simulaciones si lo desea: enlace de descarga en mi Dropbox . Tenga en cuenta que no tiene que ser un usuario registrado de Dropbox para poder descargar el archivo.
La resolución de ADC es 12b
, a la que "aumento" 15b
, no para aumentar la resolución de medición (que no se puede hacer), sino para aumentar la resolución del filtro:
v_in = ADCBUF0<<3;
La función de transferencia de filtro de muesca en el dominio s se da como:
donde filtrar parámetros
,
, y
determinar completamente el filtro. Si queremos filtrar un 100 Hz
componente, entonces establecemos
. En cuanto a otros parámetros, sin explicaciones detalladas, uso
y
. Para implementar este filtro en un sistema digital, necesitamos discretizar la función de transferencia en s-domain, y para eso utilizo un método de discretización de Tustin .
La ecuación recursiva correspondiente, implementada en un sistema digital, es:
Aquí está el código de MATLAB para obtener la función de transferencia en el dominio z:
Ts = 50e-6;
zeta1 = 0.001;
zeta2 = 1;
wn = 100*(2*pi);
Gs = tf([1 2*zeta1*wn wn^2], [1 2*zeta2*wn wn^2]);
Gz = c2d(Gs, Ts, 'tustin');
bodeplot(Gz);
Consulte a continuación las características de frecuencia del filtro en el dominio z generado por MATLAB. Como se puede ver, este tipo de filtro es muy sensible en términos de respuesta de frecuencia. Incluso los cambios más pequeños en los parámetros podrían causar un comportamiento completamente diferente, por ejemplo, una ganancia inesperada, cambio de fase, etc.
Ahora, como no tengo una unidad de punto flotante a disposición, utilizo un método muy conocido llamado escalado binario. Cualquier número decimal se puede representar como , dónde , y es una función de redondeo al entero más cercano. El escalado binario es un método que se usa cuando queremos evitar el uso de una división, que es una operación muy costosa en términos de ciclos de CPU necesarios (normalmente 18 ciclos), ya que el desplazamiento binario puede producir los mismos resultados en muchos menos ciclos (normalmente 1 ciclo). Para este ejemplo usé , que es la precisión más alta que podría usar considerando los bits disponibles para hacer una multiplicación (un resultado debe estar dentro de los 32 bits). La ecuación recursiva correspondiente usando aritmética de enteros se implementa de la siguiente manera:
yk0 = ( B0*uk0+B1*uk1+B2*uk2 - A1*yk1-A2*yk2 + (1<<14) ) >> 15;
uk2 = uk1; uk1 = uk0;
yk2 = yk1; yk1 = yk0;
El término (1<<14)
se utiliza para garantizar que el resultado se redondee al entero más cercano después de la operación de cambio de bit. Tenga en cuenta que >>15
es prácticamente una división entera por 32768
, pero sabemos que no es completamente equivalente. El cambio de bit siempre redondea a menos infinito, mientras que la división de enteros siempre redondea a cero. Los valores de los parámetros de filtro son los siguientes: B0=31771
, B1=-63509
m B2=31769
, A1=-63509
, A2=30772
. Esto también se puede encontrar en un código de MATLAB proporcionado.
Me sorprendió mucho cuando me di cuenta de que la variante entera del filtro no funciona en absoluto. Consulte a continuación las respuestas de tres filtros diferentes utilizados para eliminar un 100 Hz
componente de la señal de entrada. De arriba a abajo: (1) filtro de muesca en la implementación de punto flotante, (2) filtro de muesca en la implementación aritmética de enteros usando
, (3) un filtro de promedio móvil simple.
Así es como implementé un filtro de promedio móvil en C:
uk200 = window[ind];
window[ind] = uk0;
win_sum = win_sum - uk200 + uk0;
yk0 = (((win_sum+(1<<3))>>4)*5243+(1<<15))>>16;
ind++;
if (ind==200) ind=0;
Preguntas a la comunidad.
Como no tengo mucha experiencia en filtrado digital, ¿alguien puede confirmarme si se esperan estos resultados? ¿Es realmente problemático implementar un filtro de muesca en un sistema digital usando solo aritmética de enteros ? ¿Qué filtro digital se utiliza normalmente para eliminar una determinada frecuencia ? Como veo en estos resultados, el filtro de media móvil supera a las dos implementaciones de filtro de muesca. ¿Hay alguna desventaja para el filtro de promedio móvil que deba tener en cuenta, excepto por la demanda de memoria obviamente aumentada ?
Hay dos problemas con los filtros digitales, uno es el rango dinámico (capacidad de representar un rango de números), el otro es el ruido de cuantificación del redondeo.
Los filtros de enteros tienen un rango dinámico mucho más reducido que los filtros de punto flotante y también tienen más ruido de cuantificación.
Es necesario comprobar el filtro para asegurarse de que no satura los registros. (El filtro siempre está multiplicando un número grande por una constante grande, el multiplicador se desbordará y esto provocará inestabilidad en el filtro o ruido). Hay formas de superar esto, los coeficientes se pueden ajustar para obtener la misma respuesta pero evitando.
Consulte este recurso para obtener más información.
Una cosa que puede intentar (si es posible con su compilador/hardware) es aumentar el tamaño de las variables de 32 a 64 y ver si eso ayuda.
Otra cosa que querrá verificar (y aún no lo he hecho, necesito averiguar qué forma tiene su filtro antes de poder convertirlo a una forma diferente) es el orden y la forma del filtro. Diferentes formas tienen diferentes resultados. El orden de filtro que tiene es un filtro de segundo orden. El formulario parece una sección de segundo orden de algún tipo, pero no estoy seguro (ahora mismo)
Los filtros digitales pueden tener un orden superior, se puede diseñar un filtro de muesca (o paso alto o paso bajo, lo que sea) filtrar con un filtro de segundo orden o más, a mayor orden más constantes, y multiplica y suma (más recursos computacionales) pero el mejor el filtro es aproximado.
Probablemente sea mejor diseñar el filtro a través de métodos digitales, hay documentos que describen cómo calcular los coeficientes, pero también hay calculadoras en línea y, por supuesto, matlab, pero use la herramienta de diseño de filtros. Asegúrese de que cualquiera que sea el método que utilice, sus constantes calculadas coincidan con la forma (secciones bicuadráticas de segundo orden, forma directa 1, forma directa II, etc.)
usuario_1818839
Dirceu Rodrigues Jr.
Marko Gulin
12b
la resolución, que "aumento" para15b
aumentar la resolución del filtro.Dirceu Rodrigues Jr.
Marko Gulin
Dirceu Rodrigues Jr.
usuario_1818839
Dirceu Rodrigues Jr.