Low Pass Filter Bessel C / C++ Implementation
Some time ago while working on a vehicle crash simulation system we needed to simulate a Bessel low pass filter.
These hardware Bessel filter are used to “smooth out” signals from a acceleration sensor. Some sensors output a pulse-width modulated signal. After letting it pass through a Bessel filter we get a pseudo integral type signal. You can use these filters with any sample rate you like. The cut off frequency is mentioned below as a factor of the actual sample rate you are using. For example, 0.04.
The below code implements a Bessel 4th order low pass filter in C / C++ with double precision. Note that the so-called cut off frequency is the factor 0.04 of the sampling frequency. For example, if sampled at 10kHz, the cut off is 0.04 * 10000 = 400 Hz
// cuts off at 0.04 * sampling freq void BesselLowpassFourthOrder004(const double source[], double dest[], int length) { double xv[4+1] = {0.0}, yv[4+1] = {0.0}; for (int i = 0; i < length; i++) { xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4]; xv[4] = source[i] / double(1.330668083e+03); 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.3041592568 * yv[0]) + ( 1.5960375869 * yv[1]) + ( -3.1910200543 * yv[2]) + ( 2.8871176889 * yv[3]); dest[i] = yv[4]; } }
Below is the same Bessel low pass filter as 3rd order:
// cuts off at 0.04 * sampling freq void BesselLowpassThirdOrder004(const double src[], double dest[], int size) { double xv[3+1] = {0.0}; double yv[3+1] = {0.0}; for (int i=0; i<size; i++) { xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = src[i] / double(2.711023309e+02); yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = (xv[0] + xv[3]) + 3 * (xv[1] + xv[2]) + ( 0.4226750651 * yv[0]) + ( -1.6550518354 * yv[1]) + ( 2.2028676179 * yv[2]); dest[i] = yv[3]; } }
The same cut off frequency again but 2nd order Bessel low pass:
// cuts off at 0.04 * sampling freq void BesselLowpassSecondOrder004(const double src[], double dest[], int size) { double xv[2+1] = {0.0}, yv[2+1] = {0.0}; for (int i = 0; i < size; i++) { xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = src[i] / double(5.050469146e+01); yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = (xv[0] + xv[2]) + 2 * xv[1] + ( -0.5731643146 * yv[0]) + ( 1.4939637515 * yv[1]); dest[i] = yv[2]; } }
And this code simulates a 0.036 cut off frequency (360Hz at 10kHz sample rate), 2nd order Bessel low pass filter:
// cuts off at 0.036 * sampling freq void BesselLowpassSecondOrder0036(const double src[], double dest[], int size) { double xv[2+1] = {0.0}, yv[2+1] = {0.0}; for (int i = 0; i < size; i++) { xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = src[i] / double(6.089464560e+01); yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = (xv[0] + xv[2]) + 2 * xv[1] + ( -0.6062613139 * yv[0]) + ( 1.5405740936 * yv[1]); dest[i] = yv[2]; } }
sir, can you please explain how this code can be used for filtering a data from ADC in PIC microcontroller
do you have floating point arithmetic in the microcontroller?
If not it won’t work without adaptation…