2020-06-18 04:20 AM
Hi all,
My application requires to sample a sensor and send the samples out in real time, without saving the samples.
I am required to run a low pass filter on the samples, but here is the problem cause if I want to do it on 20 samples for example then I will not be able to send out the samples each after I got it as required, and when I send them immediately each after I got it I use an ongoing average on 10 samples but that wasn't enough.
what low pass filter algorithm is the best for this application?
what is the accepted way to do this ?
Best regards
JK
2020-10-06 03:25 AM
Try the Exponential, or First-order filter:
Y[n] = dY[n-1] + (1-d)X[n]
· Y[n] is the current output
· Y[n-1] is the previous output
· X[n] is the current input
· d is the damping factor
The damping factor is a number between 0 and 1. If d = 0, the output is just equal to the input, and no filtering (smoothing) takes place.
The closer d is to 1, the greater the amount of filtering (smoothing).
Here is an example:
The input signal is a Sine function with amplitude +- 100, added to that is random noise of +-10.
To filter out the noise we run the data through the filter equation first with d = 0.5 and then d = 0.8
Code to reproduce the above >>
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "math.h"
#include "stdlib.h"
// ......
/* USER CODE BEGIN PV */
int R;
float d, Xin, Yout, Yprev, X[37], Y[37];
float e, f, g;
// ......
/* USER CODE BEGIN 2 */
// FIRST ORDER DIGITAL FILTER
d = 0.5; // Damping factor (adjust as needed)
srand(123);
R = (rand() % 20) - 10; // random number from -10 to +10
Xin = 100*sin(0) + R; // Input 0 (Sine function with noise)
Yprev = Xin; // Initial value for previous output
X[0] = Xin; // for plotting only
Y[0] = Xin; // for plotting only
for (int n = 1; n < 37; n++) // This will be a "while (1)"- infinite loop in final project
{
R = (rand() % 20) - 10; // random number from -10 to +10
Xin = 100*sin(n*M_PI/18) + R; // Input n (Sine function with noise)
Yout = d*Yprev + (1-d)*Xin; // Output n (Filtered)
Yprev = Yout; // Save previous output
X[n] = Xin; // saving data in arrays just for plotting the ..
Y[n] = Yout; // graph afterwards (not needed in final project)
}
If you need stronger filtering, you can go to a second or even third order digital filter:
Second-order:
Y[n] = eY[n-1] + fY[n-2] + (1-e-f)X[n]
· e = 2*d (where d is the damping factor as before)
· f = -d*d
Third-order:
Y[n] = eY[n-1] + fY[n-2] + gY[n-3] + (1-e-f-g)X[n]
· e = 3*d (where d is the damping factor as before)
· f = -3*d*d
· g = d*d*d
Add the following code, below the previous, to try the second and third order filters.
We just use the data already in the X[n] array as input to generate a new Y[n] output array. >>
// SECOND ORDER DIGITAL FILTER
d = 0.5; // Damping factor (adjust as needed)
e = 2*d;
f = -d*d;
Y[0] = X[0];
Y[1] = X[0];
for (int n = 2; n < 37; n++)
{
Y[n] = e*Y[n-1] + f*Y[n-2] + (1-e-f)*X[n];
}
// THIRD ORDER DIGITAL FILTER
d = 0.5; // Damping factor (adjust as needed)
e = 3*d;
f = -3*d*d;
g = d*d*d;
Y[0] = X[0];
Y[1] = X[0];
Y[2] = X[0];
for (int n = 3; n < 37; n++)
{
Y[n] = e*Y[n-1] + f*Y[n-2] + g*Y[n-3] + (1-e-f-g)*X[n];
}
Here is a real world example:
Noisy pressure sensor – data; filtered with first order and third order filter, both with d=0.8