I am reading some noisy data from external sensors and trying to smooth it out. I know very little about discrete filters. When looking at my data in my plotting program (kst), I applied a low-pass filter and it looked great so I tried to implement a similar filter in my own software. In the plotter program, it was described as a "zero phase low-pass filter with a butterworth amplitude response", I set order to 4 and cutoff frequency to 0.005 (as a fraction of the sample rate - my sample rate is 189 Hz so this works out to about 1Hz - my noise is roughly 6Hz).
I searched around the internet for Butterworth filter calculators and found Butterworth / Bessel / Chebyshev Filters. I entered the following parameters:
- Type: Butterworth
- Order: 4
- Sample Rate: 189
- Corner Frequency: 1
It generated the following coefficients and function (C++):
Code:
#define GAIN 1.367579855e+07
float LowPass::next (float value) {
xv[0] = xv[1];
xv[1] = xv[2];
xv[2] = xv[3];
xv[3] = xv[4];
xv[4] = value/GAIN;
yv[0] = yv[1];
yv[1] = yv[2];
yv[2] = yv[3];
yv[3] = yv[4];
yv[4] = (xv[0] + xv[4]) + 4 * (xv[1] + xv[3]) + 6 * xv[2]
+ (-0.9167904003*yv[0]) + (3.7468029782*yv[1])
+ (-5.7431439716*yv[2]) + (3.9131302238*yv[3]);
return yv[4];
}
Where xv and yv are both float[5] arrays initially filled with 0's.The results are not ideal. There is a ringing at approximately 0.91 Hz. Here is what it looks like:
The block in the center is the original data with the filter turned off. The left and right portions are the filtered data. The filtered lines should be relatively flat, but instead there is a ~0.91Hz sine-shaped ringing. The ringing is constant amplitude, it does not seem to depend on the data and it does not diminish over time (at least as far as I can tell). Is something wrong with my filter design/implementation? Is Butterworth not the best type of filter to use here? Why does the plotter's built-in filter (not shown above) work so well when mine doesn't?
Thanks!
J