0
\$\begingroup\$

I am sending data between a master and several slaves with RS485 with bytes (8 bit) messages with a very simple frame inspired on Modbus ASCII:

0x3A 0x30 0x31 0x32 0x3F 0x0D 0x0A

in which the bytes are the frame sections 1) Start 0x3A, 2) Sender ID 0x30, 3) Receiver ID 0x31, 4) Function to execute 0x32, 5) Data 0x3F, and 6) End 0x0D 0x0A.

With one master and multiple slaves, a receiver slave only sends messages when reads a message with its ID, and is silent otherwise, for discarding any collision.

When the master is the last device to be turned on, everything is ok. All slaves read the full message, and reply accordingly.

But if not, some late in wake up slaves will not detect the Start byte correctly, do not read a full frame at some point, and I don't have any way to make them know where to start.

Because the Data part in the message can perfectly include the Start byte 0x3A randomly, I cannot figure a robust way to deal with this.

I feel this problem is like "escaping" an special character inside a string...

How should I program the frame detection for not having this problem?

\$\endgroup\$
  • 3
    \$\begingroup\$ the beginning of your post states that there is only one receiver .... anyway, why not program the receiver to drop any incomplete frames ... include a data length byte just before the end flag ... if the length byte is zero, then the data length is the default length (whatever you use the most), otherwise the byte indicates the length \$\endgroup\$ – jsotola Sep 13 '19 at 5:19
  • \$\begingroup\$ @jsotola I clarified.. I have one master and several receivers. \$\endgroup\$ – Brethlosze Sep 13 '19 at 5:26
  • 1
    \$\begingroup\$ @jsotola For the parser it is easier to have a data length in the header, which always has an identical structure, then you know exactly where data is located and kow many, lastly you know also where the end and checksum is located. \$\endgroup\$ – Marko Buršič Sep 13 '19 at 5:29
  • 1
    \$\begingroup\$ @MarkoBuršič, i was not thinking about checksums or about headers ... i was thinking about the simplest way to tell if a part of the frame is missing \$\endgroup\$ – jsotola Sep 13 '19 at 5:58
  • 1
    \$\begingroup\$ The silence duration has to do with receive timeout condition + telegram parse time. When receiving, the completion of receive state ends when the last character is received + timeout (no char received within that time). Then the receiver has to parse the telegram (takes time) and only after that it is capable to receive another telegram. So for this time the sender has to keep silence. \$\endgroup\$ – Marko Buršič Sep 13 '19 at 8:15
3
\$\begingroup\$

The header should include also size of data packet and everything should end with CRC or some checksum. You say that you have been inspired by Modbus, so why you didn't copy the whole protocol, which runs perfectly over decades in industry?

If you include checksum at end, there is no way the telegram can be wrongly interpreted

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I had a Hamming 7,4 stage for checking/correcting every byte. Whatever... \$\endgroup\$ – Brethlosze Sep 13 '19 at 5:33
1
\$\begingroup\$

start your frame with an over-length symbol eg: a 9 bit symbol if the usual symbol length is 8 bits.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I think this is a very solid solution, although i am not yet prepared for it. I should reinterpret and rewrite several parts in the code. \$\endgroup\$ – Brethlosze Sep 13 '19 at 6:20
1
\$\begingroup\$

Your protocol looks like Modbus ASCII, but data in binary which means the data can contain framing codes. As the start and end framing are just letters of text data then of course these can exist in the binary data, while originally the binary data is sent as text of hexadecimal string. So either encode your binary data into hex letters so special symbols are only used as delimiters, or then use a encoding with binary escape character after which a byte is sent to represent start, stop or the escape character itself. Even if you don't change the protocol, timeouts would help - receiver can ignore a packet which was not completed in time, and master can retransmit a packet if a receiver does not send anything back in time.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I forgot the difference between Modbus RTU and Modbus ASCII which indeed was the original ancient inspiration. And i am not using a LRC (CRC) because i had a Hamming 7,4 stage. Perhaps I should stick to the standard and drop that detection correction? I guess the solution is the timeout and the 3 1/2 silence mark condition. \$\endgroup\$ – Brethlosze Sep 13 '19 at 6:06
1
\$\begingroup\$

You need some kind of framing. Modbus solves this by introducing time gaps between each frame. A timer checks for this gap time and resets the state machine of the receiver if there is a timeout.

Normally, I suggest using Modbus protocol directly instead of designing your own. If using Modbus is not an option, maybe you can reserve special bytes to indicate start of the frame. In that case, you will also need escape sequences.

You may try Consistent Overhead Byte Stuffing (COBS) algorithm. It uses 0x00 to indicate the end of frame, but avoids using high number of escape characters even if the payload includes lots of 0x00 bytes.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.