Pages: [1]   Go Down
Author Topic: "long" variable overflowing like an "int"  (Read 602 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi everyone,

I have a sketch which I'm running on an Arduino Mega 2560.

In this sketch I declare two volatile long int variables that are used for tracking encoder pulses (with interrupts) from two motors (x and y).

The problem is that when displaying these on the serial monitor, I find that they overflow at +32,767 or -32,768, as I'd expect integers to do.

I've tried changing long int to long but to no avail.

Here are the relevant pieces of code:

Code:
volatile long int x_position = 0; //Global coordinates, remembering last position
volatile long int y_position = 0;

const int CONVERSION = 1000; //Convertion between ecnoder pulses (as depicted in x_position and y_position) and mm

void displayCoordinates(int x_position, int y_position)
{
  Serial.print("(x,y) in pulses:(");
  Serial.print(x_position);
  Serial.print(",");
  Serial.print(y_position);
  Serial.print(")");
  Serial.print("(x,y) in mm:("); //For CONVERSION pulses per mm
  Serial.print(x_position/CONVERSION);
  Serial.print(",");
  Serial.print(y_position/CONVERSION);
  Serial.print(")");
  Serial.println();
}

Hope that's specific enough. If you need more details please let me know.

Thanks a lot!  smiley-eek

Gadi.
Logged

Gosport, UK
Offline Offline
Faraday Member
**
Karma: 19
Posts: 3114
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
void displayCoordinates(int x_position, int y_position)

If you are passing longs to this, I'm not surprised you're having problems.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
void displayCoordinates(int x_position, int y_position)

If you are passing longs to this, I'm not surprised you're having problems.

Now isn't this embarrassing..  smiley-red

Thanks!
Logged

Global Moderator
Netherlands
Online Online
Shannon Member
*****
Karma: 168
Posts: 12431
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Now isn't this embarrassing.. 

No, it is a well known fact that you are nearly "blind" when it comes to reading your own code (or any other document). Your brain just makes the same mistake over and over again. A trick that helps is reading code (or your doc) backwards, yes it takes much time but you are very aware of what you read.
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

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

No, don't feel bad about it, especially if you program on architectures where an 'int' is 32 bits wide at the same time as programming for Arduino.
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.

Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Got the same problem. But my code is so simple, I don't think I'm converting it at any way to an int.
When I put the time to 40000, I get an output of -25536.
Any helps would be great.


Code:
long myTime = 0;

void setup(){
  Serial.begin(57600);
  myTime = 40*1000;
}

void loop(){
  Serial.println(myTime);
  delay(2000);
}
Logged

Leeds, UK
Offline Offline
Edison Member
*
Karma: 71
Posts: 1641
Once the magic blue smoke is released, it won't go back in!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

For integer math (more specifically 'int' math) 40000 = -25536. It is the difference between a signed typed and an unsigned type.

Unless told otherwise, the compiler will assume the int type for literal values. You need to tell it to use long type instead:

Code:
myTime = 40L*1000L;
Note the L at the end to specify Long. UL can be used to specify Unsigned Long.
Logged

~Tom~

Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, thanks.
But why do I declare it as long (or unsigned long, both didn't work) if he still works with it like an integer.
Get it that he does, but is there any higher philosophy?
Logged

California
Offline Offline
Faraday Member
**
Karma: 82
Posts: 3123
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, thanks.
But why do I declare it as long (or unsigned long, both didn't work) if he still works with it like an integer.
Get it that he does, but is there any higher philosophy?

The intermediate match is assumed to be an int, you're just assigning it to a long.

If you're working with the long variable, it treats it as a long.
Logged

Ayer, Massachusetts, USA
Offline Offline
Edison Member
*
Karma: 50
Posts: 1766
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, thanks.
But why do I declare it as long (or unsigned long, both didn't work) if he still works with it like an integer.
Get it that he does, but is there any higher philosophy?

Yes, without at least one suffix (U, L, and LL, or the lower case varients u, l, and ll -- but you really don't want to use 'l' since humans likely confuse it with the digit '1'), the compiler gives it a type based on the value:

  • If the value is between INT_MIN and INT_MAX inclusive, the type is signed int
  • If the value is between INT_MAX+1 and UINT_MAX inclusive, the type is unsigned int
  • If the value is between LONG_MIN and INT_MIN-1 or UINT_MAX+1 and LONG_MAX, the type is signed long
  • If the value is between LONG_MAX+1 and ULONG_MAX, the type is unsigned long
  • If the value is between LLONG_MIN and LONG_MIN-1 or ULONG_MAX+1 and LLONG_MAX, the type is signed long long
  • If the value is between LLONG_MAX+1 and ULLONG_MAX, the type is unsigned long long
  • If the value cannot be represented as a signed long long or unsigned long long value, it is an error
Since both 40 and 1000 are greater than or equal to -32768 (INT_MIN) and less than or equal to 32767 (INT_MAX), the types are signed int.  If you had written 40000, then the type would have been unsigned int.

In the ISO C world, this is called value preserving, and it is one of the changes that the original C standards committee did over the original K&R C language, which was somewhat looser, and would go from signed int to signed long without going to unsigned int (called sign preserving).
« Last Edit: August 21, 2012, 11:58:26 am by MichaelMeissner » Logged

Pages: [1]   Go Up
Jump to: