parseInt oddity

Hi!

Playing with my Christmas present :) I stumbled on an odd thing

This code seems not to work:

int vel=0;

...

void loop() {
 while (Serial.available() > 0) {
   vel = constrain(Serial.parseInt(), -255, 255);
   Serial.println(vel);   
 }
}

It returns 0 about a second after entering any number in the monitor.

But this does:

int vel=0;

...

void loop() {
 while (Serial.available() > 0) {
   vel = Serial.parseInt();
   vel = constrain(vel, -255, 255);
   Serial.println(vel);  
 }
}

Returns the constrained input as it should.

What is happening here?

What is happening here?

My first question would be what you have the option in the lower, right corner of the Serial Monitor set to. That it takes approximately one second to do anything suggests that the option is set to not append anything. Appending something will speed up the parseInt() method considerably.

Thanks for the info. I did try the two versions with and without appending line ending. It might have been a faster reply with line ending but the result (0) for the first version remained.

I'm curious about the apparent difference between: vel = constrain(Serial.parseInt(), -255, 255); and vel = Serial.parseInt(); vel = constrain(vel, -255, 255);

I'm curious about the apparent difference between:

Beats me. The return type for parseInt() (stupid name, given the return type) is long, so explicitly forcing the truncation to an int may be (and apparently is) giving different results than implicitly converting in the function call.

Aha! Thanks! "If doing math with integers, at least one of the numbers must be followed by an L,"....

Further testing still gives odd behaviour.

Testing with appended newline in serial monitor:

long vel = 0;

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

void loop() {
  while (Serial.available() > 0) {
    vel = Serial.parseInt();
    //vel = max(Serial.parseInt(), 10L);
    vel = max(vel, 10L);
    Serial.println(vel);
  }
}

Prints directly the correct maximum of the input and 10.

But

long vel = 0;

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

void loop() {
  while (Serial.available() > 0) {
    //vel = Serial.parseInt();
    vel = max(Serial.parseInt(), 10L);
    //vel = max(vel, 10L);
    Serial.println(vel);
  }
}

Returns 0 after 1 second. It seems that parseInt times out and then max gives an exception so vel is unchanged.

Uses: Arduino Uno r3 Arduino IDE 1.0.6

does this give you a clue?

#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))

So constrain and max are macros and not a functions. But how does that affect the inline use of Serial.parseInt()?

I have (almost) never programmed C so this is new ground for me.

The pre-processor see’s

#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))

and turns…

vel = constrain(Serial.parseInt(), -255, 255);

into…

   vel = ((Serial.parseInt())<(-255)?(-255):((Serial.parseInt())>(255)?(255):(Serial.parseInt())));

i.e. two nested ternary operators, which is effectively functionally equivalent to…

if (Serial.parseInt() < -255)
{
  vel = -255;
}
else
{
  if (Serial.parseInt() > 255)
  {
    vel = 255;
  }
  else
  {
    vel = Serial.parseInt();
  }
}

Ok. That explains it. So it ends up with three calls to Serial.parseInt() and two will fail due to lack of input. Maybe this effect should be mentioned in the reference.

It is mentioned in the reference - look for the "Warning" section: http://arduino.cc/en/Reference/Max

However the entry for constrain() lacks the warning...

There definitely is room for improvement in the language reference...