9 years, 11 months ago.

Best way to sync to a Serial stream

Hey guys, I'm working on a project in which one microcontroller is a "transmitter" and several other microcontrollers are "receivers". The "transmitter" broadcasts 7 byte frames every millisecond using the UART, and the "receivers" listen for these frames and act on them. My problem, is that the receivers are hot swappable and could be connected to the bus at any time, including in the middle of a frame. What's the best way for a receiver to detect the start of a frame and synchronize with the incoming data? Since the frames are pure data, there's no way I can prefix them with a "magic byte" to signify the the start. I thought about using a Timer with the Serial interrupt to make sure there's a certain amount of dead time between bytes, but I figured I'd see if anyone else had any better ideas first.

Neil, you can't expand those frames, as you mentioned, with a synchronization 2 bytes for example?

posted by Martin Kojtal 01 Jun 2014

I could, but there's a chance those two bytes could appear in the data stream, which would throw the receivers out of sync.

posted by Neil Thiessen 01 Jun 2014

is the range of valid data really full range 0-255?

posted by Martin Kojtal 02 Jun 2014

Unfortunately yes, it's RGB data for a constant current LED driver. I suppose I could restrict the range to 0-254, but I would prefer not to...

posted by Neil Thiessen 02 Jun 2014

3 Answers

9 years, 11 months ago.

What's the baud rate? Can you change it? The obvious solution is to have a timeout where if the receiver hasn't seen any data for longer than n us it throws the data away and assumes the next byte is the start of a new packet.

At 115200 baud I make 7 bytes to be 600us busy then 400us idle. If your cable lengths let you get away with it then upping the baud rate to 460800 or higher would open up that idle time to being more like 850us making it's detection a lot safer and also reducing the risk of connecting mid packet.

The other option would be a start byte and a simple checksum at the end.

If the start byte happens to also appear in the data then the checksum would tell you that you were out of sync. Depending on how common the start byte is in the data it may not sync instantly but unless the byte you pick happens to be in the same location in every single packet it will get there in the end.

Assuming random data and an 8 bit checksum then the odds of a bad packet getting through before you sync correctly is about 1 in 40,000 (60% chance of connecting mid packet * 1 in 256 chance of getting the start byte in the data * 3 bytes of data left on average * 1 in 256 chance of the data happening to be the correct checksum) The odds of two bad packets before syncing become so slim that they are meaningless. By picking a start byte that is unlikely to show up in the data then you can reduce the odds even more. Similarly a 16 bit start pattern and/or checksum also reduce the odds a lot.

Obviously if you can insert bytes into the data stream then you can remove all risk by modifying it to prevent the start character from ever showing up. The down side is that packet length is no longer fixed, for a data packet of all start bytes you would end up sending 15 bytes (1 start + 1 escape byte and 1 data byte per byte of data) which would require you to run at speeds over 115200.

Accepted Answer

The baud rate has yet to be decided, I'm going to do some experiments to see what I can expect to get out of 2.5mm stereo cables. It looks like timeout + checksum byte may be the best solution here, thanks for your help everyone!

posted by Neil Thiessen 02 Jun 2014
9 years, 11 months ago.

Looking at your requirements and that it is apparantly purely binary data, then I would say your options are either timer (make sure it has been idle a while before accepting frames), or you could start by sending a serial break. But while the mbed lib allows you to send a serial break, i don't think receiving one is as easy.

Yeah, I thought of using a break, but I didn't see a way to receive one...

posted by Neil Thiessen 01 Jun 2014

Typical way to detect a BREAK is to check for framing errors (i.e. receive zero's where stopbits (ones) are expected). All UARTS have a flag (usually called FE) for that.

posted by Ad van der Weiden 02 Jun 2014
9 years, 11 months ago.

this link may be help you: http://technet.microsoft.com/en-us/library/cc957975.aspx

And check: Preventing the Occurrence of the Flag Character

posted by Tuan PM 02 Jun 2014

Hmm, character stuffing might work with a little bit of effort... Good idea Tuan!

posted by Neil Thiessen 02 Jun 2014