Go Down

Topic: Combining bitwise and integer math (Read 926 times) previous topic - next topic

Stafford

May 26, 2009, 07:41 pm Last Edit: May 26, 2009, 07:43 pm by staffordj Reason: 1
I am working on a temperature control application using DS18B20 temp sensor.  I wrote code to convert the serial data into a temperature.  In order to troubleshoot I set it up in MS Visual C++ with some test values.  I used the following statement to get the whole portion of the temp and scale it so I can add the fraction portion and return it as an integer:
    Whole= (TReading >> 4) *10000;
It worked fine in visual c++, but did not work in Arduino.  After trying a few things (OK, more than a few) I found that this works:
    Whole= (TReading >> 4) ;
    Whole*=10000;
Any idea why the original method didn't work out?

Coding Badly

It's very likely a problem with "type promotion".  How are Whole and TReading declared?

- Brian

Stafford

I tried both int and long.  I also tried to typecast to int, but I am not sure my syntax is correct:
     (int) (TReading >>4) * 10000;

AWOL

As Coding Badly said, if you declared your variables as "int" in VC++, they won't be the same size "int" in Arduino.

It's one of the quirks of C (and by extension, C++) that "int" is was originally meant to be the native word size of the processor.

On an Arduino, sizeof (int) returns "2", whereas on a Pentium derivative, it will return "4".

Automatic type promotion is another tricky legacy of 'C'

http://home.att.net/~jackklein/c/inttypes.html
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

AWOL

Code: [Select]
(int) (TReading >>4) * 10000L;
Maybe?
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Stafford

Thinking about it a little more, I am not certain I up'd TReading to long because it was holding a 2 byte integer.  I am sure I had Whole set to long.  Is there a temporary int generated to hold the intermediate value that is overflowing?

Coding Badly

If there is then the compiler has a serious bug.  In other words, this is very unlikely to be the problem.

- Brian

Stafford

#7
May 28, 2009, 05:11 am Last Edit: May 28, 2009, 05:12 am by staffordj Reason: 1
Whole = (TReading >> 4) * 10000L     did the trick.  C and C++ are supposed to follow the same rules for promotion and default to the largest size involved.  In this case, I guess it was evaluating the expression ((TReading >>4 ) *10000) as int since both TReading and 10000 were int and then promoting to long for the assignment to Whole. Using 10000L forces the promotion to happen before the expression is evaluated and prevents the overflow.  Thanks for the help.  

Go Up