In the Arduino library, the Serial object has a method called “flush().”  Often users go throwing it into programs without fully understanding what it does. It doesn’t help that it’s functionality changed when version 1.0 of the Arduino IDE was released. Does Serial.flush() affect the Transmit Buffer or the Receive Buffer and when do you need to use it?

What does Serial.flush() do?

From the Arduino reference for Serial.flush (found on this page):
Waits for the transmission of outgoing serial data to complete.
The key to that statement is “outgoing”.   Serial.flush() doesn’t empty the “incoming” buffer as many people think.  It pauses your program while the transmit buffer is flushed.

Serial.print() / Transmits Are Interrupt Based

Something you may not realize is that when you issue a Serial.print(), that function returns almost immediately.  Instead of waiting until the string has been transmitted, print() sets up a buffer for the string, and then is transmitted via interrupts one character at a time.  This method allows your program to keep running, with the transmitting happening in the background. A simple way to see this behavior is to send long sentences and time them,  like in the next section.

The difference between flush() and no flush()

Borrowing code from the millis() as a stopwatch example, we can see the difference between using flush() or not using flush() when sending data over Serial.

The Code Without a Flush


void setup() {
  // Give some time to open serial monitor after programming
  delay(2500);
  Serial.begin(9600);

  // Store the current time (start the clock)
  unsigned long millisNoFlushStart = millis();
  // Transmit some psuedo-random text
  Serial.println(F("How long will it take to transmit the following:"));
  Serial.println(F("abcdefghijklmnopqrstuvwxyz"));
  Serial.println(F("done"));
  // Store the current time (stop the clock)
  unsigned long millisNoFlushStop = millis();
  Serial.print(F("Without flush, Serial.println()s return control in: "));
  Serial.print( millisNoFlushStop - millisNoFlushStart);
  Serial.println(F(" milliseconds."));
}
void loop() {}

Results

So this code is “done” in 20 milliseconds.  This sounds pretty good, right?  Okay, let’s look what happens if you call Serial.flush() before counting the time.

The Code WITH a Serial.flush()


void setup() {
  // Give some time to open serial monitor after programming
  delay(2500);
  Serial.begin(9600);

  // Store the current time (start the clock)
  unsigned long millisWithFlushStart = millis();
  // Transmit the same psuedo-random text as before
  Serial.println(F("How long will it take to transmit the following:"));
  Serial.println(F("abcdefghijklmnopqrstuvwxyz"));
  Serial.println(F("done"));
  // This time, let TX buffer flush before "stopping" the clock
  Serial.flush();
  // Store the current time (stop the clock)
  unsigned long millisWithFlushStop = millis();

  // Print results for flushed calls
  Serial.print(F("WITH flush, Serial.println()s return control in: "));
  Serial.print( millisWithFlushStop - millisWithFlushStart);
  Serial.println(F(" milliseconds."));
}

void loop() {
}

Results

Just by adding a Serial.flush() line, now the same code takes almost 90 milliseconds to complete!  That’s 4.5 times longer.  This difference in time may not be an issue or a problem.  However, it is a behavior to understand.  If you want your code to wait for a serial string to be finished sending, you need to make use of Serial.flush().

How do you clear the incoming Serial buffer?

Since the flush() method only clears the transmit buffer, how do you empty the receive (or incoming) buffer?  This code will do it, which you can put into a function like “flushReceive()” or something equally amusing.

  while(Serial.available())
    Serial.read();

Conclusion

For most programs, the transmit buffer is a good thing.  It’ll keep your Arduino from getting tied up waiting for Serial transfers to finish.  However, if you have critical timing mixed in with Serial.print()s, you need to keep in mind that your timing might change.  That’s where the Serial.flush() comes into play.  It gives you a chance to wait until all Serial.print()ing is done.
Author

Fan of making things beep, blink and fly. Created AddOhms. Stream on Twitch. Video Host on element14 Presents and writing for Hackster.IO. Call sign KN6FGY.

47 Comments

  1. An unorthodox method to clear (instantly!) incoming serial buffer is to disable receiver by clearing RXENn bit of UCSRnB register; where n is Serial id
    eg. bitClear(UCSR0B, RXEN0);
    enable it back… et voila!
    You win time; you loose safety

  2. So serial.print() followed by serial.flush() cause some delay. can we control this delay by serial.setTimeOut(). Because I have a watchdog timer, and I dont want this delay to trigger the watchdog timer. thanks

      • Thank you sir. Now I understand that serial.settimeout works with reading and parsing the incoming data and nothing to do with serial.flush. Also you gave me the idea of calculating the flush duration. My watchdog timer chip has the time out period of 1600ms. So I am safe.

  3. Goran Grubić Reply

    The article discusses print(), without mentioning write() — this leaves few questions in fog: is described output buffering feature related to print() only (and not write() ) or author mentions print() only, assuming that great majority of prefers print() over write()? It would be good to provide clarification on this.

  4. Vipul swamy ballupet Reply

    Hi Mr.Lewis, Great Information But how do I make my BT Master and slave communication effective,like soft real time. Thanks from germany – Vipul

    • Vipul swamy ballupet Reply

      I mean to say how can one handle such an issue when it comes to communicating with a Bluetooth module. I am currently trying to communicate between 2 hc-05 bluetooth modules, and there a lot of time lag.

  5. I think it is important to stress that flush() means the content of the stream is transferred to the stream output until the stream is empty. It is not about clearing or getting rid of. It is just to force the accumulated data in the stream to move on to the output.

  6. Great stuff James, found this discussion while looking for solutions to a problem I am having using Serial.print.

    I am using Serial.println to debug some simple code:
    [arduino firstline=”1″]
    digitalWrite(redpin, HIGH); // set the red LED on
    Serial.println("Red");
    delay(1000);
    [/arduino]
    But, if I put in three sets of this sequence as in driving three different LEDs, it will not compile (Verify). I get this error –

    Arduino: 1.6.8 (Windows XP), Board: “Arduino Nano, ATmega328”
    (lotta other stuff in here…..)
    collect2.exe: error: ld returned 5 exit status

    exit status 1
    Error compiling for board Arduino Nano.

    If I comment out any one of the Serial.println lines it compiles fine.
    Any suggestion on what I am doing wrong??

    • Code snippets rarely contain the error. This is an example of such a situation. Post your entire code, or the entire code that causes the problem.

      • This is the whole sketch.
        [arduino firstline=”1″]
        const int redpin=11;
        const int bluepin=10;
        const int greenpin=9;
        void setup() {
        // initialize the digital pin as an output.
        // Pin 13 has an LED connected on most Arduino boards:
        pinMode(greenpin, OUTPUT);
        pinMode(bluepin, OUTPUT);
        pinMode(redpin, OUTPUT);
        Serial.begin(9600);
        }

        void loop() {
        digitalWrite(greenpin, LOW);
        digitalWrite(bluepin, LOW);
        digitalWrite(redpin, HIGH); // set the red LED on
        Serial.println("Red");
        delay(1000); // wait for a second
        digitalWrite(greenpin, LOW);
        digitalWrite(bluepin, LOW);
        digitalWrite(redpin, LOW); // set the LED off
        delay(1000); // wait for a second
        digitalWrite(greenpin, LOW);
        digitalWrite(bluepin, HIGH); // set the blue LED on
        digitalWrite(redpin, LOW);
        Serial.println("Blue");

        delay(1000); // wait for a second

        digitalWrite(greenpin, LOW);
        digitalWrite(bluepin, LOW); // set the LED off
        digitalWrite(redpin, LOW);
        delay(1000); // wait for a half second

        digitalWrite(greenpin, HIGH); // set the green LED on
        digitalWrite(bluepin, LOW);
        digitalWrite(redpin, LOW);
        Serial.println("Green LED is on.");
        delay(1000); // wait for a second
        digitalWrite(greenpin, LOW); // set the LED off
        digitalWrite(bluepin, LOW);
        digitalWrite(redpin, LOW);
        delay(1000); // wait for a second
        }
        [/arduino]

        • I don’t see any issues and it compiles fine for me. It is possible there is a stray non-visible character somewhere throwing off the compiler (well actually the linker). It is more likely something is wrong with your install. I would try re-installing the IDE. Maybe even try a version older just to see if anything changes.

          • Thanks for your help James. I will try your suggestions and will report back what I find. I have done quite a bit of cut and paste from other sketches I have built, so some stray characters may have crept in.

            Wes

          • Sketch compiled fine in 1.0.6. I uninstalled and then re-installed 1.6.8, still no joy. Installed latest version 1.8.4 and it compiled the sketch just fine. Machine is WXPSP3, so kinda old. But, I am now back on track. At least for now. Thanks James, as always, a big help.

            Wes

  7. Hi
    Greetings!
    The code:
    while (Serial.available())
    Serial.read();

    is also not working as in case of blinking of a Led when we give a bunch of strings it displays invalid for a no. of times.
    Kindly help me with the alternative code to flush the values.

    Thanks in advance

  8. hi
    i have a serial communication ,i should catch 32 bit from my hall encoder, i use if(serial.available()>=4);
    the arduino(mega 2560) wait for it till catch all data and then the main loop take a long time to run(20 times in each sec.), i need it to be faster than it !! any suggestions??!!
    TNX

  9. Hi James,

    Brilliant website! Has been massively helpful in getting me up to speed with my Arduino projects. However, I have one major issue with my work that I’m wondering if you can help me to understand. Every time I re-upload a new sketch to the Arduino I get a load of garbage in the transmit buffer. I’ve tried using the Serial.flush() statement in my setup loop (with a view to clearing it the first time it runs.) As a double measure I’m also reading the serial bus on my bluetooth receiving device (mobile) and clearing the serial buffer read string to = “” (on screen initialization)…. but whenever I open my app and connect for the first time after a new sketch is uploaded the same thing happens. Typically it crashes the app with a series of dingbat type symbols… but next time I reopen the app it runs fine.

    Any tips for which device needs to be instructed to clear, and how best to achieve this. I’ve tried putting flushes and clear read buffer at all points in my program but nothing seems to work. Seems really odd – almost like the bluetooth module holds data in between.

    • If you’re having hang-ups or other issues it isn’t because of the strange characters in the buffer. The strange characters are a symptom of whatever the actual problem is.

      The Bluetooth module probably has its own buffer (and so does the PC). Don’t connect your PC (Arduino’s USB Port) and Bluetooth module to the same Serial pins.

      In UART/serial communications, there is almost never any time you need to empty a buffer. Either side’s software should be able to handle any data it receives. In fact, the primary reason for the Serial.flush() isn’t to empty the buffer but to let you know that all characters have been transmitted. (Which is why its behavior changed in Arduinio 1.0.There is almost never a good reason to “empty” the receive buffer either.)

      You have another issue with your setup, it isn’t because of extra characters. Could be a wiring, power, or software issue.

    • Long posts automatically go into the spam queue. You posted at 9:28pm server time and your very kind follow-up occured at 6:13am. Sorry. I usually sleep for 8 hours.

  10. I have a very interesting problem for you i wonder if you might like put some light on the subject I’m using a HC05 blue-tooth module using the software serial calls on an Arduino UNO and I have found something quite strange with this Ive written the application for my mobile in android and a simple application for the Arduino It works fine connects at 9600 baud and uses default settings for stop bits etc

    I am simply turning on and off an led via the ports of the Arduino on receiving correct commands via bluetooth TX and RX

    Here is the problem Its a very perplexing but interesting problem and suggest that there is either a bug in the hardware itself or the initial serial routines haven’t been set properly

    I can obviously use both hardware ports and a virtual software port at the same time also works but there is a big huge question mark over this

    The only time the software or hardware serial port will respond to the blue tooth module is if I send a character doesn’t matter what character to the hardware port first There after this all works A ok responds to bluet-tooth data transfers and activates the LED

    What could I be doing wrong do you think

    Ive got past the problem , however Im not saying to much about the solution because in my mind I shouldn’t have to do this but i have to use additional components to solve the problem I just would like to know what you think about this and why the atmel 323p or arduino uno does this

  11. Very useful. I had problems when sending dsta over serial Bluetooth hc06. Sometimes string arrives splitted. Will try this. Thanks.

  12. Hi,
    I found this article very useful in trying to debug the serial communication to create a constant transfer per second. Unfortunately, it still creates a periodic burst of different transfers. Using the very basic code:

    void setup () {Serial.begin(9600); }
    void main () { Serial.println(“00000”); }

    sends most of the data thru at 137 lines per second. About 6% of the time (not an insignificant number when trying to collect specifically timed data) the data transmits at 141 or 142 sets of “00000” per second, which is 35 characters more per second.

    I added Serial.flush(); after the println, hoping that would make things stable, but now it seems that every 25 seconds there is a drop in the transfer down to 133 lines (sets of “00000”) per second.

    I’m using a python script to read the serial and write to a file, so i’m at a loss to understand if it is the python script or the Arduino serial.

    Considering the problem went from excess data without the flush to “missing” data with the flush, it would seem that the Arduino would be the likely cause.

    Any suggestions?
    thanks

    • The Arduino is a real-time system and is not likely the issue of the bursting, on its own. The issue is either a) your Arduino code or b) something on the PC side (the driver, the OS, the language’s stack, etc… way more things to go “wrong.”).

      Serial.flush() changing the behavior suggests whatever else the rest of your Arduino code is doing, isn’t allowing the Serial’s transmit buffer to “stay full.” I’d look closer at what the rest of your code is doing and make sure it isn’t either blocking events filling the transmit buffer OR that it isn’t filling so quickly that the ISR sending serial characters is pausing.

      Running 9600 baud with “carefully timed data” seems strange to me. I’d be running 56700 or 115200.

      • Thanks for the detailed reply.

        The intent of the experiment was to determine if Arduino serial communication could be used, reliably, to collect timed sample data vs buying an expensive DAQ system. The 2 line code above is the complete code. I made sure to strip everything else out just to monitor the data streaming.

        9600 was used to get a baseline, and if 9600 has timing issues then it follows that any higher bitrate also has timing issues to varying degrees.

        Other suggested solutions to the timing problem were to add a timestamp to the serial output to mark when the data was taken, using millis() for example, vs when the data was received in the data file, trying to eliminate any bottlenecks. That solution works pretty well up to a point, until the length of runtime makes millis() a very long number (greater than 3 hours, for example) and then the overhead of sending time along with the data slows things down a bit.

        Ultimately, the fact that getting from the Arduino to an external data file has variable time steps eliminates it from heavy duty data collection work for me.

        thanks for you answer though.

        • You misunderstand my comment about going faster than 9600. It isn’t a “timing issue.” It’s math. You may be putting more data into the buffer than 9600 can transmit. When the transmit buffer is full, Serial.print() will pause until the entire string passed to it can be placed into the transmit buffer. While I would expect that to mean your Arduino continue to stream without interruption, it could give unpredictable results depending on what the rest of your code does. So in that case either fill the buffer slower or transmit the data faster. Or secret option #3, don’t send ASCII data use Serial.write() and send binary data instead.

          All that said, the Arduino isn’t going to be the issue. PC operating systems seem to buffer Serial Data / Virtual COM Ports, making them difficult to use for a real-time application without timestamps.

          To get around your sending millis() as a timestamp you have two options: 1) Pad the string so the amount of data sent is always the same (like with sprintf()) or 2) Use Grey Code and only send difference between stamps (that’s how logic analyzers usually stamp their data.)

  13. Thanks. This is really informative. I am using an Arduino Uno with a HC-06 to send the times at which a simple switch is pressed to my PC. Works fine except there are delays in receiving the data sometimes lasting 10 ore more seconds and then it starts flowing again. The data will be received fine with no delay between switch change and data arriving at the PC but then data will stop halfway through a data string, seemingly frozen for 3-12 seconds, and then in a burst the rest of the data comes through?

    The problem does not occur when I send data over the USB port – only for Bluetooth.

    Does the HC-06 have a buffer? Is there anyway to force it to continue to transmit?
    Thanks

    • It could be the PC’s Bluetooth driver is buffering it, could be a bluetooth connectivity issue, or it could be the module itself. I have no experience with them, so I have no idea.

  14. The Code for clearing the Input Buffer is wrong as a lot of copies in the Net. Arduino is way faster than the data arrives. So Serial.available() could be < 1 before all data is there and the while loop is finished before.
    I wonder why such a fail is widespreaded in the net.

    • No, the code for clearing the buffer is 100% correct. Your understanding of when to use it is wrong (which limits the fail to a single person.). How do you know when “all the data is there”? Unless your byte-level protocol has a method for identifying when a transmission is complete, you will never know when “all the data is there.” Clearing the input buffer does just that, empties whatever data is in the buffer at the time the while-loop runs.

      • But that is not that what most users want. If I broadcast some Data and all Clients but one should discard the data then this code won’t work. It has absolutely no use then. When should I use your code? The same wrong assumption is the while (available > 0) { read }. If there is no data and it will be, than the loop will end before all data ist there. My solution for this is to send the first Byte with the number of all next bytes. The only way for me not to send the data as a char string and to spare bytes which are used for comma separation.

        • Serial in Arduino projects is usually a peer to peer communication. You’re over complicating a simple request people have. While you probably make valid points for your corner case, they don’t apply here.

  15. I think the “how do you clear the output buffer” at the end needs to be “how do you clear the input buffer”.

  16. Hi,

    When using HC-05 and a bluetooth App to transmit a string like “hello” to an Arduino, I get the reading as * 12|99|99|hello#

    Any reason why I am getting those initial values before the string hello? How is this extra values getting into the buffer?

    The code is

    while (Serial.available()) {

    char inChar = Serial.read();

    inputString += inChar;

    }

    Serial.println (inputString);
    inputString=””;

      • David Watson Reply

        I always liked the expression;

        “Standards are wonderful, there are so many to choose from.”

        If you’re doing a straight serial read, then you’re also reading the header and trying to print meaningless (to us) data.

        If you expect the header data to be stripped off by the H/W, make sure you have compatible devices or do it yourself in S/W. There’s ACL, SCO, LMP, HCI, SDP, SMP and a whole bunch of other TLAs that packetize the data you’re transmitting that, under normal circumstances, we never see. If you examine the ISO/OSI stack, serial.read deals with the physical and data link layers while bluetooth rides up a couple of layers higher.

    • Abdie Tabrizi Reply

      Hi, please move inputString=””; before while(….). InputString needs to be initialized in order your += expression to work. Otherwise the system is picking up some garbage for the initial value of the inputString.

  17. How big is the buffer? If you are not connected to a serial device and the code is pumping out text into the buffer what happens if you never connect back up?

    • Serial UARTs are asynchronous. The transmitting side does not wait for the receiving side to acknowledge a bit or byte has been received. I don’t remember the size of the buffer, but it is probably on the order of 64 or 128 bytes. However, the time it takes to empty that buffer will be constant only limited by the baud rate used.

Write A Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.