Smoothing analog sensor inputs - double arrays?

Hello there,

I probably should be able to figure this out, but I just can't get my head around it.

I'm reading from 4 temperature sensors, using the smoothing code on the arduino site to get ten readings from each sensor, and take an average. At the moment, I'm writing this out 'long-hand' by doing this for each sensor.

Can anyone tell me a way of putting each average reading from each sensor (after smoothing) in to another array to get the average of all these.

So, for example ten readings from each sensor, take an average, put each average from each sensor and take an average from this.

This is the smoothing code:

#define NUMREADINGS 10

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

int inputPin = 0;

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

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

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

  average = total / NUMREADINGS;          // calculate the average
  Serial.println(average);                // send it to the computer (as ASCII digits)
}

Any help would be greatly appreciated :slight_smile:

Thanks,
Emma

A few thoughts :slight_smile:

Ints can not hold decimals, and are not suited to represent avarage measurements, float or doubles are.

index = (index + 1);

Could be done by

index++; //or readings[index++];

As for how to avarage:

//UNTESTED
#define VARIABLES_LENGTH 10
byte variables[VARIABLES_LENGTH] ={1,2,3,4,5,6,7,8,9};

float avarage(byte a[]){
float avarage = a[0];
for(byte i=1; i<VARIABLES_LENGTH; i++){
avarage += a*;*

  • }*
  • avarage /= VARIABLES_LENGTH;*
  • return avarage;*
    }
    void setup() { Serial.begin(9600); Serial.println( avarage(variables) ); }
    void loop() { ; }
    [/quote]

I think this should work as you described. I've always found nested arrays the easiest way to handle data sets like this. I don't have any hardware to test this. Obviously your readings will be bogus until the data arrays are filled with good data.

Another thing to be noted as well. This will print out the average of the analogRead function. This will need to be scaled with your hardware slope, via a multiplier of totalAverage.

#define NUMSENSORS 4
#define NUMREADINGS 10

int readings[NUMSENSORS][NUMREADINGS];      // the readings from the analog input
int index = 0;                            // the index of the current reading
float total = 0;                            // the running total
float average[NUMSENSORS];                      // the average
float totalAverage;
int i,j;

int inputPin[NUMSENSORS] = {0,1,2,3};

void setup()
{
  Serial.begin(9600);          // initialize serial communication with computer
  for(i=0;i<NUMSENSORS;i++)
  {
    for(j=0;j<NUMREADINGS; j++)
    {
     readings[i][j]= 0;     // Clear the data
    }
  }
}

void loop()
{
  for(i=0; i<NUMSENSORS; i++)        // This handles the data for each sensor
  {
    for(j=0; j<NUMREADINGS - 1; j++)
    {
      readings[i][j+1] = readings[i][j]; // Shift to make room for the new reading
    }
    readings[i][0] = analogRead(inputPin[i]); // get the latest value
  }
  
   for(i=0; i<NUMSENSORS; i++)    // Average each sensor
   {
     total = 0;                    // Reset the total for each sensor
     for(j=0; j<NUMREADINGS; j++)
       total += readings[i][j];
     average[i] = total / NUMREADINGS;
   
   }
 
  total = 0;                    // Reset total again for use with totalAverage
 
  for(i=0; i<NUMSENSORS; i++)  // Average all sensors together
  {
    total += average[i];
  }
  
  totalAverage = total / NUMSENSORS;
  Serial.println(totalAverage);       // send it to the computer (as ASCII digits)
}

Nice one.

Thank you both. So, it's nested arrays, rather than two dimensional arrays? This is what I was trying to find, I think.

Thank you so much :slight_smile:

So, it's nested arrays, rather than two dimensional arrays? This is what I was trying to find, I think.

Is the average of the individual sensors of any interest? If not, you can just take the average of all readings.

Also, to avoid bogus results until the array is filled with actuals, you can fill it with the result of one initial reading. Then you'll get sensible data from the first reading.

Something like this (NB! Untested code.):

#define SENSORS 4
#define READINGS_PER_SENSOR 10
#define READINGS READINGS_PER_SENSOR * SENSORS

#define SENSOR_1 0
#define SENSOR_2 1
#define SENSOR_3 2
#define SENSOR_4 3

int readings[READINGS];

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

  // Fill the array with an initial actual reading
  for (int i = 0; i < READINGS; i++)
    readings[i] = analogRead(SENSOR_1);
}

void loop(void)
{
  // Read from each sensor
  sensor_read(SENSOR_1);
  sensor_read(SENSOR_2);
  sensor_read(SENSOR_3);
  sensor_read(SENSOR_4);
  
  // Print average to serial port
  Serial.println(average_reading());
  
  // Do other stuff if you need to
  delay(1000);
}

// Insert a reading
void sensor_read(int sensor)
{
  // Shift out the last reading
  for (int i = 1; i < READINGS; i++)
    readings[i] = readings[i-1];
    
  // Insert the new reading
  readings[0] = analogRead(sensor);
}

// Find average of all readings
float average_reading(void)
{
  long sum = 0;
  for (int i = 0; i < READINGS; i++)
    sum += readings[i];
    
  return sum/READINGS;
}

So, it's nested arrays, rather than two dimensional arrays? This is what I was trying to find, I think.

Unless I'm mistaken, nested and multidimensional arrays are the same thing.

Also, I think it is worth noting the amount of time it takes to fill your arrays with 10 readings is very small. I ran my serial monitor and I couldn't even read the first 10 outputs. If you were to run a delay this might be a concern.

Also skumlerud, your initial setup will fill the array with readings from sensor 1 only. So i would argue that that data is bogus as well becuause you are not getting a true average of all 4 sensors until you have called your sensor read 10 times for all 4 sensors.

Unless I'm mistaken, nested and multidimensional arrays are the same thing.

They are in C, yes. But in other languages, an array can have two, three or more dimensions. E.g. in BASIC:

10 DIM A(3,3)

makes a 3x3 (two-dimensional) array.

And yes, I chose that example because I'm old enough to have used BASIC interpreters on 8-bit micros like the PET and the BBC Micro.

right isn't a C array e.g.

int myArray[3][3]; // A 3X3 array
or
int myArray[4][4][4]; // A 4X4X4 array

the same thing as what you have shown in basic?

C allows for any depth of arrays you wish. If in BASIC there is a difference between multidimensional and nested arrays could you explain that?

I've always thought of a n dimensional array as a datastructure with a variable at all indexes.

And nested arrays I've thought of as a more dynamic:

Here at index 1 , 2 the value of the 'pointed' [dereferenced contents of the pointer] is 1
But at 1,3 the poited data is yet another pointer (to yet another array, this is in my point of view a 'nested' array)

nested[1][2] = 1;
nested[1][3] = { 2 , 3 , 4 , 5 };

And thus:

nested[1][2][2]; would cause an error but
nested[1][3][2]; is equal to 4

I think this is not traditinally used in c/c++ but are often used in php and other interpreted languages.

BTW array[x][y] is essentially the same as array[x*y].

same thing as what you have shown in basic?

Yes, exactly the same! But in BASIC, the syntax uses a commas to separate the index numbers, whereas in C you write the entire index, including the brackets, twice (square brackets in C of course). I was just trying to point out the difference in syntax.

Yes, exactly the same! But in BASIC, the syntax uses a commas to separate the index numbers, whereas in C you write the entire index, including the brackets, twice (square brackets in C of course). I was just trying to point out the difference in syntax.

Ah sorry, I misunderstood what you wrote.