Averaging and Finding the Median

Here’s how to find the average of 9 samples, or the median number of a sorted list of samples. Arduino/Wiring and PicBasic Pro examples follow.

Thanks to Zach Layton for correcting my bubble sort code and Zach Lieberman for the correction.

Written in Wiring, tested on an Arduino board:

/*
  Analog median and average
 by Tom Igoe

 This program reads an analog input and gives the average of 9 readings,
 and sorts the list of readings and delivers the median number.

 Created 17 October 2005
 Updated 7 August 2007

 */
int numReadings = 9; // number of samples to take
int median = 0;      // median of the sorted samples
int readingNumber;   // counter for the sample array

// variables for subroutines:
byte i = 0;
byte j = 0;
byte position = 0;
int analogValues[9]; 

//function prototypes:
void bubbleSort();
int  averageArray();

void setup() {
  Serial.begin(9600);
}

void loop() {
  for (readingNumber = 0; readingNumber < numReadings; readingNumber++) {
    //get the reading:
    analogValues[readingNumber] = analogRead(0);
    // increment the counter:
    readingNumber++;
  }
  // sort the array using a bubble sort:
  bubbleSort();

  // get the middle element:
  median = analogValues[numReadings / 2]; 

  // print the results:
  // print the array, nicely ASCII-formatted:
  Serial.print("Array: [");
  for (j = 0; j < numReadings; j++) {
    Serial.print(analogValues[j], DEC);
    Serial.print (", ");
  }
  Serial.print("]\r\n");
  // average the array:
  Serial.print(" Average = ");
  Serial.print(averageArray(), DEC);
  Serial.print("\tMedian = ");
  Serial.print(median, DEC);
  Serial.print("\r\n");
}

// average the values in the array:
int  averageArray() {
  int total = 0;
  int average = 0;
  for (i = 0; i< numReadings; i++) {
    total = total + analogValues[i];
  }
  average = total/(numReadings + 1);
  return average;
}

void bubbleSort() {
  int out, in, swapper;
  for(out=0 ; out < numReadings; out++) {  // outer loop
    for(in=out; in<(numReadings-1); in++)  {  // inner loop
      if( analogValues[in] > analogValues[in+1] ) {   // out of order?
        // swap them:
        swapper = analogValues[in];
        analogValues [in] = analogValues[in+1];
        analogValues[in+1] = swapper;
      }
    }
  }
}

Written in PicBasic Pro, tested on a PIC 18F252:

'  Analog median and average
' by Tom Igoe

' This program reads an analog input and gives the average of 9 readings,
' and sorts the list of readings and delivers the median number.

' Created 17 October 2005
' Updated 

  ' Define ADCIN parameters
DEFINE  ADC_BITS        10     ' Set number of bits in result
DEFINE  ADC_CLOCK       3     	' Set clock source (3=rc)
DEFINE  ADC_SAMPLEUS    50    	' Set sampling time in uS

TRISA = %11111111       ' Set PORTA to all input
ADCON1 = %10000010      ' Set PORTA analog and right justify result

numReadings con 9 ' number of samples to take
median var byte   ' median of the sorted samples
readingNumber var byte     ' counter for the sample array
' serial variables and constants:
tx var portc.6
rx var portc.7
inv9600 con 16468

'  variables for subroutines:
 i var byte
 j var byte
 position var byte
 analogValues var word[numReadings]
 total var word
 average var word
 out var byte
 in var byte
 swapper var word

main:
  for readingNumber = 0 to (numReadings - 1)
    ' get the reading:
    adcin 0,analogValues[readingNumber]
    '  increment the counter:
    readingNumber = readingNumber + 1
  next
  '  sort the array using a bubble sort:
  gosub bubbleSort

  '  get the middle element:
  median = analogValues[numReadings / 2] 

  '  print the results:
  '  print the array, nicely ASCII-formatted:
  serout2 tx, inv9600,["Array: ["]
  for j = 0 to (numReadings - 1)
    serout2 tx, inv9600, [DEC analogValues[j], ", "]
  next
  serout2 tx, inv9600,["]", 10, 13]
  '  average the array:
  gosub averageArray
  serout2 tx, inv9600, ["Average: ", DEC average, 10, 13]
  serout2 tx, inv9600, ["Median: ", DEC median, 10, 13]
GOTO MAIN

'  average the values in the array:
averageArray:
   total = 0
   average = 0
  for i = 0 to (numReadings - 1)
    total = total + analogValues[i]
  next
  average = total/numReadings
RETURN

bubbleSort:
  for out = 0  to (numReadings - 2)  '  outer loop
    for in = out+1 to (numReadings - 1)    '  inner loop
        if analogValues[out] > analogValues[in] then  'out of order?
            swapper = analogValues[out]
            analogValues [out] = analogValues[in]
            analogValues[in] = swapper
        endif
    next
  next
return