Serial.available behavior

I'm an absolute beginner with coding, and this might be my first post here. Apologies if I'm wasting anyone's time.

I'm going through a book called "Arduino for Musicians" and in one of the early chapters, I'm going over an "if (Serial.available...)" example. The point of the sketch is to input a number into the serial monitor, and then the Arduino spits out the square, cube, and whether the number is odd or even.
Everything works as expected, except quickly after the answers appear in the serial monitor, another set of answers appears as if there was a second input 0. This is strange, as the loop starts with:

if (Serial.available() > 0)

Why would the Arduino respond to 0 as an input? And furthermore, why does it behave as if another entry was made? No matter what number you enter into the serial monitor, it spits back both the correct answers to that number as well as the answers to 0, always as a pair, with the answers to 0 lagging by some milliseconds.

When I change the code to the following:

if (Serial.available() > 1)

it no longer adds the additional "ghost" entry answers and behaves exactly as expected (with the exception it gives back an answer for 0, but only if you type it in).

I poked around some but couldn't find anything relevant, how can find some information about this specific behavior? Is there something in this code causing that odd behavior? Is there something more elegant than the solution I found? Anyone here recognize what's going on? I've pasted the entire code below, and a screen shot of the serial monitor with the code. Thanks!

void setup()
{
    Serial.begin(9600);
    Serial.println("Enter a number: ");
}

void loop()
{
    if (Serial.available() > 0)
    { 
        long input_byte = Serial.parseInt();
        
        long square = input_byte * input_byte;
        
        Serial.print("The square of the number is: ");
        
        Serial.println(square);
        
        long cube = input_byte * input_byte * input_byte;
        
        Serial.print("The cube of the number is: ");
        
        Serial.println(cube);
        
        if(input_byte % 2 == 0)
        {
            Serial.println("The number is even.");

        }else{

            Serial.println("The number is odd.");
        }
    }
}

click to expand:

Turn off line endings in serial monitor in the box in the attached image. Change Newline to No line ending. With line ending set to Newline a line feed character (0x0a or '\n')is sent after your number. Since parseInt only removes the number from the serial buffer, the line feed is left over and is evaluated the next time through loop(). The parseInt function interprets that character as a 0 (non numeric).

line ending.jpg

For information on doing reliable and non blocking serial communication see the serial input basics tutorial. The parseInt function is a blocking function that can slow the response of your program.

line ending.jpg

The parseInt() function leaves the newline (\n or 0x0A) in the buffer so the next time through loop() it tries to parse that which gives you a value of 0.

A more robust method is outlined in the thread "Serial Basics" by Robin2

Thank you! That was exactly it, I'll indeed look into the serial input basics tutorial and Serial Basics, cheers y'all

serial input basics tutorial and Serial Basics

Serial Basics and the serial input basics are the same thing.

Dragoicho:
Thank you! That was exactly it, I'll indeed look into the serial input basics tutorial and Serial Basics, cheers y'all

1. This is the details of the Serial Monitor of the Arduino IDE.
SerialMonitor.png
Figure-1: Serial Monitor of Arduino IDE

2. Assume that you have chosen 'Newline' option in the 'Line ending tab' and then you have entered a character/digit (say 5) in the InputBox and then you have clicked on the Send button, the following events occur:

(1) The Serial Monitor sends 0x35 (the ASCII code of 5) to Arduino; after a while (about 1.04 ms at 9600 Bd), the Serial Monitor sends 0x0A (the ASCII Code of Newline) to Arduino. This clearly indicates that the Serial Monitor sends one character at a time.

(2) When 0x35 arrives at the Arduino, the MCU is interrupted and then saves the received code into a FIFO (first-in first-out) type buffer. The code 0x0A is saved in the next location of the buffer.

(3) At the Arduino/receiver side, we keep checking if one/more characters have been accumulated in the buffer by executing the following codes: (Data byte availability/data byte read/data byte process time is always faster than the data byte arrival time.)

void loop()
{
    byte n = Serial.available();   //checking if the buffer contains at least one data byte
    if(n != 0)
    {
         byte x = Serial.read();    //the buffer contains data; bring it out and save in x
         //process data byte
    }
}

(4) The 'long input_byte = Serial.parseInt();' function does the following:
Parse refers to the act of 'looking for a particular character/digit' in a flow/stream of incoming charcaters out-of-buffer; parseInt looks for integers ( 0/0x30 to 9/0x39). The function terminates when it encounters a non-integer/non-digit like 0x0A (code of Newline) and returns a valid integer. Observe that the code 0x0A remains in the buffer.

If the function encounters 0x0A (any non-digit) before finding any 'codes for digits' or 'no codes' within 1-sec time (default timeout period), the function terminates and returns 0.

(5) The example codes with Serial.parseInt() function:

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

void loop()
{
  byte n = Serial.available();
  if(n !=0)
  {
    long input_byte = Serial.parseInt();
    Serial.println(input_byte);
  }
}

SerialMonitor.png

Don't know if this helps, but if you need to wait for something, I love using this:

while(!Serial.available()){
;// stall waiting
}

:slight_smile:

If the goal is to totally lick up the Arduino and make it impossible for it to respond to anything else then I guess that helps.

My Arduinos* are running motors and handling inputs on 5 other Serial ports so they can't afford to wait for a person to push a button. If an input from a person does arrive, it can be dealt with in a few microseconds and the Arduino can go back to doing its real job.

*Actually I mostly use Teensys with the Arduino IDE.