EmbeddedRelated.com
Memfault Beyond the Launch

Exponential Moving Average

February 13, 20133 comments Coded in C

The exponential moving average is a type of IIR filter that is easy to implement in C and uses minimal resources.  Unlike a simple moving average, it does not require a RAM buffer to store previous samples.  It just has to store one value (the previous average).  

An exponential moving average is expressed as the following equation:  avg[n] = (in * alpha) + avg[n-1]*(1-alpha).  Implementing this equation using floating point math is straightforward but using fixed point variables is a little tricky.  The code snippet here use 32-bit signed integers for the average and input values.  Intermediate values need to use 64-bit math to avoid overflow errors.

Alpha values close to zero represent heavy averaging while an alpha value of one has no averaging.

//This macros defines an alpha value between 0 and 1
#define DSP_EMA_I32_ALPHA(x) ( (uint16_t)(x * 65535) )
 
int32_t dsp_ema_i32(int32_t in, int32_t average, uint16_t alpha){
  int64_t tmp0; //calcs must be done in 64-bit math to avoid overflow
  tmp0 = (int64_t)in * (alpha) + (int64_t)average * (65536 - alpha);
  return (int32_t)((tmp0 + 32768) / 65536); //scale back to 32-bit (with rounding)
}

//here is a function that uses the averaging code
int32_t my_avg_func(void){
     static int32_t average = 0;
     int32_t adc_value;    
     adc_value = read_the_adc_value();
     average = dsp_ema_i32(adc_value, average, DSP_EMA_I32_ALPHA(0.1));
     return average;
}

Memfault Beyond the Launch