asynchronous serial output?

Serial.available() tells me that I have pending incoming data. This is great, I can get work done between incoming characters. But, what if I need to stream output? How do I know that I can send a character without blocking? Serial.print() doesnt seem to be buffered. If I am reading the docs correctly, Serial.print("some big string") wont return until all but the last character has been sent. Do interrupts still get handled during the call to print()?

I have need for an interrupt that causes a read of many inputs, forms a three byte message from the input then sends the message out at 9600 baud. I suspect that the interrupts (which are known to come in bursts) will happen faster than the messages can be transmitted. Pointers on how best to buffer the messages and get them out the serial port without missing any interrupts would be appreciated.

Thanks!

If you generally generate more data than can be send over a 9600 serial connection then you have a problem.

You could implement a circular buffer as large as Arduinos limited RAM allows and then hope that "in the long run" you can send data faster than you generate them.

At least with a circular buffer you would know when you have a problem, when the write pointer catches up with the read pointer.

Hope this makes sense

Thanks MikMo,

I mentioned the "bursty" nature of the interrupts for exactly that reason. In fact, a small circular buffer (50 bytes or so) is all I need. My concern has more to do with how to avoid missing interrupts while still getting the data out in a timely manner and while performing other tasks.

I am having trouble understanding the timing around sending a byte out. Perhaps I am worried about nothing. Is there any time during the output of a byte that interrupts are disabled? Also, in the interest of keeping the data flowing, I'd like to send just one byte at a time and use the time between sends to get some work done. The serial.print() function isnt going to do this for me.

dBeau--

I don't think you risk missing any interrupts simply because you are doing a bunch of serial writes. To verify this theory, I wrote a simple program:

void setup()
{
Serial.begin(9600);
unsigned long m = millis();
Serial.println("asdfadfadf adsf adf asdf laskfnd asldf nkas;lfd nkasd; flnkasdf; laknf ;lanasl;kf nasdl fnasdfl knasdlf nkasdlf nasdfl knasfdl knasd flansd flkandf lasnkfd las fnda;sdl fnkas;dlf nkas;dfl knasdf; lkansdf; laknfd ;lak fnda;sld na;fdls nkas;df lknasdf;l nk");
unsigned long n = millis();
Serial.println(n-m);
}

void loop()
{

}

which merely measures how long it takes to Serial.print a huge string. The answer was 264 milliseconds, which proves that lots and lots of interrupts were handled during the call to Serial.println. So my guess is that if you adopt this strategy:

Interrupt handler: gather data from sensors and stuff it into circular buffer.
Loop function: if any data is in the circular buffer, remove it and Serial.print it.

you should be fine unless the interrupts come sufficiently fast so as to overflow the circular buffer.

Mikal

Thanks Mikal,

The answer was 264 milliseconds, which proves that lots and lots of interrupts were handled during the call to Serial.println.

I must be missing something. The math all works out, 250-ish characters at 9600 baud... 264ms. But how does that prove my interrupts will not be missed?

Interrupt handler: gather data from sensors and stuff it into circular buffer.
Loop function: if any data is in the circular buffer, remove it and Serial.print it.

The outline sounds fine. But to minimize loss the interrupt handler as to return as quickly as possible. I know that while in an interrupt handler, interrupts are disabled. So, any processing of the gathered data needs to be done in the main loop. However, while in the main loop, I'll also have to avoid doing anything that could block interrupts.

So how do I determine what I'll need to avoid?

I must be missing something. The math all works out, 250-ish characters at 9600 baud... 264ms. But how does that prove my interrupts will not be missed?

Sorry, I should have been more clear. Millis() is returning a calculation based upon a counter that is repeatedly updated by an interrupt handler. If interrupts had been disabled during the call to Serial.println(), we would not have seen the time increment.

You are right about making the interrupt handling routine as short as possible. How long with the data gathering process take anyway? If it's just a handful of pin reads, I think you should be fine. If your fear is that the data gathering will take so long that you might miss the next interrupt, then I don't think any algorithm will be able to collect data fast enough to service interrupts at that rate.

Mikal

Ah, I get it. That the measured time comes in at about what would be expected implies that writing the data didnt affect the interrupt handling at all (or at least not much).

I am trying to emulate an LCD display (HD44780 like) and send the data out a serial interface. The only specs I have on the display are that the enable pulse can be as short as 450ns with a cycle time of 1000ns. I dont know yet what the real numbers are like. To do this I need to trigger an interrupt on enable and then read 10 pins. I am hoping a couple of portReads would do the trick. The data is coming from an existing, PIC18F4620 circuit that I have no control over.