float number calculation issue

Hello all,

I just received my Arduino and I am following some basic tutorial to better understand how to program it etc.

Now, my very simple program reads the temperature sensor and converts its output in ºC.

int tempPin = 0;
int analogTempRead;
float celsiusTempRead;

void setup() {
  Serial.begin(9600);
  Serial.println("Ready.");
}

void loop() {
  analogTempRead = analogRead(tempPin);
  delay(3);
  analogTempRead += analogRead(tempPin);  // Taking 5 samples in an attempt
  delay(3);                               // to get a more accurate reading
  analogTempRead += analogRead(tempPin);  // but I'm not sure it makes any
  delay(3);                               // difference…
  analogTempRead += analogRead(tempPin);
  delay(3);
  analogTempRead += analogRead(tempPin);
  analogTempRead /= 5;
  celsiusTempRead = (((analogTempRead*5/1024)-.5)*100);
  Serial.print("Temperature = "); Serial.print(celsiusTempRead); 
  Serial.println(" C");
  delay(1000);
}

What I don't understand is what happens on this line:

 celsiusTempRead = (((analogTempRead*5/1024)-.5)*100);

If I divide by 1024, I am getting a bogus result (ie -50.00 C) but if I divide by 1024.0 then I am getting around 25 which is about the right temperature.
Why does 1024 vs 1024.0 make any difference?

Also, if you have any suggestions re the general structure of the code, I'd be glad to hear them as I learnt how to code by myself.

Why does 1024 vs 1024.0 make any difference?

Because 1024 is an integer, and so forces integer-only arithmetic.

hfp777:
Also, if you have any suggestions re the general structure of the code, I'd be glad to hear them as I learnt how to code by myself.

Look at how to use a for() loop for your multiple reads. Use a const (or #define) for the number of samples so you can adjust it easily.

I see, thanks!

wrt your comments in the code:

Making multiple reading reduces the noise as too high readings and too low cancel each other out (most of the time) which increases the precision.
If you do averaging it is good practice to use a power of 2 as the compiler can optimize the division afterwards, typically 4,8,16 or 32. If you want to take more than 32 readings e.g. 64 or 128 or even 256 to average you should use a long iso int as it otherwise would not fit.

Another way to average is to take a running average:

float val;
float alpha = 0.10;  // valye to play with

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

void loop()
{
  val = alpha * analogRead(A0) + (1-alpha) * val;  // new value counts for 10% old value for 90%
  Serial.println(val);
}

Another thing you can do to get a better result is to take multiple reading and don't average them but adjust the formula.
The difference is shown in the sketch below.

float val;
float alpha = 0.10;  // valye to play with

void setup()
{
  Serial.begin(9600);
  Serial.println("Volt1\t\tVolt2");
}

void loop()
{
  long sum = 0;
  for (int i=0; i<100; i++) sum += analogRead(A0);      // make 100 readings so sum = [0..102300]

  float volt1 = 5.0 * sum / 102300;

   // compare to this
  sum = sum/100;
  float volt2 =  5.0 * sum / 1023;

  Serial.print(volt1, 3);
  Serial.print("\t\t");
  Serial.println(volt2, 3);
}

Succes

Very useful info, much appreciated :slight_smile: