2
\$\begingroup\$

I'm trying to implement a 10th-order Butterworth Low Pass digital filter on my MCU.

To find the coefficients I used Matlab's Filter Design & Analisys Tool. So I create two little scripts: in the first of them I used the Filter Object created by the tool and it seems to works perfectly, but in the second one I tryed to implement the general code based to the Biquad Direct-Form-II using only the coefficients generated by the tool and, in this case, the filter works good except for a signal amplification of about 5E+7!

My code in matlab is the following:

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

Consider that in the coeff_lp array there are a1,a2,b1,b2,.... since a0=b0=1 for every biquad section.

Why in this case the filtered signal is amplified by a 5E+7 factor? Where I'm wrong?

\$\endgroup\$
2
  • \$\begingroup\$ wrong polarity of terms? not sure,... so you ended up with positive feedback gain \$\endgroup\$ May 24, 2017 at 15:26
  • \$\begingroup\$ @TonyStewart.EEsince'75 The polatity is ok. Thanks for your interest, but I found the mistake. Now I answer to myself. \$\endgroup\$
    – thoraz
    May 24, 2017 at 16:16

1 Answer 1

5
\$\begingroup\$

I found the mistake in my code:

when the Matlab's Filter Design & Analisys Tool generates the cofficients, there are even the Gains for the every biquad section. Before the value goes out from one section, it must be multiplied with this gain.

So the right code is the following:

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

Then the C-Code for my MCU is (maybe is usefull for someone):

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;
}

and now it works very well.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ You were the best person to be answering your question, as you are current with the tools you are applying. I love it when the author does discover the problem and posts the solution. Makes total sense given the added context. Thanks! \$\endgroup\$
    – jonk
    May 24, 2017 at 17:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.