1

What's the low level difference between if(Serial.available() > 0) and while(Serial.available() > 0)? On what conditions would you choose one over the other?

I was testing my codes on 4 daisy chained 74HC595 shift registers controlling multiple LEDs. The code takes in a number from the serial monitor and displays it out in binary via the LEDs. Here is the code below that worked:

#define latchPin 8  //ST_CP pin of 74HC595
#define clockPin 9  //SH_CP pin of 74HC595
#define dataPin 7   //DS pin of 74HC595

//number of 74HC595 in daisy chain
#define numOfDaisyChainReg 4

byte registerVal[numOfDaisyChainReg];

void setup() {
    Serial.begin(115200);
    pinMode(latchPin, OUTPUT);
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, OUTPUT);
}

void loop() {

  while (Serial.available() > 0) {
    
    uint32_t num = Serial.parseInt();
    Serial.print(num, DEC);
    Serial.print(" : ");
    Serial.println(num, BIN);

    //breaks the recieved int into 4 unsigned bytes
    //and assigns the byte value into the "registerVal" array
    for (uint8_t a = 0; a < numOfDaisyChainReg; a++) {
      registerVal[a] = (num >> (numOfDaisyChainReg - (a + 1)) * 8) & 0xFF;
      Serial.print("registerVal["); Serial.print(a); Serial.print("] = ");
      Serial.println(registerVal[a], BIN);
    }

    //writes the 4 bytes into the shift register
    digitalWrite(latchPin, LOW);
    for (uint8_t x = 0; x < numOfDaisyChainReg; x++) {
      shiftOut(dataPin, clockPin, MSBFIRST, registerVal[x]);
    }
    digitalWrite(latchPin, HIGH);
    
  }
    
}

Originally, I had if(Serial.available() > 0) and that didn't work as no LEDs lit up despite everything else in the code working as it was expected. Switching to while(Serial.available() > 0) solved that problem. Anyone have any idea why that's the case?

10
  • Turn up the warning level in File/Preferences with regard to while(Serial.available) without () , as in .available().
    – timemage
    Apr 21 at 0:56
  • despite everything else in the code working as it was expected ... that may not be true
    – jsotola
    Apr 21 at 1:20
  • think of a sink full of dirty dishes .... if (dirtyDish.available > 0) {washDishOrNot()} , lets you go to sink, maybe wash a dish or a few, and go play ...... while (dirtyDish.available > 0) {washDishOrNot()} would have you stuck at the sink until there were no dirty dishes, or until you used an emergency escape
    – jsotola
    Apr 21 at 1:27
  • 1
  • 1
    @jsotola. Thanks! It was an interesting read. I'll implement it into my code for testing :)
    – Kuan
    Apr 21 at 2:35
2

I figured out why while(Serial.available()>0) and if(Serial.available() > 0) would or would NOT work in terms of my shift register code. It has to do with the serial monitor line feed and carriage return setting! If it isn't set to no line ending, it will either not register the input number or reset it back to zero right after the input is read. Learned to always check the line return option in the serial monitor! With this solved, the original question is nothing more than a general if vs while statement; which I already know the answer.

Thanks to everyone who contributed to this question! It did help me understand a lot more about Serial.available() in general. @jsotola gave a really good article. Combined with this YouTube video, it makes a lot more sense now.

0

Some implementations of the Arduino core have features that need loop() to exit regularly. Although it's not often used, the serialEvent() is an example of one such thing, at least in the AVR Arduino core.

The ESP8266 Arduino core appears to do some task scheduling when loop() exits, among other things.

For your particular use case, it may make no difference at all, probably doesn't. It may not even generate different code once compiled. If you were doing something where you could not afford to exit loop(), run other stuff and re-enter loop() to run your code for a second pass, then there might be a performance reason to use your own while loop inside loop(). In your code as it currently is, the eventual blocking on Serial writes will end up limiting the execution to the same speed.

3
  • I'm a bit confused here. So you're saying there is a chance loop() function exiting/ending and that might break the code if using the if(Serial.available())?
    – Kuan
    Apr 21 at 1:51
  • I'm not sure I understand your question, and it seems like I should if the answer to it were anything other than "no, that wasn't what I was saying." Since replacing the while in your code with an if results in loop() exiting more frequently, since that is the difference, and you asked "On what conditions would you choose one over the other?", that is what I addressed. It's the best interpretation of your question that I could come up with.
    – timemage
    Apr 21 at 2:06
  • Okay I get it now. Seems to me that the if statements doesn't behave as I'd expect it to when it's paired with the Serial.available(). It might exit pre-maturely.
    – Kuan
    Apr 21 at 2:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.