Pages: [1]   Go Down
Author Topic: Combining bitwise and integer math  (Read 751 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 6
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
« Last Edit: May 26, 2009, 12:43:44 pm by staffordj » Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 176
Posts: 12285
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

- Brian
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 6
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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;
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 238
Posts: 24284
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

"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.

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 238
Posts: 24284
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
(int) (TReading >>4) * 10000L;
Maybe?
Logged

"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.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 6
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 176
Posts: 12285
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

- Brian
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 6
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.  
« Last Edit: May 27, 2009, 10:12:30 pm by staffordj » Logged

Pages: [1]   Go Up
Jump to: