Library: AverageList - averaging made easy

I’ve just made a new template library called AverageList.

It will help averaging a set of values of the same datatype.

Download AverageList

API:

  • addValue(datatype value)

  • //add a value to the AverageList

  • getAverage() : datatype

  • //return the average of all values that are added with an addValue call

  • getTotalAverage() : datatype

  • //return the average of all values in the AverageList

  • getMin() : datatype

  • //return the low peak of the values in the set

  • getMax() : datatype

  • //return the high peak of the values in the set

  • reset()

  • //reset the AverageList, discard old values

  • operator=

  • //reset and assign

  • operator+=

  • //add value to AverageList

  • operator-=

  • //remove value from AverageList if present

  • operator

  • //subscript operator, read and/or assign

Short Example:
This example will take 20 readings from analog pin 2 and calculate the average, then send it to the serial console.

#include <AverageList.h>

const byte LIST_SIZE = 20;

void setup(){

//enable user feedback
Serial.begin(9600);

//this is used for storage, an array of ints
int arr[LIST_SIZE] = {0};

//initialize an AverageList object that operates on ints
AverageList testList(arr,LIST_SIZE);

//take samples
for(int i=0; i<LIST_SIZE; i++){
testList = analogRead(2);

  • delay(20);*

  • }*

  • Serial.println( testList.getTotalAverage());*
    }
    void loop(){/nothing to loop/}
    [/quote]
    Example Sketch:
    A more thorough investigation of the API and operator overloading.
    ```
    *#include <AverageList.h> //http://www.arduino.cc/playground/uploads/Code/AverageList.zip

const byte LIST_SIZE = 5;

void setup(){
 
 //enable user feedback
 Serial.begin(9600);
 
 //this is used for storage, an array of ints
 int arr[LIST_SIZE] = {0};  
 
 //initialize an AverageList object that operates on ints
 AverageList testList(arr,LIST_SIZE);
 
 //perform operations on the AverageList
 testList.addValue(2);  //add 2 to the AverageList
 testList.addValue(4);  //add 4 to the AverageList
 testList.addValue(6);  //add 6 to the AverageList
 
 //average should be (2+4+6)/3 = 4
 Serial.print("Avarage of the values inserted into testList: ");
 Serial.println( testList.getAverage() );
 
 //perform operations on the AverageList
 testList.reset();      //reset AverageList to 0
 testList+=1;        //add 1 to the AverageList
 testList+=3;            //add 3 to the AverageList
 
 //average should be (1+3)/2 = 2
 Serial.print("Avarage of the values inserted into testList: ");
 Serial.println( testList.getAverage() );
 
 //perform operations on the AverageList
 testList=1;              //reset AverageList to 1
 testList+=3;            //add 3 to the AverageList
 testList+=5;            //add 5 to the AverageList
 testList-=4;            //try to remove 4 from the AverageList, but no item in the list is equal to 4, therefore take no action
 testList+=12;            //add 12 to the AverageList
 
 //average should be (1+3+5+12)/4 = 5,25 = (int) 5
 Serial.print("Avarage of the values inserted into testList: ");
 Serial.println( testList.getAverage() );
 
 //total average should be (1+3+5+12+0)/5 = 4,2 = (int) 4
 Serial.print("Avarage of testList: “);
 Serial.println( testList.getTotalAverage() );
 
 //perform operations on the AverageList
 testList[4] = 12;
 
 //total average should be (1+3+5+12+12)/5 = 6,6 = (int) 6
 Serial.print(“Avarage of testList after ‘testList[4] = 12;’: “);
 Serial.println( testList.getTotalAverage() );
 
 Serial.print(”\nThe AverageList testList contains:\n\t”);
 for(int i=0; i<LIST_SIZE; i++){
   Serial.print( testList[i] , DEC );
   Serial.print(”, ");
 }
}

void loop(){/nothing to loop/}*

* *Example Sketch Serial Output:* *
*Avarage of the values inserted into testList: 4
Avarage of the values inserted into testList: 2
Avarage of the values inserted into testList: 5
Avarage of testList:  4
Avarage of testList after ‘testList[4] = 12;’:  6

The AverageList testList contains:
      1, 3, 5, 12, 12*

```
Feedback Welcome!

Excellent! I like it!

Does it perform a "windowed average"? In other words, what happens if a value is added when the list is full?

Any thoughts about adding time-weighted averages (typically used to estimate flow)?

  • Brian

As is now a call to addValue() when the list is full will do nothing. One need to call clear() first.

But, if one uses [] operators one can change whichever value one wants.


'time-weighted averages' sounds interesting. But also more resource demanding, and to be honest I do not know exactly how the inner mechanics would be.

Typically one would log a value at a specific time (logging both the value and the time) and later one could get an avarage that takes the time into account? If yes, how exactly? Or is it more like a avarage from t1 to t2?

[edit]I managed to use the word 'one' six times! Oh-well. English is not my primary language :-[[/edit]

Not part of a average series, but it might be useful to add functions for 'peak high' and 'peak low' value detection for the values in the set?

Lefty

PS: The above green comments with a grey backround has to be the worst color selections I have ever tried to read ;)

Not part of a average series, but it might be useful to add functions for 'peak high' and 'peak low' value detection for the values in the set?

Done :) [edit]The functions are named getMax and getMin respectively.[/edit]

PS: The above green comments with a grey backround has to be the worst color selections I have ever tried to read ;)

I agree. Tried to emulate the Arduino IDE coloring, but without luck. [edit]Fixed.[/edit]

'time-weighted averages' sounds interesting ... Typically one would log a value at a specific time ...

I'm certainly willing to answer your questions but first...

Have you read of anyone needing such a thing? If the answer is no, your time is better spent on something else. It popped into my mind that the only place I've seen time-weighted averages used is estimating smoke-stack pollution; hardly the realm of Arduino!

As is now a call to addValue() when the list is full will do nothing

I've seen "windowed averaging" used often on analog inputs to be generally useful.

  • Brian

Thanks very much. This is a very useful class for handling analog inputs as averaging acts somewhat like a low pass filter and will increase the apparent accuracy on noisy signals.

Lefty

AlphaBeta,

I tried to make averageList to work, however, I couldn´t.

In fact, I couldn´t understand your example and why you use your routine in void setup instead than in the program (void loop).

For instance, in my little test sketch that follows, I want to read several values of an analog variable.

In this example, I generate random numbers as I cannot attach my board to my car at this point.

The sketch includes function LcdPrintFloat developed by mem, at the end. This is for printing decimals.

In my case, I read real positive integer numbers.

Would you please insert the lines that would replace my mean calculations in my sketch?

Tks a lot in advance.

// ============ Test Rutina para calcular media de n obs ========
//
// This routine computes mean of 10 obs of variable of interest.
// Includes function lcd
#include <LiquidCrystal.h>

//create object to control an LCD.
LiquidCrystal lcd(12, 11, 6, 7, 8, 9, 10);

int valx; // valores random
int y; // suma de valores
int nrox; // cuenta obs
float x; // variable auxiliar

void setup() {
pinMode(13, OUTPUT); //LED for debugging
y = 0; // inicializa sumas
nrox = 0;
}

void loop() {
digitalWrite(13, LOW); //light the debug LED

// ============ generates random numbers for testing ======
valx = random(1,100);
y = y + valx; // suma valores a promediar
delay (100);

// ======= cuenta ciclos =======
nrox = nrox +1; // lleva cuenta del nro de obs

// ======= prints values =======

lcd.setCursor(0,0);
lcd.print (“x=”); lcd.print(valx); lcd.print(" “); lcd.setCursor(5,0);
lcd.print (“y=”); lcd.print (y); lcd.print (” “); lcd.setCursor(11,0);
lcd.print (“obs=”); lcd.print (nrox); lcd.print (” ");

// ==== resetea sumas cuando nobs = 10 ================

if(nrox==10){
lcd.setCursor(0,1);
lcd.print(“Mean=”);
x = y/nrox; lcdPrintFloat (x,1);

// ==== blinks led =============
digitalWrite(13, HIGH); delay (100);

y=0 ; // inits
nrox=0;
}
}

/* -------------- Function LcdPrintFloat ---------------- */
void lcdPrintFloat( float x, byte precision){
// prints val on a ver 0012 text lcd with number of decimal places determine by precision
// precision is a number from 0 to 6 indicating the desired decimal places

if(x < 0.0){
lcd.print(’-’);
x = -x;
}

lcd.print ((long)x); //prints the integer part
if( precision > 0) {
lcd.print("."); //prints decimal point
unsigned long frac;
unsigned long mult = 1;
byte padding = precision -1;
while(precision–)
mult *=10; //“amplifies” decimal values

if(x >= 0)
frac = (x - int(x)) * mult;
else
frac = (int(x)- x) * mult;
unsigned long frac1 = frac;
while( frac1 /= 10 )
padding–;
while( padding–)
lcd.print(“0”);
lcd.print(frac,DEC) ;
}
}