cancel
Showing results for 
Search instead for 
Did you mean: 

Low pass filter on ongoing samples.

JKhal
Associate III

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

1 REPLY 1
JElli.1
Associate II

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

0693W000004Jo9CQAS.jpg 

 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

0693W000004Jk2cQAC.jpg