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:
- 2nd order
- Direct form I algorithm
- Coefficients:
//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
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.