# How can I average a TMP-36 reading?

Okie doke, I had an issue in another thread unrelated to this specific region of my project, so I felt a new thread was in order- Not to mention I just thought of this…

My project is simple; displaying the temperature from a TMP-36 on an oLED display.
My goal is to be able to average 5 readings and display the calculated average from that.

``````int sensorPin = 0; //the analog pin the TMP36's Vout (sense) pin is connected to
#include <SPI.h>
#include <Wire.h>

#define OLED_RESET 4

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2

#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH  16

#if (SSD1306_LCDHEIGHT != 64)
#endif

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

// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x64)
// init done

display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(2);
display.setCursor(32,0);
display.print("Temp:");
display.setTextSize(1);
display.setCursor(0,0);
display.print("TMP36");
display.display();
}

void loop() {

// 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(" degrees C");

// now convert to Fahrenheit
float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;

display.setTextColor(WHITE, BLACK);
display.setTextSize(3);
display.setCursor(8,18);
display.print(temperatureF);
display.print("F");
display.setTextSize(1);
display.setCursor(0,40);
display.print(temperatureC);
display.print("C");
display.display();
Serial.print(temperatureF); Serial.println(" degrees F");
delay(750);
}
``````

Is my current code, I don’t know how to store the values in my Arduino in order to do the calculation.

I’ve looked around and I can’t find all that much on this. Thanks everyone, I’m slowly learning!

``````#define NO_OF_READINGS 5

{
// move old readings down to make room for new one
for( int i=1; i<NO_OF_READINGS; i++ )
{
}
}

{
float total= 0.0;
for( int i=0; i<NO_OF_READINGS; i++ )
{
}

}
``````

Yours,
TonyWilk

Here’s one simple way, google “Arduino analog smoothing” for many more.

``````void setup()
{
Serial.begin(9600);
}
void loop()
{
int total = 0;
for(int i = 0;i < 16;i++) // accumulate 16 readings in total
Serial.println(total / 16); // divide by 16 and print
delay(1000);
}
``````

outsider:
Here’s one simple way, google “Arduino analog smoothing” for many more.

``````void setup()
``````

{
Serial.begin(9600);
}
void loop()
{
int total = 0;
for(int i = 0;i < 16;i++) // accumulate 16 readings in total
Serial.println(total / 16); // divide by 16 and print
delay(1000);
}

Can you break this down in detail for me? What does each operator do? Thanks, appreciate it.

Is this good enough?

``````void setup()
{
Serial.begin(9600);
}
void loop()
{
int total = 0; // declare a 16 bit signed integer (int)
// named "total"
for(int i = 0;i < 16;i++) // the "for" loop does the next line 16 times
Serial.println(total / 16); // print the results of total divided by 16
delay(1000); // wait one second
}
``````

outsider:
Is this good enough?

``````void setup()
``````

{
Serial.begin(9600);
}
void loop()
{
int total = 0; // declare a 16 bit signed integer (int)
// named “total”
for(int i = 0;i < 16;i++) // the “for” loop does the next line 16 times
Serial.println(total / 16); // print the results of total divided by 16
delay(1000); // wait one second
}

How does `int i = 0;i < 16;i++` work? I’d like to familiarize myself with this type of loop as I see it sometimes, but don’t quite understand it.

Thanks again.

I'd like to familiarize myself with this type of loop

Have a look at:

Reference > Language > Structure > Control structure > For

or

https://www.cprogramming.com/tutorial/c/lesson3.html

Yours,
TonyWilk

The other option is an Exponential Moving Average:

It's a type of IIR filter.

In the IDE menu bar, click HELP -> Reference:
https://www.arduino.cc/reference/en/language/structure/control-structure/for/
https://www.arduino.cc/en/Reference/HomePage

Ahh, I understand the loop now. All is going good! Thanks everyone for all the help!

Actually, I just realized something.

138.88Favg
137.12 degrees F
136.24Favg
135.36 degrees F
133.60Favg
134.48 degrees F
130.96Favg
131.84 degrees F

I’m doing something wrong, but I can’t figure it out. I want a 30 second average, I heated up the sensor for just a second, if it’s an average, why would it basically reflect the current value?

My code so far

``````int sensorPin = 0; //the analog pin the TMP36's Vout (sense) pin is connected to
#include <SPI.h>
#include <Wire.h>

#define OLED_RESET 4

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2

#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH  16

#if (SSD1306_LCDHEIGHT != 64)
#endif

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

// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x64)
// init done

display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(2);
display.setCursor(32,0);
display.print("Temp:");
display.setTextSize(1);
display.setCursor(0,0);
display.print("TMP36");
display.display();
}

void loop() {
int total = 0;
for(int i = 0;i < 30;i++) // accumulate 5 readings in total
int avg = (total / 30); // divide by 30
//  Serial.println(avg);

/////////////////////////////////////////////////

float voltageavg = avg * 5.0;
voltageavg /= 1024.0;

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

// now convert to Fahrenheit
float temperatureFavg = (temperatureCavg * 9.0 / 5.0) + 32.0;

Serial.print(temperatureFavg);
Serial.println("Favg");
///////////////////////////////////////////////////

float voltage = reading * 5.0;
voltage /= 1024.0;

// 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(" degrees C");

// now convert to Fahrenheit
float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;
///////////////////////////////////////////////////

display.setTextColor(WHITE, BLACK);
display.setTextSize(3);
display.setCursor(8,18);
display.print(temperatureF);
display.setTextSize(2);
display.print("F");
display.setTextSize(1);
display.setCursor(0,40);
display.print(temperatureC);
display.print("C");
display.display();
Serial.print(temperatureF); Serial.println(" degrees F");
delay(1000);
}
``````

How many samples in 30 seconds?

outsider:
How many samples in 30 seconds?

It should be 30, with a 1000ms delay at the end of the loop, right?

``````  for(int i = 0;i < 30;i++) // accumulate 5 readings in total
``````

What you think of this rude & crude start? Only ADC results, not yet converted to temperature.

``````unsigned long tStart;
int tEnd = 1000,

float temp,
total,
average;
byte counter,
samples = 30;

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

}

void loop()
{
if(millis() - tStart > tEnd)
{
tStart += tEnd;
average = total / samples;
Serial.print("  ");
Serial.print(counter + 1);
Serial.print(" \t");
if(++counter >= samples)
{
counter = 0;
total = 0;
Serial.println();
Serial.print(" 30 second average = ");
Serial.println(average);
Serial.println();
}
}
}
``````

For a rolling average like this, I like to use a software low-pass filter.

``````double smoothed = some_sensible_initial_value;

void loop() {
if(its time to take a sample) {
double sample = take_a_sample();
smoothed = smoothed * .75 + sample * .25;
}
}
``````

If you tweak the .75/.25, you get a filter that responds quickly or slowly to fluctuations. If you make two filters - a quick one and a slow one - the difference can tell you something about how fast the temperature is changing. Eg, you could ignore the data temperature unless both values more-or-less agree, so filtering out transient spikes.

Slick, I’m going to try that on my current blunder project, an LM34 (Fahrenheit) thats being a real bear to smooth,
TNX & k++.