Prioritise Serial I/O


I'm making a MIDI system for a synth.

Synth MIDI out -> Arduino Serial1 IN Arduino Serial1 OUT -> Synth MIDI IN Buttons etc -> Arduino IN EXT MIDI CLOCK -> Arduino Serial2 IN -> Arduino Serial1 OUT -> Synth

My question is:

The Arduino will be getting clock messages from the external source via serial... these need to be passed on out of the arduino's serial port. How can I prioritise this? As these bytes are timekeeping they're really important to the system. If I check for these incoming bytes at the same rate as I'm checking everything else (MIDI IN from the synth, Buttons, other code etc) then this will cause delays/poor timekeeping, correct? Especially as I'll be doing things like debouncing buttons and cycling through arrays.

I need the Arduino to prioritise sending bytes received from a serial port to another serial port, regardless of what else is going on. Is this possible?

I am aware of interrupt, but I've read that this doesn't work with serial. Threading would be ideal (I think?) but I'd rather not use a library for this.

Using a Mega.

Thanks in advance. Ready to answer any Q's.

What kind of delay would be allowed ? A few milliseconds ?

It is possible to write code in an interrupt that passes data on to another serial port, using direct register programming. However, I think you want to combine the clock with the MIDI (everything output to Serial1, right ?). I think that should be done in a sketch with the Arduino Serial library and the buffers of the Serial library.

Do you have any delay() in your sketch ? I hope you don't use a delay() to debounce the buttons. Perhaps there is a smarter way to cycle through an array. Perhaps with a jump table (case-statement).

A few milliseconds would be acceptable.

That's correct. I do want to combine the clock with my own MIDI data. My own data will only be sent momentarily, and irregularly, however. The clock must always be running.

Why would I need the serial library? How would I go about using buffers?

I feel like an interrupt would be a good solution.

Almost like a separate void loop() that comprises of "if you receive byte xyz on serial, then transmit it immediately!

I'm not using delay for debouncing for that exact reason :) I'll look into cases, thanks.

The midi uses a low baudrate, I think the sketch can keep up with it.

I can't help with an interrupt that combines two serial ports. I don't know how to combine them at a low level.

Have a look at this code:


That code uses the Arduino Serial library and the buffers inside that library. This is the code of the Serial library (only a part of it) :

I suggest to start writing a sketch that uses the Arduino Serial library. Perhaps the delay will be very short after all.

MIDI is packet-based isn't it? There's a start and an end to any MIDI command? Then usually you want to receive complete packets from your two serial inputs before putting them in the outgoing queue. I do a lot of work with NMEA, which has an end-of-packet checksum. My programs always wait to check the checksum is correct so that they're not wasting time forwarding invalid data.

You could program it so that it always forwards data from Serial2 without checking if the packet is complete.

How is the system supposed to work if Serial1_out is halfway through sending a packet when bytes start coming in on Serial2_in? Should it complete sending that packet or should it abort the packet and restart a new packet with the incoming Serial2 data?

The key to this system is keeping your main loop running very fast. It never stops and waits and it never tries to send or receive more than one character at a time. This means you need to keep your own buffers of incoming and outgoing packets. Just send one character off the outgoing buffer, then check all the other inputs to see if there's a char available and repeat.