Arduino-1.0 Serial.flush()

Soooo,

Serial.flush()

As detailed in the Arduino 1.0 release notes;

  • Serial transmission is now asynchronous - that is, calls to
    Serial.print(), etc. add data to an outgoing buffer which is transmitted
    in the background. Also, the Serial.flush() command has been repurposed
    ** to wait for outgoing data to be transmitted, rather than dropping**
    ** received incoming data.**

This seems really dumb. If one were to make a new function, IT SHOULD HAVE A DIFFERENT NAME! why sacrifice this existing function, to add another one? It's basically ridiculous this change got passed.

It would be of no consequence to have this new function called something like Serial.WaitForTx();

It's simple to resolve this with the standard API calls but here is a slow and dirty method, and frankly unreliable because you can get stuck here!

while(Serial.available()>0)
{
Serial.read();
}

Or, for those of you a little more enthusiastic, you can modify the Arduino source back to how it used to be!
Open
\arduino-1.0\hardware\arduino\cores\arduino

Add this to HardwareSerial.h within the class definition
virtual void Iflush(void);

Add this to function to HardwareSerial.cpp in the body
void HardwareSerial::Iflush()
{
_rx_buffer->head = _rx_buffer->tail;
}

Save files and recompile - you can now use Iflush in place of what used to be flush.
Tested and working fine.

I partially agree that re-purposing Serial.flush() was a bad idea. But, it was frequently misused.

I also disagree with this:

and frankly unreliable because you can get stuck here!

How? If there is serial data to read, it is read and discarded. If there is no serial data, there is nothing to do, so the while loop doesn't get executed. How can you possibly get stuck? Neither Serial.available() or Serial.read() are blocking functions.

If there is no serial data, there is nothing to do, so the while loop doesn't get executed. How can you possibly get stuck? Neither Serial.available() or Serial.read() are blocking functions.

Noted. You are right. But that bit of code is still a crummy solution.

But that bit of code is still a crummy solution.

Not an ideal solution, perhaps. but I don't think it's all that bad.

First, the buffer size if only 128 bytes. It wouldn't take that long to read and discard the entire buffer.

Second, there are very few legitimate uses of the flush function. Throwing away random amounts of unread data is hardly ever a good idea. At least with that code, you could compare the character read to some start- or end-of-packet marker, and stop throwing the characters away when you got back in sync, after encountering a bad packet.

First, the buffer size if only 128 bytes. It wouldn't take that long to read and discard the entire buffer.

It's just poor design to let it be done this way. Ultimately, it's these kind of compromises that will make Arduino get even slower than it already is.
Don't get me wrong, I <3 Arduino. :grin: :grin: :grin:

Second, there are very few legitimate uses of the flush function.

At a user sketch level its totally valid. If you have a particularly verbose module, it can be constant spewing stuff into the serial port. If you are only interested in query-response, then you would want to be able to flush the serial buffer.

sleahey:
It's just poor design to let it be done this way. Ultimately, it's these kind of compromises that will make Arduino get even slower than it already is.

I completely fail to see how this change makes anything slower.

sleahey:

Second, there are very few legitimate uses of the flush function.

At a user sketch level its totally valid. If you have a particularly verbose module, it can be constant spewing stuff into the serial port. If you are only interested in query-response, then you would want to be able to flush the serial buffer.

You say it is valid and then propose a completely invalid situation. If you really feel the need to flush the serial buffer so that you only see the "response" you are interested in, you have to write your own flush method anyway. You would need to flush everything except for tokens that you want to see.

If on the other hand you want to just dump whatever is in the Serial Receive buffer, a simple for loop will do that. Re-purposing flush to the transmit makes sense now that the transmit buffer is asynchronous.

I completely fail to see how this change makes anything slower.

this
_rx_buffer->head = _rx_buffer->tail;
takes just a couple of cycles (or less)

this however
while(Serial.available()>0){Serial.read();}
Could take upto (n? cycles) x (the size of the buffer)

Its slow in the context that accomplishing something very simple, as a user takes more cycles now, depending on how full the buffer is, than it did before.

You say it is valid and then propose a completely invalid situation. If you really feel the need to flush the serial buffer so that you only see the "response" you are interested in, you have to write your own flush method anyway. You would need to flush everything except for tokens that you want to see.

How is it invalid? what rubbish. IMO, it's totally valid. I can point you at a whole hand full of modules that fill the serial buffer with unnecessary information that you either have to parse, or dump. Just dumping it is totally valid!

If on the other hand you want to just dump whatever is in the Serial Receive buffer, a simple for loop will do that.

SLOW.

Re-purposing flush to the transmit makes sense now that the transmit buffer is asynchronous.

Maybe to you, and other participants at a developer level - but that's also not likely the majority of users out there....

Arduino is mean't to be eeeeasy for the users.
This change has also perhaps gone and broken a whole bunch of libraries...

This Improvement comes at the sacrifice of something else completely unnecessarily!

And on this, it would seem there was no discussion on this topic in the google code project

See here
http://code.google.com/p/arduino/issues/detail?id=593&can=1&q=serial.flush

and here
http://code.google.com/p/arduino/issues/detail?id=497&can=1&q=flush

Poll time.

I developed modbus master and slave libraries called SimpleModbus that works flawlessly with V0022 but know it doesn't. I monitored the port to see what's happening and the message is being truncated. I have a suspicion that it's the flush() method messing about.
In general many request/response protocols require the ability to flush the incoming receive buffer if a bad frame is detected.

There are probably ways around this so I will investigate and test as I go along. Maybe it's not worth to change the flush() method to avoid a break in compatibility.

In general many request/response protocols require the ability to flush the incoming receive buffer if a bad frame is detected.

Please explain how throwing away random amounts of unread data will accomplish anything.

Certain values in a request frame are read as they come in. E.g. modbus states the first byte is the ID byte, all the slaves read the same data and respond if the ID matches, if not the frame is discarded without even looking at the next byte. This is true for many multi-drop master/slave protocols.

The thing is I'm not quite sure what the Arduino team has done with the flush() method with regards to the async transmission. I need explicit control on the timing when transmitting characters/frames.

It is bad design to use the same function name for a new function. Flush() should have been deprecated and a new function added. How do we manage legacy code if this practice persists.

These hypothetical situations might be valid for an in-buffer flush:

  1. you have a modified serial bus with some id in the beginning of a package like mentioned before, you want to talk with the next ID and do a flush before you switch to the next ID just in case?!
  2. something on your modified serial bus is misbehaving and spews junk. You pull its reset and flush the in-buffer and give it another try after restart or just move on to another ID?!
  3. some synchronous communications only happen say once a second with a package over serial. You read one of them and it's bad/not useful from reading the first few bytes, so you flush the rest and wait for the next package, assuming nothing happens between two timed packages?!
  4. you have a talk only device on a modified bus and it keeps talking. Now you're done with it and pull its reset, flush the in-buffer, move on to another device that might or might not be talk only?!

You are a newbie so you do not want to program the whole protocol in your first sketch.
Therefore you only read the first chars(s) and flush the rest. because you know david will only send new data after you send a message.
This is what the david people advice to do.
Best regards
Jantje

ps david is a laser scanning system. more at http://www.david-laserscanner.com