You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As explained in http://arduino.cc/en/Reference/StreamAvailable#.UyDJNvFl7PE
available tells how much data is available for receiving in the stream.
There is however no method how much is available or waiting for sending.
This lack makes it impossible for a sketch to be smart about what it sends.
Hi Paul thanks for agreeing on the concern.
Personally I think "availlable" and "ready" are to common and do not specify about which queue ( send queue or receive queue) we are talking.
I modified my code so that available takes a boolean which specifies the queue and which defaults to rx.
However I don't like that as well because it is another parameter which increases program size and it hardly makes things clearer.
I now think of adding 2 methods
availableInSendQueue and availableInReceiveQue (the best I could think of right now). Available like in "How much data is available."
Making available inline non virtual method implemented as { return availableInReceiveQue();} should make for a "hardly no impact at all solution".
Some more background why I need this (and this would be the perfect time for the Arudino core team to make me do the work ;-) )
I log data every x millis in the loop for logging and running my web site to control arduino. I'm talking about debugging so there is quite some data (800+characters per log)
I need to log in 1 go because otherwise I get inconsistent data.
If I use 9600BAUD it takes about 1ms per character to send. With a buffer of maximum 255 (due to uint8_t) it takes at least (800-255=545) ms for sending the data. Which is about half a second my robot is not responding (completely unacceptable for a robot).
Currently I can not check whether the buffer is empty so I may have 800ms unresponsiveness.
Because the logging itself (without the actual write) takes about 55ms that makes a total of 855ms.
I could increase the BAUD rate but unfortunately I have not been able to get "100% reliable communication" yet at higher Baud rates.
But if I can not test the transmission buffer and I have 10 times better transmission it will still take 55ms for processing and 80ms transmission totalling 135ms which is still to much for me as I prefer to log every second.
I have implemented the previous solution and I didn't like it (again :-( )
I'm now pretty pleased with this code (in stream)
virtual int available()=0 ;
int availableInReceiveQue(){ return available();};
virtual int availableInSendQueue() {return -1;};
this is 100% compatible with existing libraries and sketches and allows for extension of availableInSendQueue() with a consistent naming.
I'm still doubting whether availableInReceiveQue() should be virtual or not. I prefer it virtual but there is a program and memory size impact.
my hardware serial class definition looks like
virtual int available();
virtual int availableInSendQueue();
It is a duplicate but if you only fi it in hardware serial the fix of the duplicate is not good enough for me. @PaulStoffregen
Please look at the code I came up with and posted above. It handles nearly all concerns posted on the developers list.
It is backwards compatible, allows for the symmetric names for tx and rx and by using -1 as default return value one can test whether the available for tx is implemented.
It only needs a mod in stream and hardware serial.
I like this solution better than any of the other solutions I've seen so far and MUCH
better than having available() in Stream and then a proprietary writeBufferFree() function that may or may not exist down in a library.
It offers consistency and backward compatibility since all the new code will use
availableInReceiveQue()
and
availableInSendQueue()
@jantje
is there a reason to put availableInSendQueue() in Stream instead of Print?
The write method is defined in Print so I'm expecting to find the corresponding availableInSendQueue() there too.
This question was also asked by matthijskooijman in #1408
I have no objections in putting the method in Print. However the most logical name to me in that case would be availableInWriteQueue()
In that case I would rename availableInReceiveQue to availableInReadQue
I'm picky on naming but as I'm not responsible for the naming I'm not going to make a fuss of it.
This question was also asked by matthijskooijman in #1408
I have no objections in putting the method in Print
Oh, I see, missed that, thanks.
However the most logical name to me in that case would be availableInWriteQueue()
In that case I would rename availableInReceiveQue to availableInReadQue
mmhh, may I ask why you feel the need to specify that there is a "queue"?
I mean, the original method was called available() and not availableInQueue() (the fact that there is a queue was implicit).
Now, since we are going to handle input and output, I expect that available() becomes something like availableRead()/availableWrite() or availableForRead()/availableForWrite().
This question was also asked by matthijskooijman in #1408 <https://github.com/arduino/Arduino/issues/1408>
I have no objections in putting the method in Print
Oh, I see, missed that, thanks.
However the most logical name to me in that case would be availableInWriteQueue()
In that case I would rename availableInReceiveQue to availableInReadQue
mmhh, may I ask why you feel the need to specify that there is a "queue"?
I mean, the original method was called |available()| and not |availableInQueue()| (the fact that there is a queue was implicit).
Now, since we are going to handle input and output, I expect that |available()| becomes something like |availableRead()/availableWrite()| or |availableForRead()/availableForWrite()|.
—
Reply to this email directly or view it on GitHub #1930 (comment).
I like names being consistent and to have a name that can help
portray the functionality.
I don't have particularly strong feelings on the names
but I'd pick either:
availableInReadQue()/availableInWriteQue()
or
availableForRead()/availableForWrite()
BTW, I realize this next part below is pretty far off topic for the "available" discussion,
but while we are looking at adding a new functions to the Stream/Print APIs,
flush() has somewhat similar confusing issues.
Currently flush() is in Stream and with the exception of flush() all other Stream implemented functions
are for the read direction.
Originally flush() was also for the read side which made sense because Stream only implements
read side functions. (It inherits the write side from print)
When flush changed to being on the write side, things went wonky
and we got things like HardwareSerial and SoftwareSerial implementing it on different
directions having very different functionality.
It isn't obvious from looking at the Stream header what flush() does
since there is no comment where flush() is declared in the class.
Maybe "flush" could use an update as well?
Currently, since flush() is in Stream,
there is no common way to tell a device library that uses Print but not Stream
to force buffered data to be sent to the device
without dragging in Stream which doesn't see right to me.
When might having "flush" without Stream be useful?
Say you had a graphic device like a GLCD which is output only so it only uses Print.
Maybe it does buffered writes in local memory.
flush() could be used to force the dirty local buffer to be pushed to the physical display.
I probably should start a new thread on the developers list for this,
since backward compatibility and naming
issues are just as complex and potentially contentious as with the available() functions.
Especially since there is also the throw the data away vs wait for the i/o to complete
functionality, and names like flush/purge/drain/empty have not been used consistently
across different operating systems, and APIs so it is easy to get confused by names.
I only brought it up here because, timing wise,
if there is going to be changes to Stream & Print,
it might be good to also do changes to "flush" at the same time.
And if updates to "flush" were desired,
it also might be useful to consider all the new function names of both the "available" and
the "flush" functions at the same time
to have some sort of consistency between them.
as I stated before. Available just doesn't say anything.
Finding good names is hard. In my experience longer names make less confusing code.
Rereading the above I think availableInWriteQueue() is not even 60% perfect. It can be understood as "available written data in write queue" (which is the current implementation) and as "available for adding data to write queue".
I agree that Queue is an implementation and is not a good idea to add to the name.
As to availableForRead()/availableForWrite()
availableForWrite is not compliant with the code as the code is exactly the same as the existing available. So it is more StillToWrite(). For my code that works fine as I test for StillToWrite()==0.
But due to the dubious nature of the word "available" one is fully right when disagreeing :-(
There is lots of confusion and doubt on my side. I think the word "available" is part of the problem.
What I think users want as functionality(And that Is not what I implemented) is
How much data is there for me to read.
How much room for data is there for me to write.
Note that that is a "different calculation" on a "different queue". I think this should be reflected in the names:
The best I can come up with right now is:
stillToRead()/availableForWrite()
I hope other people have better ideas.
Activity
PaulStoffregen commentedon Mar 13, 2014
Yes, I've long wanted to add Stream::ready()
jantje commentedon Mar 14, 2014
Hi Paul thanks for agreeing on the concern.
Personally I think "availlable" and "ready" are to common and do not specify about which queue ( send queue or receive queue) we are talking.
I modified my code so that available takes a boolean which specifies the queue and which defaults to rx.
However I don't like that as well because it is another parameter which increases program size and it hardly makes things clearer.
I now think of adding 2 methods
availableInSendQueue and availableInReceiveQue (the best I could think of right now). Available like in "How much data is available."
Making available inline non virtual method implemented as { return availableInReceiveQue();} should make for a "hardly no impact at all solution".
Some more background why I need this (and this would be the perfect time for the Arudino core team to make me do the work ;-) )
I log data every x millis in the loop for logging and running my web site to control arduino. I'm talking about debugging so there is quite some data (800+characters per log)
I need to log in 1 go because otherwise I get inconsistent data.
If I use 9600BAUD it takes about 1ms per character to send. With a buffer of maximum 255 (due to uint8_t) it takes at least (800-255=545) ms for sending the data. Which is about half a second my robot is not responding (completely unacceptable for a robot).
Currently I can not check whether the buffer is empty so I may have 800ms unresponsiveness.
Because the logging itself (without the actual write) takes about 55ms that makes a total of 855ms.
I could increase the BAUD rate but unfortunately I have not been able to get "100% reliable communication" yet at higher Baud rates.
But if I can not test the transmission buffer and I have 10 times better transmission it will still take 55ms for processing and 80ms transmission totalling 135ms which is still to much for me as I prefer to log every second.
jantje commentedon Mar 21, 2014
I have implemented the previous solution and I didn't like it (again :-( )
I'm now pretty pleased with this code (in stream)
this is 100% compatible with existing libraries and sketches and allows for extension of availableInSendQueue() with a consistent naming.
I'm still doubting whether availableInReceiveQue() should be virtual or not. I prefer it virtual but there is a program and memory size impact.
my hardware serial class definition looks like
and the code
I have an idea about the growth path (getting rid of available) but due to lack of interest I won't bother to explain.
jantje commentedon Jul 4, 2014
can this please be taken into consideration?
PaulStoffregen commentedon Jul 5, 2014
I believe this issue is a duplicate of #1408 and maybe #672
jantje commentedon Jul 7, 2014
It is a duplicate but if you only fi it in hardware serial the fix of the duplicate is not good enough for me.
@PaulStoffregen
Please look at the code I came up with and posted above. It handles nearly all concerns posted on the developers list.
It is backwards compatible, allows for the symmetric names for tx and rx and by using -1 as default return value one can test whether the available for tx is implemented.
It only needs a mod in stream and hardware serial.
bperrybap commentedon Jul 7, 2014
I like this solution better than any of the other solutions I've seen so far and MUCH
better than having available() in Stream and then a proprietary writeBufferFree() function that may or may not exist down in a library.
It offers consistency and backward compatibility since all the new code will use
availableInReceiveQue()
and
availableInSendQueue()
jantje commentedon Jul 8, 2014
@bperrybap
Thanks.
As you can see I use this and it is the result of many trials and errors.
cmaglie commentedon Jul 13, 2014
Really interesting!
@jantje
is there a reason to put
availableInSendQueue()
in Stream instead of Print?The
write
method is defined in Print so I'm expecting to find the correspondingavailableInSendQueue()
there too.jantje commentedon Jul 13, 2014
This question was also asked by matthijskooijman in #1408
I have no objections in putting the method in Print. However the most logical name to me in that case would be availableInWriteQueue()
In that case I would rename availableInReceiveQue to availableInReadQue
I'm picky on naming but as I'm not responsible for the naming I'm not going to make a fuss of it.
cmaglie commentedon Jul 13, 2014
Oh, I see, missed that, thanks.
mmhh, may I ask why you feel the need to specify that there is a "queue"?
I mean, the original method was called
available()
and notavailableInQueue()
(the fact that there is a queue was implicit).Now, since we are going to handle input and output, I expect that
available()
becomes something likeavailableRead()/availableWrite()
oravailableForRead()/availableForWrite()
.bperrybap commentedon Jul 13, 2014
On 07/13/2014 11:13 AM, Cristian Maglie wrote:
I like names being consistent and to have a name that can help
portray the functionality.
I don't have particularly strong feelings on the names
but I'd pick either:
availableInReadQue()/availableInWriteQue()
or
availableForRead()/availableForWrite()
BTW, I realize this next part below is pretty far off topic for the "available" discussion,
but while we are looking at adding a new functions to the Stream/Print APIs,
flush() has somewhat similar confusing issues.
Currently flush() is in Stream and with the exception of flush() all other Stream implemented functions
are for the read direction.
Originally flush() was also for the read side which made sense because Stream only implements
read side functions. (It inherits the write side from print)
When flush changed to being on the write side, things went wonky
and we got things like HardwareSerial and SoftwareSerial implementing it on different
directions having very different functionality.
It isn't obvious from looking at the Stream header what flush() does
since there is no comment where flush() is declared in the class.
Maybe "flush" could use an update as well?
Currently, since flush() is in Stream,
there is no common way to tell a device library that uses Print but not Stream
to force buffered data to be sent to the device
without dragging in Stream which doesn't see right to me.
When might having "flush" without Stream be useful?
Say you had a graphic device like a GLCD which is output only so it only uses Print.
Maybe it does buffered writes in local memory.
flush() could be used to force the dirty local buffer to be pushed to the physical display.
I probably should start a new thread on the developers list for this,
since backward compatibility and naming
issues are just as complex and potentially contentious as with the available() functions.
Especially since there is also the throw the data away vs wait for the i/o to complete
functionality, and names like flush/purge/drain/empty have not been used consistently
across different operating systems, and APIs so it is easy to get confused by names.
I only brought it up here because, timing wise,
if there is going to be changes to Stream & Print,
it might be good to also do changes to "flush" at the same time.
And if updates to "flush" were desired,
it also might be useful to consider all the new function names of both the "available" and
the "flush" functions at the same time
to have some sort of consistency between them.
--- bill
jantje commentedon Jul 13, 2014
as I stated before. Available just doesn't say anything.
Finding good names is hard. In my experience longer names make less confusing code.
Rereading the above I think availableInWriteQueue() is not even 60% perfect. It can be understood as "available written data in write queue" (which is the current implementation) and as "available for adding data to write queue".
I agree that Queue is an implementation and is not a good idea to add to the name.
As to availableForRead()/availableForWrite()
availableForWrite is not compliant with the code as the code is exactly the same as the existing available. So it is more StillToWrite(). For my code that works fine as I test for StillToWrite()==0.
But due to the dubious nature of the word "available" one is fully right when disagreeing :-(
There is lots of confusion and doubt on my side. I think the word "available" is part of the problem.
What I think users want as functionality(And that Is not what I implemented) is
Note that that is a "different calculation" on a "different queue". I think this should be reflected in the names:
The best I can come up with right now is:
stillToRead()/availableForWrite()
I hope other people have better ideas.
6 remaining items