creating an averaging function correctly

Trying to write my own averaging function, but not sure if I am going about it right. I am getting values from processing and sending them to arduino. Here is what I have so far, but It doesn't seem to be working correctly, the math is easy I just am not sure how I should be storing/collecting values.

import ddf.minim.*;
import processing.serial.*;
Serial comPort;

Minim minim;
AudioInput in;

int lf = 10;

void setup()
{
  int width = 150;
  int height = 500;
  size(width,height, P3D);
  minim = new Minim(this);
  in = minim.getLineIn();
  comPort = new Serial(this, Serial.list()[4], 9600);
}

void draw()
{
  int maxLevel = 650;
  
  int currentLevel = int(in.left.level()*1000);
  int convertToDegrees = int(map(currentLevel, 0, maxLevel, 0, 180));
  smooth();
  background(0);
  stroke(166, 212, 255);
  fill(76, 169, 255);
  rect(0, height, height, -currentLevel);
  
  int avgVal = mean(currentLevel);
  print("current lvl:");
  println(currentLevel);
 
  print("avg lvl:");
  println(avgVal);
  comPort.write(avgVal);
}

int count = 0;
int numberReadings = 2;
int avg;

public int mean(int in){
  count++;
  if(count<numberReadings){
   avg += in;
   avg = avg/count;
  }
  if(count >= numberReadings){
    count = 0;
    avg = in;
  }
  return avg;
}

The code you posted for mean() doesn't compute an average and it isn't even clear what you are actually trying to do. Perhaps if you took a moment to explain just what you would like to calculate, for how many input values, you will get some useful help.

public int mean(int in){
  count++;
  if(count<numberReadings){
   avg += in;
   avg = avg/count;
  }
  if(count >= numberReadings){
    count = 0;
    avg = in;
  }
  return avg;
}

This seems to be trying to average every N samples, starting again for the next N samples. It is not producing a rolling average. Did you intend it to start again every N samples?

In order to calculate an average over a number of samples you need to record the sum and the count. You don't need to record the previous average. Instead of this:

   avg += in;
   avg = avg/count;

You want:

   sum += in;

The result is then sum / count.

If what you want is a rolling average you can do that easily using an exponential decaying average, e.g.:

average = (0.9 * average) + (0.1 * newValue);

PeterH:

public int mean(int in){

count++;
  if(count<numberReadings){
   avg += in;
   avg = avg/count;
  }
  if(count >= numberReadings){
    count = 0;
    avg = in;
  }
  return avg;
}




This seems to be trying to average every N samples, starting again for the next N samples. It is not producing a rolling average. Did you intend it to start again every N samples?

In order to calculate an average over a number of samples you need to record the sum and the count. You don't need to record the previous average. Instead of this:



avg += in;
   avg = avg/count;




You want:


sum += in;




The result is then sum / count.

If what you want is a rolling average you can do that easily using an exponential decaying average, e.g.:



average = (0.9 * average) + (0.1 * newValue);

the equivalent of that rolling avg code using int operations is

sum = sum-avg+newvalue
avg=sum/count; //where count=10.

you can set count to whatever number of sample that makes sense for what you are averaging

I would say that a more obvious implementation using integer variables would be:

average = ((9 * average) + (1 * newValue)) / 10;

PeterH:
I would say that a more obvious implementation using integer variables would be:

average = ((9 * average) + (1 * newValue)) / 10;

Though this will have problems if the values of newValue are ever greater than or equal to the 1/10th the maximum value the int type can hold. On AVR processors, newValue must not be more than 3,266 (max signed int is 32,767). For reading analog values, which range from 0..1023, you are probably safe.

Also, you may want to think about rounding the average before doing the division:

average = ((9 * average) + newValue + 5) / 10;

MichaelMeissner:
the int type

It is always necessary to choose the appropriate data type, and 'integer' doesn't necessarily mean 'int'.

I suppose what you want to do is use a "boxcar" average.

There are two ways to do this

a "real" boxcar

const int count = 4;
int boxcar[count];

int average(int value){
  static int i;
  int sum;
  boxcar[i++] = value;
  i %=count;
  for(int j=0; j>count, j++) sum +=boxcar[j];
  return sum/count;
}//average

or a "fake" boxcar

const int count = 4;
int average(int value){
  static int sum;
  sum += value;
  sum -= (sum/count);
  return sum/count
}//average

from performance point of view

average = ((9 * average) + newValue + 5) / 10;

the divider better be a multiple of 2 (even if average and newvalue are floats)

average = ((7 * average) + newValue + 5) / 8;

another boxcar variation (without loop)

const int count = 4;
int boxcar[count];

int average(int value)
{
  static int i;
  static long sum=0;

  sum -= boxcar[i];  //remove oldest value from sum
  boxcar[i] = value;  // add new value to array
  sum += boxcar[i]; // add new value to sum

  i++;
  if (i == count) i=0;
  return sum/count;
}

Did some related code in the past, might be worth studying.
statistics - Arduino Playground - Statistics -
running average - http://playground.arduino.cc/Main/RunningAverage -
running median - Arduino Playground - RunningMedian -

robtillaart:
from performance point of view

average = ((9 * average) + newValue + 5) / 10;

the divider better be a multiple of 2 (even if average and newvalue are floats)

average = ((7 * average) + newValue + 5) / 8;

another boxcar variation (without loop)

const int count = 4;

int boxcar[count];

int average(int value)
{
  static int i;
  static long sum=0;

sum -= boxcar[i];  //remove oldest value from sum
  boxcar[i] = value;  // add new value to array
  sum += boxcar[i]; // add new value to sum

i++;
  if (i == count) i=0;
  return sum/count;
}




Did some related code in the past, might be worth studying.
statistics - http://playground.arduino.cc/Main/Statistics -
running average - http://playground.arduino.cc/Main/RunningAverage - 
running median - http://playground.arduino.cc/Main/RunningMedian -

those links were exactly what I was looking for. thank you all for the example sketches too.

robtillaart:
from performance point of view

average = ((9 * average) + newValue + 5) / 10;

the divider better be a multiple of 2 (even if average and newvalue are floats)

average = ((7 * average) + newValue + 5) / 8;

indeed better for integer values. However, if the value is a float, I think the method using sum and avg variable is more efficient, as it only involves one addition, one subtraction and one division.

IEEE754 floats store the exponent as a power of 2. So dividing a float with a power of 2 is a subtraction in the native representation. Can be done quite fast.