Arduino Maths

Hi guys, I having some problems calculating the temp from sensor with arduino, I know the formula, and I can manually calculate with a calculator, but when I put it into code it doesn’t seem to work. I’m guessing this is just a stupid mistake due to my ignorance of how how arduino handles maths.

The formula is (((1.2/1023) * Sensor Value) -0.5) * 100

This is for an TMP36 being read by and Xbee (1.2V range, 10bit resolution), which works fine if I read the Sensor value directly and do the maths on a calculator.

The value is being read over serial from an attached Xbee, and being output to a 16x2 LCD screen

The bit of code I’m using(sorry if it’s ugly/messy):

int analogHigh = Serial.read();
      int analogLow = Serial.read();
      analogValue =  analogLow + (analogHigh * 256);
      value = 120000 / 1023;    //1200mv / 10 bit xbee 
      value2 = value * analogValue;   // convert Xbee reading into voltage
      current = (value2 / 10000) - 0.5;    //- offset from TMP 36

And the full code:

#include <LiquidCrystal.h>

// connect to an LCD using the following pins for rs, enable, d4, d5, d6, d7
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);


int debugLED = 13;
float analogValue = 0;
float value = 0;
float value2 = 0;
float current = 0;
float high = 0;
float low = 20;

void setup() {
  pinMode(debugLED,OUTPUT);
  Serial.begin(9600); 
  
    // set up the display 
   lcd.begin(16, 2); //Width and Height
   lcd.clear();
   lcd.print("Sensor Network");
   delay(3000);
   lcd.clear();
    //End LCD Setup
}
  
void loop() {
  //Read Temp from Serial ******************************************************************************
  // make sure everything we need is in the buffer
  if (Serial.available() >= 21) {
    // look for the start byte
    if (Serial.read() == 0x7E) {
      //blink debug LED to indicate when data is received
      digitalWrite(debugLED, HIGH);
      delay(10);
      digitalWrite(debugLED, LOW);
      // read the variables that we're not using out of the buffer
      for (int i = 0; i<19; i++) {
        byte discard = Serial.read();
      }
      int analogHigh = Serial.read();
      int analogLow = Serial.read();
      analogValue =  analogLow + (analogHigh * 256);
      value = 120000 / 1023;    //1200mv / 10 bit xbee 
      value2 = value * analogValue;   // convert Xbee reading into voltage
      current = (value2 / 10000) - 0.5;    //- offset from TMP 36
      
      if (current >= high) {  //Record High temp
        high = current;
      }
      if (current <= low) {   //Record low temp
        low = current;
      }
    } 
  }
  //Finish Read Temp from serial ************************************************************************

  
  //Start Screen
  
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Temp: ");
    lcd.print(current,1);
    lcd.print(" ");
    lcd.print(analogValue,1);
    lcd.setCursor(0,1);
    lcd.print("H: ");
    lcd.print(high,1);
    lcd.print("  L: ");
    lcd.print(low,1);
    delay(100);
    
}

I originally was using the following code, but broke it down into steps and outputted it to the scrren to try and work out where I was going wrong, my first assumption was that it was rounding 1.2/1023 to one decimal casing the problem, hence why I used 120000 and divided the final value by 1000 to compensate, but that didn’t work either:

 int analogHigh = Serial.read();
      int analogLow = Serial.read();
      analogValue =  analogLow + (analogHigh * 256);
      
      current = (((1.2 / 1023) * analogValue) -0.5) *100;

Currently it’s outputting between 5.1 and 7.4 when the actual value should be more like 4.0-18.0

Initial guess at what is wrong (we don't actually know, you just say it doesn't work) might be something to do with int to float casting.

I never bother remembering the rules, but I do bother remembering the potential for problems, my next step would be to try:

 current = (((1.2 / 1023) * (float)analogValue) -0.5) *100;

Also why not just calculate the factors once and use #defines or constant floats:

const float multiplier =1.1730205279;
#define OFFSET 50

 current = multiplier * (float)analogValue - OFFSET;

etc.

It would help to know what it calculates, compared to what you expect.

      value = 120000 / 1023;    //1200mv / 10 bit xbee

Since that is done with whole numbers, the result will be 117, regardless of that fact that you are putting it into a float afterwards.

1:1:
Initial guess at what is wrong (we don't actually know, you just say it doesn't work) might be something to do with int to float casting.

I never bother remembering the rules, but I do bother remembering the potential for problems, my next step would be to try:

 current = (((1.2 / 1023) * (float)analogValue) -0.5) *100;

Also why not just calculate the factors once and use #defines or constant floats:

const float multiplier =1.1730205279;
#define OFFSET 50

 current = multiplier * (float)analogValue - OFFSET;

etc.

Thanks, that code makes a lot more sense and is somewhat more tidy, I just had to change the cont float to 0.11730..... (error in my original formula) and it seems to work, an analogValue of 628 gives me 23.7. The value is a bit high but that is due the sensor reading about 5C to high rather then the math which is another matter altogether

For future reference, even when using floats unless you define (float) in the equation does it just perform integer math?

Once again, thanks for your help.

For future reference, even when using floats unless you define (float) in the equation does it just perform integer math?

If the calculation involves floats, no. Your calculation involved two ints. That the result was stored in a float is immaterial.

I can’t remember the rules, but it’s my opinion that it’s more important to remember that there are rules. :wink:

…and then try and see and/or web search.

In this case the search string you’re after is “implicit vs. explicit casting”

Oh and hey mate! from a fellow kiwi

The compiler evaluates expressions without wondering what you will do with them. For example this is valid C:

2 + 2;

What “type” is the result? Well we aren’t storing it anywhere, so it can’t know what type to use. So it follows the typing rules for evaluating expressions (these are fairly complex). Suffice to say in this case that they would be considered to be “int” type.