¿Por qué mi filtro digital de paso bajo se amplifica en la banda de paso?

2

Estoy intentando implementar un filtro digital de paso bajo Butterworth de décimo orden en mi MCU.

Para encontrar los coeficientes utilicé Filter Design & de Matlab; Herramienta de análisis. Así que creo dos pequeños scripts: en el primero de ellos usé el Objeto de Filtro creado por la herramienta y parece que funciona perfectamente, pero en el segundo intenté implementar el código general basado en el Biquad Direct-Form-II usando solo los coeficientes generados por la herramienta y, en este caso, el filtro funciona bien, excepto por una amplificación de señal de aproximadamente 5E + 7!

Mi código en matlab es el siguiente:

input = AmplitudeF8.';

delayline_lp = [0,0,0,0,0,0,0,0,0,0];
coeff_lp = [-1.7582972612745587, 0.89109671836321969, 2, 1, -1.5932765493727838, 0.71361243648860972, 2, 1, -1.4754804435926461, 0.58691950806119031, 2, 1, -1.4002643388507841, 0.50602253348347193, 2, 1, -1.3637162169443289, 0.46671403035270148, 2, 1];

for k=1:length(output1)    
    y = output1(k);

    for j=1:5 %the biquad sections (order 10 = num_sections = 5)
        w = y;
        for i=1:2
            w = w - (coeff_lp(((j - 1) * 4) + i) * delayline_lp(((j - 1) * 2) + i));
        end

        y = w;
        for i=1:2
            y = y + (coeff_lp(((j - 1) * 4) + i + 2) * delayline_lp(((j - 1) * 2) + i));
        end

        delayline_lp(j * 2) = delayline_lp((j * 2) - 1);        
        delayline_lp((j * 2) - 1) = w;
    end

    output2(k) = y;
end

Considera que en la matriz coeff_lp hay a1, a2, b1, b2, .... ya que a0 = b0 = 1 para cada sección de biquad.

¿Por qué en este caso la señal filtrada se amplifica por un factor 5E + 7? Donde estoy equivocado?

    
pregunta thoraz

1 respuesta

5

Encontré el error en mi código:

cuando el diseño del filtro de Matlab & La herramienta de análisis genera los cofficientes, incluso hay las ganancias para cada sección de biquad. Antes de que el valor salga de una sección, debe multiplicarse con esta ganancia.

Por lo tanto, el código correcto es el siguiente:

input = AmplitudeF8.';

delayline_lp = [0,0,0,0,0,0,0,0,0,0];
scale_values = [0.033199864272165251, 0.030083971778956442, 0.027859766117136031, 0.026439548658171989, 0.025749453352093145];
coeff_lp = [-1.7582972612745587, 0.89109671836321969, 2, 1, -1.5932765493727838, 0.71361243648860972, 2, 1, -1.4754804435926461, 0.58691950806119031, 2, 1, -1.4002643388507841, 0.50602253348347193, 2, 1, -1.3637162169443289, 0.46671403035270148, 2, 1];

for k=1:length(input)    
    y = input(k);

    for j=1:5 %the biquad sections
        w = y;
        for i=1:2
            w = w - (coeff_lp(((j - 1) * 4) + i) * delayline_lp(((j - 1) * 2) + i));
        end

        y = w;
        for i=1:2
            y = y + (coeff_lp(((j - 1) * 4) + i + 2) * delayline_lp(((j - 1) * 2) + i));
        end

        y = y * scale_values(j);

        delayline_lp(j * 2) = delayline_lp((j * 2) - 1);        
        delayline_lp((j * 2) - 1) = w;
    end

    output2(k) = y;
end

Luego, el C-Code para mi MCU es (quizás sea útil para alguien):

double Filter_IIR_Biquad_Sec( double signal, double *coeffs, double *scaleValues, double *delayLine, uint32_t nSections )
{
    uint32_t i, j;
    double y = signal;
    double w = 0.0;

    for ( j = 0; j < nSections; j++ )
    {
        // The denominator
        w = y;
        for ( i = 0; i < 2; i++ )
            w -= coeffs[ ( j << 2 ) + i ] * delayLine[ ( j << 1 ) + i ];

        // The numerator
        y = w;
        for ( i = 0; i < 2; i++ )
            y += coeffs[ ( j << 2 ) + i + 2 ] * delayLine[ ( j << 1 ) + i ];

        y *= scaleValues[ j ];

        // Shift the register values
        delayLine[ ( j << 1 ) + 1 ] = delayLine[ j << 1 ];
        delayLine[ j << 1 ] = w;
    }

    return y;
}

y ahora funciona muy bien.

    
respondido por el thoraz

Lea otras preguntas en las etiquetas