Creating a program that takes multiple readings from a sensor and averaging them

hello, I am fairly new to writing my code for Arduino and I am working on a project and wanted to take a series of readings from temperature sensor over an hour and average them out (and possible find the range) any Ideas on how I should go about doing this?

I have been using tinkerCAD to test out my code, I tried using an Array but that didn't do anything, I probably did something wrong.

int sensorPin = 0; //the analog pin the TMP36's Vout (sense) pin is connected to
                        //the resolution is 10 mV / degree centigrade with a
                        //500 mV offset to allow for negative temperatures
unsigned long second= 1000;
unsigned long minute= 60000;
unsigned long previousMillis=0; 
float ArrayTemp[4];
float tsum=0;
float AvgTemp=0;


void setup(){
  Serial.begin(9600);  //Start the serial connection with the computer
                       //to view the result open the serial monitor 
}
 
void loop()                     // run over and over again
{

  int reading = analogRead(sensorPin);  
 
 // converting that reading to voltage, for 3.3v arduino use 3.3
 float voltage = reading * 5.0;
 voltage /= 1024.0; 
 
 // print out the voltage
 Serial.print(voltage); Serial.println(" volts");
 
 // now print out the temperature
 float temperatureC = (voltage - 0.5) * 100 ;  //converting from 10 mv per degree wit 500 mV offset
                                               //to degrees ((voltage - 500mV) times 100)
 Serial.print(temperatureC); Serial.println(" Celcius"); 

 for(int i=0; i<4;i++){
	ArrayTemp[i]= temperatureC;
}
for (int s=0; s<4; s++){
    tsum += ArrayTemp[s];
}
AvgTemp = tsum/4;
Serial.print(AvgTemp);
delay(5*second);
  
}

Yes.

This

 for (int i = 0; i < 4; i++) {
	ArrayTemp[i] = temperatureC;
}

Almost instantly puts the same value in all array slots. What do you expect the average would be?

You need to read the sesnor to get a new value, and you have to take those readings at regular intervals like once a minute or once every ten seconds or whatever.

Also, use some spaces in your code. They are free and make it easier to read.

Try the IDE Auto Format tool.

a7

Do you know to fix it?

OK, How exactly should I go about doing this? I tried but the sensor read code in the for loop for the array, but when I run the code nothing is output for the Average.

int sensorPin = 0; //the analog pin the TMP36's Vout (sense) pin is connected to
                        //the resolution is 10 mV / degree centigrade with a
                        //500 mV offset to allow for negative temperatures
unsigned long second = 1000;

unsigned long minute = 60000;

unsigned long previousMillis = 0; 

float ArrayTemp[4];

float tsum = 0;

float AvgTemp = 0;



void setup(){
  
  Serial.begin(9600);  //Start the serial connection with the computer
                       //to view the result open the serial monitor 
}
 
void loop()                     // run over and over again
{

  int reading = analogRead(sensorPin);  
 
 for(int i = 0; i < 4; i++){
   
 float voltage = reading * 5.0;
  
 voltage /= 1024.0; 
 
 // print out the voltage
  
 Serial.print(voltage); Serial.println(" volts");
 
 // now print out the temperature
  
 float temperatureC = (voltage - 0.5) * 100 ;  //converting from 10 mv per degree wit 500 mV offset
                                               //to degrees ((voltage - 500mV) times 100)
 Serial.print(temperatureC); Serial.println(" Celcius"); 

 ArrayTemp[i]= temperatureC;
   
 delay(minute);
}
for (int s = 0; s < 4; s++){
  
    tsum += ArrayTemp[s];
}
AvgTemp = tsum/4;
  
Serial.print(AvgTemp);
  
  
}

You have to read the sensor to get the current value.

Move the analog read into the loop.

a7

This

int reading = analogRead(sensorPin); 

happens once. It does not establish a magic connection between the sensor and reading.

Common beginner's misapprehension.

And for testing, use a smaller dealy. Life is short!

a7

I should put that into the loop? if it only happens once it should be fine in the setup I just left it from the example of the sensor I was using. The main problem I am having seems to be the Array no info seems to be saving in it, any Ideas

use a running average, leaky integration

const byte SensorPin = A0;      // TMP36's Vout (sense) pin
                                // 10 mV / degree centigrade
                                // 500 mV offset for negative temperatures

const unsigned long MsecPeriod = 10 * 1000;
      unsigned long msecLast;

float sensorVal;
float sensorVolt;
float tempC;
float tempCavg;

char s [90];

// -----------------------------------------------------------------------------
float
getTemp ()
{
    sensorVal   = analogRead (SensorPin);
    sensorVolt  = sensorVal * 5.0 / 1024;

    //converting from 10 mv per degree wit 500 mV offset
    tempC       = (sensorVolt - 0.5) * 100 ;

    return tempC;
}

// -----------------------------------------------------------------------------
void loop ()
{
    unsigned long msec = millis ();

    if (msec - msecLast < MsecPeriod)
        return;
    msecLast += MsecPeriod;

    tempCavg += (getTemp () - tempCavg) * 0.25;

    Serial.print ("  ");  Serial.print (tempCavg);
    Serial.print ("  ");  Serial.print (tempC);
    Serial.print ("  ");  Serial.print (sensorVolt);
    Serial.print ("  ");  Serial.print (sensorVal);
    Serial.println ();

}

// -----------------------------------------------------------------------------
void setup()
{
    Serial.begin(9600);
    tempCavg = getTemp ();      // init avg with current val
    msecLast = -MsecPeriod;
}
u

Thanks for the help if I wanted a reading ever 5 minutes what would I change, or should I just add a delay?

TJ

I guess I'm having trouble explaining.

Reading the analog pin once, in setup() would mean never measuring whatever you are sensing again.

To get a new value, you have to execute a line of code that does an analogRead().

analogRead() must be done at the time you want to see the current value on the analog input pin.

I can't test your code, but like

//   int reading = analogRead(sensorPin);  // NOT HERE
 
 for (int i = 0; i < 4; i++) {
   
    int reading = analogRead(sensorPin);  // HERE. every time you need to read the sensor
   
    float voltage = reading * 5.0;
  
    voltage /= 1024.0; 

BTW I added a few more spaces, spaces which are part of almost every style guide ever written, and certainly among the handful of the more popular ones.

@gcjr is jumping ahead to where we help you do better than an average like you are using. I suggest you to get your idea functioning, and some of these misconceptions cleared up first, but the leaky integrator is def what you prolly want to use soon enough.

a7

1 Like

you need to test the code and understand what's going before using final values

@tjackin05
This code is much simpler and may be easier for you to understand
Give it a try

//The analog pin the TMP36's Vout (sense) pin is connected to
const int sensorPin = A0;
//the resolution is 10 mV / degree centigrade with a
//500 mV offset to allow for negative temperatures

// Set the rate to how often you want to read the sensor (milliseconds)
const unsigned long rate = 2000;
 
unsigned long previousMillis = 0, nowMillis = 0;

float ArrayTemp[4] = {0, 0, 0, 0};
float tsum = 0;
float AvgTemp = 0;
int i = 0;

void setup()
{
  Serial.begin(9600);  //Start the serial connection with the computer
  //to view the result open the serial monitor (baud=9600)
  nowMillis = millis(); // Initialize nowMillis
}

void loop()
{
  if ((millis() - nowMillis) > rate)
  {
    int reading = analogRead(sensorPin);

    // converting that reading to voltage, for 3.3v arduino use 3.3
    float voltage = reading * 5.0 / 1024.0;

    // print out the voltage
    Serial.print(voltage); Serial.println(" volts");

    // now print out the temperature
    float temperatureC = (voltage - 0.5) * 100 ;  //converting from 10 mv per degree wit 500 mV offset
    //to degrees ((voltage - 500mV) times 100)
    Serial.print(temperatureC); Serial.println(" Celcius");


    ArrayTemp[i] = temperatureC;
    i++;
    if (i == 4) i = 0;
    
    for (int k = 0; k < 4; k++)
    {
      tsum += ArrayTemp[k];
    }

    AvgTemp = tsum / 4.0;
    tsum = 0;

    Serial.print("Avg = "); Serial.println(AvgTemp); Serial.println();

    nowMillis = millis();
  }

}

Most of the code was already functioning just the array and Average weren't outputting to the serial monitor. The temperature reading was fine.

That question was to try and understand the code better, maybe I wasn't direct enough. Is MsecPeriod controlling the time between measurements, if not what is it doing?

yes

Wait, I misunderstood. Are you saying that it does not print anything? As opposed to not seeming to print any kind of plausible average?

  Serial.print(" you don't see this print statement execute? ");
  Serial.print(AvgTemp);

That's head scratcher. I am looking through the tiny window now, but I don't see how it can be just skipping over your print statement.

Please post your latest runs but doesn't work sketch, With all the help, it's hard to know where you are yourself.

Maybe we see why the print statements don't.

a7

when I am using my code Serial.print(AvgTemp); was not printing anything just the temperature every few seconds

My code works

The temperature is being printed as you add it to the array.
The problem is you read the temperature once, and then add it to the array four times.

The average is being printed.
However because you used Serial.print(), rather than Serial.println(), something else gets printed on the same line after it.

After you have calculated the average you need to reset the value of 'tsum' before the next time you calculate the average.
'tsum' just continues getting larger and larger

Have a look at what the serial monitor displays after I have changed your

Serial.print(AvgTemp);

to:

Serial.print("AvgTemp = ");
Serial.println(AvgTemp);
  • I've made a minute much shorter (2s) for demonstration purposes.
  • I am feeding a slowly ramping voltage from a function generator into the analogue input, to simulate a varying temperature.