send array 'tween arduinos: serial print or write?

I want to send an array of numbers from a 'sender' arduino board to a 'receiver' board via the Tx/Rx pins, and be able to read and process the individual elements of the array on the receiver board.

Which would make the task easier: serial.print or serial.write? Would serial.write be more efficient?

There has been some discussion of this topic here:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1257276571/0

....but what remains unclear for me is what is the best method for recognising the individual elements of a received array when serial.read is used on the receiver board. I imagine the methods will be quite different depending on whether the array was sent with serial.write or serial.print.

Any advice would be much appreciated.

Serial.print writes the data as characters. Serial.write writes the (byte sized) data as bytes.

Which to use depends on what you are trying to send and receive.

What size/type is the array to be sent?

Thanks for your reply.

The array will have 9 integers in it, each having the 0-1023 range (although this could be scaled to 255 if advantageous).

Scaling to 0 to 255 means that each value is then only one byte in size, and you could Serial.write those bytes much faster than converting to ascii representations using Serial.print. It would also eliminate the need to convert back on the receiver.

On the receiver board, would I do 9 serial.reads in a row to pick out each element in the array (sent with serial.write), or is there a better way of doing this? For example, associating each element with a label?

If the two boards are hard-wired together, there is virtually no risk of data loss, so 9 reads into 9 positions in an array will work fine.

In general, though, sending 11 values - a start marker, 9 values, and an end marker - is a better idea. Look for the start marker. Read the next n values, or until the end marker is received, storing up to 9 non-end-marker values.

However, since you are sending bytes, and any value between 0 and 255 will be a valid value, and no other values are possible, you don’t really have that option.

thats very informative, thanks. I will give the simple 9 reads method a try and see how reliable it is. Do you think the performance loss associated with using ascii representations via Serial.print would be substantial (ie easily noticeable)?

If the two boards are hard-wired together, there is virtually no risk of data loss, so 9 reads into 9 positions in an array will work fine.

While there may be "virtually no risk of data loss", there will still be the chance that this could occur. Depending on what is being done with the data, this may or may not matter. It would be best to think about the possibility of this situation, however remote it may be, and come up with a solution that mitigates this issue, especially if the data is critical to some other function or need on the second Arduino.

You may never see it come up, but if it does, wouldn't it be better to handle the situation gracefully, rather than being left scratching your head when it does (which could be years down the line)?

If the two boards are hard-wired together, there is virtually no risk of data loss

I'll bet that, somewhere in the world, there's an engineer who has that carved on his tombstone ;D

The odds are, indeed, pretty good that a hard-wired connection won't see the kind of garbling that shows up on modem or radio links. But Murphy's Law tells us that, sooner or later, the boards will find a way to get out of sync. The best way to protect against that is to have some sort of "sync" character or sequence that can't legally occur in normal data.

A cheap way to do that in this case is to either constrain the data if you're sending single-byte values (e.g., if you get a real reading of 0xff, change it to 0xfe), or use a bogus value if you send 2-byte readings. The ADC only returns values in the range of 0-0x3ff, so send a sequence of 10 words, with the first one being, say, 0x7fff to make it clear that it can't be a real reading. Then just use write() to send serial data, and have the receiver discard everything coming in until it sees the 0x7fff sequence. For additional robustness that you probably don't need in this case, you could also add an "end" sequence (say, 0x7eee) so you can be sure that you got exactly 9 2-byte values.

Ran

I use good old fashioned checksums to verify the integrity of data. Add 'em together and stick the total on the end of the data, at the other end check what you got in the data adds up to the received checksum......

thanks for your suggestions folks, they are very helpful to me.

@pluggy: using the checksum method, if it detected that the array was out of sync, what would be a good way of getting back in sync? If serial.flush was triggered would that clear the buffer such that it would next be filled by a complete array, thereby getting back in sync?

On my setup I have a seperate part of the sketch that does a serial flush periodically. The data goes around every 5 seconds, a SerialFlush is done around every thirty seconds. If the checksum doesn't match it ignores the data and continues with the last known good data. Flushing brings it back to sync if it does go out.

If serial.flush was triggered would that clear the buffer such that it would next be filled by a complete array, thereby getting back in sync?

Maybe, maybe not: it depends on when you issue the flush().

If you want "definitely", you need to have some sort of synchronizing sequence or signal (like using another pin to indicate the start of a group).

Pluggy and Ran, thanks very much for your advice, I will give these suggestions a try.....