Digital noise filtering by use of Expotential Moving Average (EMA)

Expotential Averaging is actually a standard 1-pins IIR filter.

Its quite easy to use because there is only one parameter - in this page named alpha - to adjust.

Starting with the algorithm

 

Its also known as a low-pass single pole IIR filter or a first order IIR filter (similar to an analog RC filter)

Letting alpha …

  • increasing towards 1 leads to y[n] ~= x[n] so filtering effect do decrease

    • alpha = 1 - no filtering

    • alpha -> 0 - filter gets more aggresive

    • alpha = 0 - what does the formual tells you ?

  • If the factor (1-alfa) on the y[n-1] is greater than or equal to 1 the filter is unstable.


A document describing EMA in more detail: link - a local copy

  • In the SMA we should select how many old sample values had to be used in the filter. Increasing number of samples did give a slower step response.

  • In EMA we have to choose the weight factor - alpha. Larger alpha equals increasing cutoff frequency


Higher order digital filters - a comment

Higher order digital filters is rather complicated.

Another way to do it is by setting requirements to your freqyency response

Here is a link to very pro homepage for designing digital filters: http://t-filter.engineerjs.com/

You can design rather complex filters but here we will stick to a low pass filter Here can shall


  • Select sampling frequency - Herz ( 2000 Hz)

  • Low pass part

    • Gain in pass band in apmlification (not in dB) select 1 = 0 dB

    • max deviation of gain in passband(ripple) in dB select 4 dB ( +-2 dB)

    • Frequency range - like 0 Hz to xxx Hz 0 to 400 Hz

  • High stop part

    • Gain in stop band - normally 0

    • Minimum damping rel to pass band in stop band -40 dB

      • increased damping will increase size of filter

  • Desired # taps in the filter

    • either let tool select it (selected)

    • or select by your self

    • (Manually seleted) fewer tabs might make your desired filter impossible

Result:

 
 
#ifndef SAMPLEFILTER_H_
#define SAMPLEFILTER_H_

/*
h file interface
FIR filter designed with
 http://t-filter.appspot.com

sampling frequency: 2000 Hz

* 0 Hz - 400 Hz
  gain = 1
  desired ripple = 4 dB
  actual ripple = 2.527326551960596 dB

* 500 Hz - 1000 Hz
  gain = 0
  desired attenuation = -40 dB
  actual attenuation = -42.12980699449226 dB

*/

#define SAMPLEFILTER_TAP_NUM 25

typedef struct {
  double history[SAMPLEFILTER_TAP_NUM];
  unsigned int last_index;
} SampleFilter;

void SampleFilter_init(SampleFilter* f);
void SampleFilter_put(SampleFilter* f, double input);
double SampleFilter_get(SampleFilter* f);

#endif

//

#include "SampleFilter.h"

static double filter_taps[SAMPLEFILTER_TAP_NUM] = {
  0.01750204006655566,
  0.04104493059368818,
  0.034156830746668504,
  -0.0049733241015522045,
  -0.03612243937234474,
  -0.006716324848775206,
  0.044618218414176056,
  0.032288748464243164,
  -0.05514177396520813,
  -0.08478411312672213,
  0.06134889205109059,
  0.3112128706221355,
  0.4355976849007708,
  0.3112128706221355,
  0.06134889205109059,
  -0.08478411312672213,
  -0.05514177396520813,
  0.032288748464243164,
  0.044618218414176056,
  -0.006716324848775206,
  -0.03612243937234474,
  -0.0049733241015522045,
  0.034156830746668504,
  0.04104493059368818,
  0.01750204006655566
};

void SampleFilter_init(SampleFilter* f) {
  int i;
  for(i = 0; i < SAMPLEFILTER_TAP_NUM; ++i)
    f->history[i] = 0;
  f->last_index = 0;
}

void SampleFilter_put(SampleFilter* f, double input) {
  f->history[f->last_index++] = input;
  if(f->last_index == SAMPLEFILTER_TAP_NUM)
    f->last_index = 0;
}

double SampleFilter_get(SampleFilter* f) {
  double acc = 0;
  int index = f->last_index, i;
  for(i = 0; i < SAMPLEFILTER_TAP_NUM; ++i) {
    index = index != 0 ? index-1 : SAMPLEFILTER_TAP_NUM-1;
    acc += f->history[index] * filter_taps[i];
  };
  return acc;
}

NOTE: the code is open for optimization and there are many float operations. But an impressive tool


Links - just garbage can

For the interested people some links