Poll
Question: Should there be an equivalent flush(forRx) function with the same behaviour as in Arduino-023 and prior?
Yes - Give me back a flush function for the receive buffer!
No - I like the Arduino-1.0 flush just how it is!
I don't think this topic even matters!

Pages: [1]   Go Down
Author Topic: Arduino-1.0 Serial.flush()  (Read 4084 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 15
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 631
Posts: 50163
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

I also disagree with this:
Quote
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.

Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 15
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 631
Posts: 50163
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 15
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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. smiley-mr-green smiley-mr-green smiley-mr-green

Quote
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.
Logged

Fort Lauderdale, FL
Offline Offline
Faraday Member
**
Karma: 71
Posts: 6144
Baldengineer
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Quote
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.
Logged

Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.c

0
Offline Offline
Newbie
*
Karma: 0
Posts: 15
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.

Quote
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!

Quote
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.

Quote
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!

Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 15
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

South Africa
Offline Offline
Full Member
***
Karma: 9
Posts: 108
if (num1 = num2) {A big mistake!} else {This will never work!}
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 631
Posts: 50163
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.
Logged

South Africa
Offline Offline
Full Member
***
Karma: 9
Posts: 108
if (num1 = num2) {A big mistake!} else {This will never work!}
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Central MN, USA
Online Online
Tesla Member
***
Karma: 74
Posts: 7251
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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?!
Logged


Belgium
Offline Offline
Edison Member
*
Karma: 68
Posts: 1925
Arduino rocks; but with my plugin it can fly rocking the world ;-)
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Do not PM me a question unless you are prepared to pay for consultancy.
Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

Pages: [1]   Go Up
Jump to: