Exponential Moving Average
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;
}