averaging filter program

I have a arduino "averaging filter" that looks like this:

const int numReadings = 35;

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

const int numReadings_ = 35;

int readings_[numReadings_];      // the readings from the analog input
int index_ = 0;                  // the index of the current reading
int total_ = 0;                  // the running total
int average_ = 0;  

const int numReadingsA = 100;

int readingsA[numReadingsA];      // the readings from the analog input
int indexA = 0;                  // the index of the current reading
int totalA = 0;                  // the running total
int averageA = 0;                // the average

const int numReadings_A = 100;

int readings_A[numReadings_A];      // the readings from the analog input
int index_A = 0;                  // the index of the current reading
int total_A = 0;                  // the running total
int average_A = 0;

//============================================================================================



int filter_x(int num) {
  // subtract the last reading:
  total= total - readings[index];         
  // read from the sensor:  
  readings[index] = num; 
  // add the reading to the total:
  total= total + readings[index];       
  // advance to the next position in the array:  
  index = index + 1;                    

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

  // calculate the average:
  average = total / numReadings; 
 
  return average;
}

int filter_y(int num) {
  // subtract the last reading:
  total_= total_ - readings_[index_];         
  // read from the sensor:  
  readings_[index_] = num; 
  // add the reading to the total:
  total_= total_ + readings_[index_];       
  // advance to the next position in the array:  
  index_ = index_ + 1;                    

  // if we're at the end of the array...
  if (index_ >= numReadings_)              
    // ...wrap around to the beginning: 
    index_ = 0;                           

  // calculate the average:
  average_ = total_ / numReadings_; 
 
  return average_;
}

int filter_xA(int num) {
  // subtract the last reading:
  total= total - readings[index];         
  // read from the sensor:  
  readings[index] = num; 
  // add the reading to the total:
  total= total + readings[index];       
  // advance to the next position in the array:  
  index = index + 1;                    

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

  // calculate the average:
  average = total / numReadings; 
 
  return average;
}

int filter_yA(int num) {
  // subtract the last reading:
  total_= total_ - readings_[index_];         
  // read from the sensor:  
  readings_[index_] = num; 
  // add the reading to the total:
  total_= total_ + readings_[index_];       
  // advance to the next position in the array:  
  index_ = index_ + 1;                    

  // if we're at the end of the array...
  if (index_ >= numReadings_)              
    // ...wrap around to the beginning: 
    index_ = 0;                           

  // calculate the average:
  average_ = total_ / numReadings_; 
 
  return average_;
}

I really don't understand after studying it for 1 entire day, can anybody kindly explain how this works?

Thanks

It works like any average (arithmetic mean);

  1. add up all the samples, and
  2. divide by the number of samples.
    However, because new samples are coming in each cycle, it keeps a circular buffer of samples, puts in the most recent and removes the oldest.
    You only need to add in the new value and subtract the oldest value from a running total, but obviously you have to store all samples to know which is the oldest.

The example isn't (IMHO) very well written - virtually identical code is repeated four times - the addition of a simple structure would reduce the amount of code to about a third of what's there, and make it easier to maintain and debug.

Another thing about this filter - before it has collected its first 'n' samples, it will return a false mean, because the running total won't have 'n' samples-worth of data in it.

This is an example of a digital filter or DSP (Digital Signal Processing) , this can be quite complex and mathematical, a good introduction to the topic is here:-

Try this:-

Yn=Yn-1+(1/kana*(Xn-Yn-1)) // Averaging formula

Very easy to implement. See here:-

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1264723470

Ian.

Just remember the fewer the terms the lower order is the filter. The best filters have a lot of terms in them. Like so many things in life there is a trade off. This time between performance and complexity. Also the more complex a filter the longer it takes to compute and so the lower the frequency you can use it at given a fixed amount of processing power.

Ian,
I don't quite understand your formula, specifically the two "-1" terms.
Yn=Yn-1+(1/kana*(Xn-Yn-1))

By rearranging the terms it becomes:
Y = (1-k)Y + kX - (1+k); // where k = 1/kana

The first part is a formula that I'm familiar with and use quite often. But I don't understand the highlighted portion. It would seem to give you a permanent offset from the true value. I.e. if X were perfectly constant then Y would eventually become equal to X - (1+k).

Yn=Yn-1+(1/kana*(Xn-Yn-1))

I think this is missing some subscripts?

Yn=Yn-1+(1/kana*(Xn-Yn-1))

Just to explain to those who don't know:-

Yn is the nth result you get

Yn-1 is the result you got before the nth result.

Xn is the nth sample you take.

That would make a lot more sense, and would match the formula that I've used a number of times before. It's just that the code shown in the linked post was actually subtracting the "1", which is why that didn't make sense to me.

Quote:

AnaIY0 = AnaIY0 - 1 + (1 / kana * ((float)AI_Raw0 - AnaIY0 - 1));

Correct implementation would be:

Y = Y + (1/kana * (X-Y));

// OR

Y = k * X + (1- k) * Y;  // where k = 1/kana

i got it, thks 4 all the replies :slight_smile:

Y = k * X + (1- k) * Y; // where k = 1/kana

For a reasonably fast approximation, using powers of 2:

Y = (X - (X >> Pow2)) + (Y >> Pow2);

Extra marks awarded for fixed-point representations.