Go Down

Topic: Why is Serial.flush() not waiting? (Read 74 times) previous topic - next topic

obskyr

Feb 24, 2019, 07:29 pm Last Edit: Feb 24, 2019, 07:38 pm by obskyr
According to the documentation, Serial.flush() is supposed to block until the outgoing serial buffer is empty. I've checked the source code, and that does indeed seem to be the case there, too. I take this to mean that, when connected to a PC via USB, the Arduino will wait until the PC's read what the Arduino's written.

However, consider the following example - it prints the numbers 0 through 9, and is supposed to wait until the PC's read each one before printing the next:

Arduino:
Code: [Select]
void setup()
{
    pinMode(LED_BUILTIN, OUTPUT);
    Serial.begin(9600);
}

void loop()
{
    if (Serial.available()) {
        while (Serial.available()) {Serial.read();}

        for (int i = 0; i < 10; i++) {
            digitalWrite(LED_BUILTIN, HIGH);
            delay(100);
            digitalWrite(LED_BUILTIN, LOW);
            Serial.println(i);
            Serial.flush();
        }
    }
}


Python code to run on the PC (requires pySerial; pip install pyserial):
Code: [Select]
import time
import serial

PORT = 'COM5' # Change to whatever port your Arduino is on.

with serial.Serial(PORT, 9600, timeout=1) as ser:
    time.sleep(2.5) # To accommodate DTR reset.
    ser.write(b'x')
    for i in range(10):
        print("Received: \"{}\"".format(ser.readline().decode('ASCII').strip()))
        time.sleep(0.5)


With the time.sleep(0.5) in the Python code there, you'd expect the LED to blink once every 0.5 seconds, in time with the script reading the lines. However, what actually happens is that the Arduino just prints all the lines at once, the LED blinking rapidly as soon as you start the script! Serial.flush() doesn't block at all! What's wrong here?

I'm using a CH340 Arduino Nano clone, if that makes a difference.

Juraj

#1
Feb 24, 2019, 08:14 pm Last Edit: Feb 24, 2019, 08:25 pm by Juraj
flush() waits until data are sent (not until they are received). it is ready as soon the TX buffer of the MCU is empty. it sends data to the CH340. there is no acknowledgment.

the purpose of flush is for buffered streams which send data not byte by byte, but after the buffer is full. we call flush() to tell "we have no more data, save/send the buffer even it is not full"


Go Up