Smoothing

Smoothing of e.g. sensor readings to be displayed in a graph can be done in several ways. A rolling average, sometimes called a moving average, is one way of doing that. The arduino pages contain a program by David Mellis, modified by Tom Igoe that illustrates this: it stores values in a 10 value array and divides the sum by 10. Whenever the array is full it removes one value and adds a new one.

// Define the number of samples to keep track of. The higher the number, the
// more the readings will be smoothed, but the slower the output will respond to
// the input. Using a constant rather than a normal variable lets us use this
// value to determine the size of the readings array.
const int numReadings = 10;

int readings[numReadings]; // the readings from the analog input
int readIndex = 0; // the index of the current reading
int total = 0; // the running total
int average = 0; // the average

int inputPin = A0;

void setup() {
// initialize serial communication with computer:
Serial.begin(9600);
// initialize all the readings to 0:
for (int thisReading = 0; thisReading < numReadings; thisReading++) {
readings[thisReading] = 0;
}
}

void loop() {
// subtract the last reading:
total = total - readings[readIndex];
// read from the sensor:
readings[readIndex] = analogRead(inputPin);
// add the reading to the total:
total = total + readings[readIndex];
// advance to the next position in the array:
readIndex = readIndex + 1;

// if we're at the end of the array...
if (readIndex >= numReadings) {
// ...wrap around to the beginning:
readIndex = 0;
}

// calculate the average:
average = total / numReadings;
// send it to the computer as ASCII digits
Serial.println(average);
delay(1); // delay in between reads for stability
}

Sadly there is a fundamental flaw in this program:

For the initial 10 readings, the result is simply wrong: when the program starts, the array is empty. A value is read into it, and the sum of the array is then divided by 10. Suppose the analog source is quite stable and always gives a reading of 5. Then the first 10 results of the program will be: 5×9*0=5  ->/10=0.5 (rounded t0 0)
5+5+8*0=10 ->/10=1
5+5+5+7*0=15 ->/10=1.5  (rounded to 1)
etc. etc.
Given the fact that the readings are taken with a 1 microsecond delay, that might not be a huge problem, but in that case there are simpler ways, without the need for an array to smooth the readings. For instance like this:

int ReadSensor(){
  int i;
  int sval = 0;

  for (i = 0; i < 10; i++){
    sval = sval + analogRead(0);
  }

  sval = sval / 10;    // average
 
  return sval;
}

strictly speaking this only gives a moving average during this loop and then 10 completely new values are averaged, but at the 1 microsecond interval of the original program that would virtually be the same.

The results in the original program do become a nuisance when you take readings at say 1 minute intervals and you do not want to wait 10 minutes before you get correct data. Fortunately the program can be simply modified to correct for the mistake: for the first 10 readings we divide by the active indexnumber and only after that we divide by the total number of readings (10). We can simply do that by setting a flag:

 // if we're at the end of the array...
if (readIndex >= numReadings) {
// ...wrap around to the beginning:
readIndex = 0;
flag=1;
}

and then calculate results like so:

// calculate the average:
if (flag==0){
average = total / readIndex;
}else{
average=total/numReadings;
}

Now if you really want to smooth things over you could combine the two techniques presented here: take the average of say 50 readings, store the result in an array and calculate the moving average of the array:

// read from the sensor:
readings[readIndex] = ReadSensor();

and ofcourse add the function “ReadSensor”, given bove, to your program