Calculating average value

I'm using this fairly basic code to calculate the average of some values (1 reading per minute, average over 5 readings)

The first cycle works fine - then things go crazy

tA = 24
tA = 24
tA = 24
tA = 24
tA = 24
then....
tA = 120
tA = 60
tA = 40
tA = 30
tA = 24
and then keeps going like this!

Here are the relevant bits of code for the average calcs:

const int TnumReadings = 5;

int Treadings[TnumReadings];      // the readings from temp sensor
int Ttotal = 0;                   // the running total
int TAverage = 0;                 // the average
int Tindex = 0;

for (int thisTempReading = 0; thisTempReading < TnumReadings; thisTempReading++)
    Treadings[thisTempReading] = 0; 


void calcAverages(){
  
  Ttotal= Ttotal - Treadings[Tindex];             // subtract the last TEMP reading:
  Treadings[Tindex] = temp;                       // read TEMP value:
  Ttotal= Ttotal + Treadings[Tindex];             // add the TEMP reading to the total:
  Tindex = Tindex + 1;                            // advance to the next position in the array:
  TAverage = Ttotal / Tindex        ;            // calculate the average:    
  if (Tindex >= TnumReadings)                    // if we're at the end of the array...
   {
    Tindex = 0;                                   // ...wrap around to the beginning:
   }

Serial.print(" tA = ");
        Serial.println(TAverage);
}

I am sure that I am missing something obvious here but no amount of coffee seems to be helping LOL!

Stocky

at no point in your loop did you zero your total averages its just adding onto your previous loop

If you are only going to provide what you think "are the relevant bits of code", perhaps we should provide only what we think are the relevant parts of the answer?

I would have liked to have seen the rest of the code, including the definition of the variable types and how the temperature is measured, and where the function is called. However...

The indenting is weird. Please use the button in the IDE to straighten it out. (I use a different IDE and cannot provide the details of how to do formatting in the Arduino IDE, but i know that it is there.)

You maintain a total of the last 5 readings (except at the beginning when you are first starting up), but the divisor for the average counts 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, ... It should be 1, 2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, ...

Your "average" is what is typically called a "running average". It is a good exercise in programming if you want to do it yourself, but I believe there is already an Arduino library for this if you want to save yourself the grief.

Good luck!

  TAverage = Ttotal / Tindex        ;            // calculate the average:    
  if (Tindex >= TnumReadings)                    // if we're at the end of the array...
   {
    Tindex = 0;                                   // ...wrap around to the beginning:
   }

What do you think the divide accomplishes, after Tindex is "wrapped around"?

EDIT - just found a error in the code - thanks jremington, your suggestion made me look again and the sample code from the example below and spotted the issue
BUT - now the first 5 reads don't average properly instead!

OK - I don't think its as simple as clearing the total

I am using the example at http://arduino.cc/en/Tutorial/Smoothing as the basis for this code

I have trimmed my code back to the bare basics and it still behaves as before
It seems to be passing the Ttotal Value to Treadings[Tindex] at the end of each loop which is why it goes haywire

So heres the FULL code as it stands for this test:

#include <dht.h>               //For RHT03/DHT22 Sensor

dht DHT;

#define DHT22_PIN 3           //RHT03/DHT22 data pin

int temp;
int rh;

#define MSECS_CALC 10000

const int TnumReadings = 5;

int Treadings[TnumReadings];      // the readings from temp sensor
int Tindex = 0;                   //index of current reading
int Ttotal = 0;                   // the running total
int TAverage = 0;                 // the average


 

//=======================================================
// Initialize
//=======================================================
void setup() {
  
Serial.begin(9600);
          
for (int thisTempReading = 0; thisTempReading < TnumReadings; thisTempReading++)
    Treadings[thisTempReading] = 0; 

}

//=======================================================
// Main loop.
//=======================================================
void loop()
{
  
int chk = DHT.read22(DHT22_PIN);
temp = DHT.temperature,0;
rh = DHT.humidity,0;
  
Ttotal = Ttotal - Treadings[Tindex];             // subtract the last TEMP reading:
Treadings[Tindex] = temp;                       // read TEMP value:
Ttotal= Ttotal + Treadings[Tindex];             // add the TEMP reading to the total:
Tindex = Tindex + 1;                            // advance to the next position in the array:

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

TAverage = Ttotal / TnumReadings;                      // calculate the average:    
Serial.println(Tindex);
Serial.println(Ttotal);
Serial.println(TAverage);
Serial.println(Treadings[Tindex]);
   

     
Serial.print("T = ");
Serial.print(temp);
     
Serial.print(", R = ");
Serial.print(rh);
  
Serial.print(", tA = ");
Serial.println(TAverage);  
       
delay(MSECS_CALC);
}

To calculate the average, you have to divide the total by the number of values totaled.
Your latest code doesn't do that correctly if less than 5 values are recorded.

Correct!
Obviously the sample code is the issue - back to the drawing board once my headache subsides...........

My "incorrect" version of the sample code DID correctly do the first 5 samples then screwed up - maybe I can work out how to combine the two after a good lie down!

Stocky

Just found an Averaging library from Majenko - will have a play with that

Thanks all for your help :slight_smile:

Stocky

I am using the example at http://arduino.cc/en/Tutorial/Smoothing as the basis for this code

Yep, the example code is wrong. It does not correctly handle the first few values either.

You really have to be wary of just about anything that is posted -- there are a remarkable number of bad examples of coding, electrical wiring, etc.

I believe the compiler initializes all global data to 0, so the code fragment:

for (int thisTempReading = 0; thisTempReading < TnumReadings; thisTempReading++)
    Treadings[thisTempReading] = 0;

really isn't necessary. However, I don't have a problem with your loop because one should get in the habit of assuming that the data are not initialized. However, it might be a little more efficient to use:

memset(Treadings, 0, sizeof(Treadings) / sizeof(int));

If the number of items to be averaged is a power of 2 (e.g. 2, 4, 8,etc) you can get the average much more quickly with right shifts.

...R