Close

2nd attempt of a 2nd-order Butterworth High-Pass

A project log for PIC32MX music box with FM synthesis and I2S DAC

Six-channel FM synthesis music box using PIC32MX250F128B microcontroller with envelope generator.

nyh-workshopNYH-workshop 01/27/2018 at 12:260 Comments

My goodness! That's a long week and I had almost forgotten about this thing!

Anyway, back to some experimentation - since this microcontroller doesn't have an FPU, I might as well as use fixed-point implementation. Using Bruce Land's simple fix16 implementation, and the other mindless experimentation on Matlab/Octave and online C compiler, I got this filter finally working.

The filter information is as follows:

//Fixed point coefficients for 20hz cutoff 2nd order high pass Butterworth filter:
fix16 coeff_b_fp[N+1] = { float2fix16(0.9973), float2fix16(-1.9945), float2fix16(0.9972) };
fix16 coeff_a_fp[N+1] = { float2fix16(1.0000), float2fix16(-1.9944), float2fix16(0.9945) };
inline void butterworth(short* inputData, fix16* outputData_fix16) {
    unsigned short i = 0;
    unsigned short j = 0;
    unsigned short k = 0;
    
    for (i = N ; i < (BUFFER_LENGTH/2) + N; i++) {

        // First order:
        //outputData_fix16[i] = multfix16(-1 * coeff_a_fp[1], outputData_fix16[i - 1]) + multfix16(coeff_b_fp[0], short2fix16(inputData[i])) + multfix16(coeff_b_fp[0], short2fix16(inputData[i]));
        
        // Second order:
        // Direct Form I algorithm:
        outputData_fix16[i]  = -1*multfix16(coeff_a_fp[1], outputData_fix16[i-1]) - multfix16(coeff_a_fp[2], outputData_fix16[i-2]) + multfix16(coeff_b_fp[0], short2fix16(inputData[i])) + multfix16(coeff_b_fp[1], short2fix16(inputData[i-1])) + multfix16(coeff_b_fp[2], short2fix16(inputData[i-2])); 
                                  
    }

    for (i = BUFFER_LENGTH/2, j = 0; i < (BUFFER_LENGTH/2 + N); i++, j++) {
        outputData_fix16[j] = outputData_fix16[i];
        inputData[j] = inputData[i];        
    }

};

And one thing is, please pay attention to the numbers at the right of the decimal point! I got the filter to behave erratically because I made a mistake rounding the numbers in the coefficients!

Here is a 20hz signal (captured using Analog Discovery 2) being passed into the filter with the mistake in the coefficients (the b part):

fix16 coeff_b_fp[N+1] = { float2fix16(0.9973), float2fix16(-1.9945), float2fix16(0.9972) };

The most obvious thing is, it never did the job, but made the signal more amplified.

Then, checking back at Matlab, the coefficients are:

0.9972   -1.9945    0.9972

 Trying 0.9972 inside, it gives me this instead:

Putting 0.9973 inside, now the whole signal got attenuated. That is very strange.  Is it some precision or rounding error that I don't know here??

I have to make do with that coefficient, and this begs an explaination why I can't directly use the coefficients from Matlab, but I have to fine tune the numbers inside??

Anyway, I hope I can fix the remaining poor output volume and that nasty click noise between music notes.

Discussions