I’m a newer arduino user and I’m probably trying to walk before I learn to fully crawl…but its still an extension to my ‘crawling’ lesson.

I made a TMP36 temperature sensor as described in the basic tutorials but I noticed that it would occasionally get a noisy signal and read +/- 1 degreeF (most of the noise is consistently reading +/- exactly 0.7 degreeF). I wanted to take my learning the next step and try to learn how to smooth the readings because I would eventually like to graph the data without having to manually remove ‘outliers’ before plotting them. Looking online, I found some smoothing examples but I still seem to get similar results whether or not I run the ‘smoothed’ or just normal ‘read the sensor and print temp’ sketch. This last run that I did with the smoothed sketch (below) had noise that was exactly +/- 0.5 degreeF (see attached excel plot). Is there any way to get rid of that noise though code? Or, is there a mistake in my sketch that might actually be ‘smoothing’ the sensor readings? Again, I’m still not extremely well versed in the language so any helpful steps/explanations are welcome!

``````/*

Smoothing

and printing it to the computer.  Keeps ten readings in an array and
continually averages them.

The circuit:

Created 22 April 2007
By David A. Mellis  <dam@mellis.org>
modified 9 Apr 2012
by Tom Igoe
http://www.arduino.cc/en/Tutorial/Smoothing

This example code is in the public domain.

*/

// Define the number of samples to keep track of.  The higher the number,
// the more the readings will be smoothed, but the slower the output will
// respond to the input.  Using a constant rather than a normal variable lets
// use this value to determine the size of the readings array.

int total = 0;                  // the running total
int average = 0;                // the average

int inputPin = A0;

float degreesC, degreesF; //added to tutorial

void setup() {
Serial.begin(9600);
analogReference(EXTERNAL);    //Set AREF to external since using 3.3v: Added to tutorial
// initialize all the readings to 0:
}
}

void loop() {

// if we're at the end of the array...
readIndex = 0;    // ...wrap around to the beginning:
}

average = total / numReadings;   // calculate the average (of sensor readings)
delay(1);

float avgVoltage = average * 0.00322265625;  //Added to tutorial
degreesC = (avgVoltage - 0.5) * 100.0; //Added to tutorial
degreesF = degreesC * (9.0/5.0) + 32.0; //Added to tutorial

delay(5000);
}
`````` You've gone and used integer (truncating) division and lost most of the benefit of averaging!

Change this line:

``````  average = total / numReadings;   // calculate the average (of sensor readings)
``````

to:

``````  float average = 1.0 * total / numReadings;   // calculate the average (of sensor readings)
``````

And lose the declaration of average as an int at top level.

In general its usually much clearer to declare variables when you first use them, not all
at the top of the program or function. Only make a variable global or static if its value
has to persist between function calls.

Thanks Mark. I'm running that change (on 1000ms delay for now) to see if it helps. Definitely makes sense that it should not have been truncated to an integer though.

Zoomkat,
I'm not quite sure what you mean with "read it twice and use the second reading." Are you suggesting something like this?

``````total = total - readings[readIndex]2;
``````

you might also try taking more data over the 5 second interval…

Also, since you have an array, you can pass it to a smoothe() function by reference and get back a lot of the SRAM you used up with globals!

``````const int numReadings = 200;
const int inputPin = A0;

unsigned long lastMillis = 0;

void setup()
{
Serial.begin(9600);
analogReference(EXTERNAL);    //Set AREF to external since using 3.3v: Added to tutorial
}

void loop()
{
{
readIndex = 0;    // ...wrap around to the beginning:
}
delay(25);  //let us collect 200 readings over 5 seconds. edit: fixed delay interval

if (millis() - lastMillis > 5000UL)
{
Serial.print("Smoothed Value: ");  //Added to tutorial
float avgVoltage = smoothedValue * 0.00322265625;  //Added to tutorial
float degreesC = (avgVoltage - 0.5) * 100.0; //Added to tutorial
float degreesF = degreesC * (9.0 / 5.0) + 32.0; //Added to tutorial
lastMillis = millis();
}
}

float smoothe(const int *myArray, const size_t size)
{
int total = 0;
for(int i = 0; i < size; i++)
{
total+= myArray[i];
}
return (float)total/(float)size;
}
``````
``````//Sketch uses 4,410 bytes (14%) of program storage space. Maximum is 30,720 bytes.

//yours used:

//Sketch uses 4,412 bytes (14%) of program storage space. Maximum is 30,720 bytes.
``````

Thanks for the replies! Changing ‘average’ from integer to float seems to have fixed the issue.

Bulldog, I am going to do some research on parts within your suggestion and try to improve my coding language/skills. Your suggestion seems to be another ‘step’ into learning more detailed language and precise coding methods. As with the stepping though the ‘basic’ tutorials, knowing what outcomes I should expect make it easier to pick up on language application in my opinion. Thanks for taking the time to improve the design of my sketch using some other steps!

I'm not quite sure what you mean with "read it twice and use the second reading." Are you suggesting something like this?

I didn't write that code so I can't speak to what would do. looping "for" code is sometimes difficult to tweak and trouble shoot. With simple inline code you can simply make two reads like below and the second one is used.

``````newvalS1 = analogRead(potpinS1);