Smoothing of analog measurements using a simple moving average

Zápisník experimentátora

I wrote this code while writing the NeoPixel Ring clock lesson. It's a fast implementation of simple moving average that is good to smoothing measurements that oscillate slightly around one value. The principle of simple moving average is simple. You record the X values backwards and the result is a sum of X values. You can study the simple moving average on the Wikipedia page.

The floating average is explained by the code used by the photoresistor and the analogue pin on Arduino to measure the intensity of the light. For measuring the intensity through a photoresistor you can read the details in a separate article. Here we will deal only with the process of smoothing itself.

We will use the connection from the picture on the right. Vcc is connected to the photoresist, which gives us results in the form of:

  • Low values for low light.
  • Big values for strong lighting.

Interesting is a simple moving average code for us. I wrote it in the form of a template where you set the data type and number of records in buffer.

///
/// Moving average
///
/// Simple moving average with fast calculation.
/// typ - any type (int, float, ...)
/// sz - size of buffer
///
template<typename typ, int sz> class MovingAverage
{
  typ data[sz]; // buffer
  int pos;      // actual position in buffer
  typ sum;      // precalculated sum
  
public:
  MovingAverage()
  : pos(0), sum(0)
    {
    memset(data,0,sizeof(data));
    }
    
  void Push(typ value)
    {
    sum-=data[pos];  
    sum+=value;
    data[pos]=value;
    pos++;
    if(pos==sz)
      pos=0;
    }
    
  typ MA()
    {
    return sum/sz;
    }
};

MovingAverage<uint16_t,16> ma;

And the use in the code is as follows. We measure the analog values, send them to the buffer, and for further calculations we already use the calculated simple moving average value.

void loop() {
uint16_t sv = analogRead(A0);
ma.Push(sv);
uint16_t sva = ma.MA();
int svc=constrain(sva,100,900);
int m=map(svc,100,900,0,255);
Serial.print(sv);
Serial.print(", ");
Serial.print(sva);
Serial.print(", ");
Serial.print(svc);
Serial.print(", ");
Serial.print(m);
Serial.println("");
delay(1000);
}

This is an elementary implementation of simple moving averages, but will meet all usual requirements. You can also try other implementations from the Arduino server.



Download

15.06.2018


Menu