Author Topic: RS485 communication handling  (Read 5994 times)

0 Members and 1 Guest are viewing this topic.

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18204
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
RS485 communication handling
« on: March 10, 2023, 09:40:39 am »
I am working on a system where I have a machine ECU and a HMI that will talk over RS485.

This means of course that there must be some sort of protocol and message handling, currently I detect a received byte and start putting the bytes into a buffer array in the interrupt handler each time the interrupt fires for a byte received. But how do I guard against any spurious data coming in like some transition on the bus when the other device starts up? is such an event likely?

I can think of 2 methods 1) have a start byte, something like 0x55 (01010101) should be fairly demanding in satisfying the timing requirements to be picked up as a byte that should be taken seriously. 2) I know that a message should be at least say 4 bytes so if I don't get at least 4 bytes in a timely fashion I ignore it all and reset by buffer index to 0.
 

Offline pcprogrammer

  • Super Contributor
  • ***
  • Posts: 5002
  • Country: nl
Re: RS485 communication handling
« Reply #1 on: March 10, 2023, 09:52:16 am »
You can use a CRC on the data and reject messages that fail the test. But you will have to make up some protocol anyway because you are controlling something from a human machine interface. So a preamble like 0x55 followed by a message length and at the end the CRC can work.

Another option is to use a longer preamble like 0x55 0xAA and only receive more data when such a sequence has been received. This reduces the problem of 0x55 being part of a valid message. The change of 0x55 0xAA being part of a valid message is less.

Online woofy

  • Frequent Contributor
  • **
  • Posts: 414
  • Country: gb
    • Woofys Place
Re: RS485 communication handling
« Reply #2 on: March 10, 2023, 10:07:58 am »
Data corruption can and does happen in an industrial environment. It might only be a single bit in one byte but its enough to ruin your day.

Use an interframe gap as the trigger for a new frame, or bit 8 (9th data bit) of the data if that is available to you. Try not to trigger off a specific byte, and don't rely on having "enough bytes".
For the protocol divide the frame into a header/payload and CRC.
The header will contain at least the target address (if there is any possibility of more than one device on the bus) and the payload count.
That is followed by the application payload, and finally the CRC of the entire frame - up to the CRC of course.

Its the CRC that will protect your data, if there is a mismatch then throw the frame away.
« Last Edit: March 10, 2023, 10:11:03 am by woofy »
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18204
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: RS485 communication handling
« Reply #3 on: March 10, 2023, 10:17:02 am »
Yes the plan is a message format with an address and error check at the end. My concern is that if a reception is triggered by anything I could never be in sync. So say some junk happens and the receiver takes this to be the first byte then it is stored in the first byte of the buffer and then the real start of message comes and will put in as byte 2 in the buffer, this will of course fail the checksum but I don't want to end up in a situation where no message comes through as the receive buffer is out of sync as it is picking up any garbage.

Yes 0x55 followed by 0xAA will be more robust, the longer the better until the starter bytes exceed the actual useful data  :bullshit:
 

Offline errorprone

  • Contributor
  • Posts: 39
Re: RS485 communication handling
« Reply #4 on: March 10, 2023, 05:39:09 pm »
Can always use a standard such as Modbus RTU where frames are delimited by a silent period of 3.5 characters or Modbus ASCII which always starts with a colon and ends with a carriage return and line feed.  Both are typical over RS485 and there are plenty of libraries available so it doesn’t need to be written from scratch.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18204
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: RS485 communication handling
« Reply #5 on: March 10, 2023, 08:13:54 pm »
well standards need taking as are so I might take on more than I need. The basic problem is solved by having a unique enough start sequence which as you say modbus ASCII has with the penalty of now having to convert everything into characters. The idea of a fixed time between frames does not sound as good, you have to start at some point so will throw the first message away if there is some gibberish followed by a message soon after.

When you say that there are libraries, where would I find these and what form do they take? This is a problem that is very tied to setting up the specific hardware.
 

Offline langwadt

  • Super Contributor
  • ***
  • Posts: 4993
  • Country: dk
Re: RS485 communication handling
« Reply #6 on: March 10, 2023, 08:59:37 pm »
I think you are over thinking this, if there's garbage on the line you'll miss frames, there's no way around it, and since RS485 is a shared bus any spurious data will affect everyone on the line and the communication must have some form of master requesting responses from each slave at a time
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18204
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: RS485 communication handling
« Reply #7 on: March 10, 2023, 09:30:07 pm »
no not necessarily. I don't know what it takes for the micro controller to detect a valid byte. I guess it will measure from the start to the end of the frame and only take the byte as good if it sees the correct timing. Now if for some reason it "sees" a 0 byte on the bus it will put that into the first byte of the buffer variable without questioning it. If a message then starts this will continue to fill the buffer. The message is now one byte out and the checksum fails.

Now I don't know what happens with the RS485 transceiver as now TX and RX are joined. the flow control pin will disable the input when the output is active, I have thought maybe it is a good idea to disable the receiver while D transmit.
 

Online peter-h

  • Super Contributor
  • ***
  • Posts: 4595
  • Country: gb
  • Doing electronics since the 1960s...
Re: RS485 communication handling
« Reply #8 on: March 11, 2023, 08:15:01 am »
If you control the protocol then it is fairly easy.

Define a packet which is all ASCII, starts with say "*" and ends with say "$".

Throw away bytes until you get a * and then load them into a buffer (bigger than needed), with a timeout of say 1 sec. If the timeout goes, go back to start. If end of buffer reached, go back to start. If $ seen and there was no timeout and you are not at the end of buffer, check a CRC or some such, which was last 2 bytes (four ascii characters) before the $.

With RS485 you are always master-slave. The master polls and the slave responds. If your application is full duplex then you can't use RS485. You have to use RS232 or RS422 (RS422 is often called 4-wire RS485).

Yes you enable the RS485 driver during transmission, then turn it off. This can be tricky; normally you transmit under interrupt, and when you get the TX Empty ("all sent") interrupt you disable the driver. The driver is enabled when data is loaded into the UART.

I would not bother with Modbus. Over-complicated, and using some library just introduces code which you don't know how it works.

Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 9677
  • Country: fi
Re: RS485 communication handling
« Reply #9 on: March 11, 2023, 08:43:56 am »
Yes the plan is a message format with an address and error check at the end. My concern is that if a reception is triggered by anything I could never be in sync.

Consider this usual stream format:
START LEN PAYLOAD CRC

By choosing START magic number properly, odds that it is repeated in payload are made smaller (can be multibyte):
acdcabba 05 (01 02 03 04 05) 13 37

Now it's still possible that acdcabba repeats in data:
acdcabba 05 (01 ac dc ab ba) 21 18

When you start parsing at correct start id, CRC check succeeds -> you are now in sync with the stream.

But let's say you are out of sync and accidentally sync to the wrong acdcabba. Now 0x21 in above example is interpreted as length. You have to read many bytes and lose many packets before you get to what you think is CRC, get mismatch and only then detect the error.

Worse, if the unlucky packets containing acdcabba are recurring, chances are you always try to resynchronize on the wrong start id, and never get a sync.

Solution to this is to buffer bytes and if CRC mismatch happens, scan old bytes in the buffer to find another acdcabba. One of them must be the right identifier. You can guarantee to get back in sync this way, but scanning the whole buffer many times is more work and also requires much more processing than byte-by-byte parsing while bytes are received.

Or, you can just accept not to cover this problem. With a long (say 32-bit), randomly chosen magic number and low error rates, the failure condition of never getting sync is extremely rare.

One way of mitigating the problem of having to waste a lot of packets due to misidentification or corruption of length field, is to use separate CRC for header only. For example, a 8-byte header block: START32 LEN16 MSGID8 CRC8, followed by payload and then CRC16 over the payload. Now, chances of this 64-bit sequence (including valid CRC) occurring in payload is extremely small, and that repeating in every data frame even more slim.

This post is assuming you want to use all possible byte values in payload. If you are willing to remove 1:1 mapping from raw payload to packet payload, you can choose unique values for start/end identifiers as peter-h suggests, but then you need to escape these values in data, and data length becomes different to original raw payload.

ASCII is good when you want human interoperability, but on the other hand, ASCII-based systems have been notoriously troublesome, despite good intentions.
« Last Edit: March 11, 2023, 08:46:55 am by Siwastaja »
 

Online peter-h

  • Super Contributor
  • ***
  • Posts: 4595
  • Country: gb
  • Doing electronics since the 1960s...
Re: RS485 communication handling
« Reply #10 on: March 11, 2023, 09:05:36 am »
The problem with binary data is that you must rely on timeouts to handle error conditions, and/or implement weird speculative approaches (like speculatively checking the CRC as you go along).

Whereas with ascii data (perhaps just straight hex) it is all very easy. Sure, the packets are 2x longer but usually this doesn't matter.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline pcprogrammer

  • Super Contributor
  • ***
  • Posts: 5002
  • Country: nl
Re: RS485 communication handling
« Reply #11 on: March 11, 2023, 09:24:00 am »
When using 7 bit ASCII the msb is available to be used in the preamble. MIDI uses this. When the msb is one it indicates a command byte. So use for instance 0xA5 0x96 as the start of the message and only 7 bit ASCII for the rest. Limit your payload size to 127 bytes and code your CRC in ASCII HEX.

Adds a bit to the length and processing of the message, but the original post mentions human machine interface, and how much data at what rate can that mean.

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18204
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: RS485 communication handling
« Reply #12 on: March 11, 2023, 09:48:15 am »
using ASCII does feel like it's a pain, I have 8, 16 and 32 bit numbers to send and bit flags. my thinking is:

1) Timing out allows me to be sure any ongoing message has ended
2) with the certainty that any new byte is a new message it must be "the one", using 2 bytes to start gives me a 1 in 65536 chance of failure instead of 1 in 256. This sounds pretty good, I don't know if having 1 start byte and a second start byte that relates to the first further improves on this like they should both add up to 0xFF so the second is also a checksum of the first as will as making it a 16 bit start instead of 8 bit.
3) having information about the data length could be useful to further be more sure about the message end. I could combine this with the start byte maybe, either a variable start sequence that much pass a checksum or just have a start, message length and then checksum of those 2, that now means that there is less than 1 in 16 million chance that there is a misinterpretation.
4) A stop byte would make matters robust as although it could repeat in the data it would have to be in that precise location it is expected and with a message length either predetermined or given at the start with checksum protection very robust.

I think essentially anything would be way better than no start identifier. Making sure it's something better than just a start byte will be fine.

Even if I were to add several bytes of overhead this would still beat the extra data from ASCII and would avoid converting the data at each end. Even if I did want to send text around the basic alphabet upper and lower case with the numbers 0-9 fit into 64 bits so you could send a really robust header and encode the text with 3-4 characters per byte. But I am not planning to send text.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18204
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: RS485 communication handling
« Reply #13 on: March 11, 2023, 09:52:58 am »
When using 7 bit ASCII the msb is available to be used in the preamble. MIDI uses this. When the msb is one it indicates a command byte. So use for instance 0xA5 0x96 as the start of the message and only 7 bit ASCII for the rest. Limit your payload size to 127 bytes and code your CRC in ASCII HEX.

Adds a bit to the length and processing of the message, but the original post mentions human machine interface, and how much data at what rate can that mean.

Right now I am doing something in a hurry with 2 devices so as long as it is sensible enough to not fail in front of a customer on a demo it's fine. In the longer term I will have multiple devices so I'm trying to make sure I'm not doing something that is just a fix but carries a lot of overhead that later ends up being a pain to live with.
 

Offline langwadt

  • Super Contributor
  • ***
  • Posts: 4993
  • Country: dk
Re: RS485 communication handling
« Reply #14 on: March 11, 2023, 11:38:46 am »
There's also a lot of uarts that directly support using the parity as a ninth bit
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 9677
  • Country: fi
Re: RS485 communication handling
« Reply #15 on: March 11, 2023, 12:30:29 pm »
Whereas with ascii data (perhaps just straight hex) it is all very easy. Sure, the packets are 2x longer but usually this doesn't matter.

What, you don't implement error checking such as CRC on ASCII? Of course it is "easier" if you set different goals.

ASCII parsers tend to be at least 10 times more complex than binary parsers. If you are willing to pay this price for human interoperability, this is fine, and a good tradeoff. But if you use ASCII thinking it is "simpler" to program (and works more robustly), you are terribly misled.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18204
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: RS485 communication handling
« Reply #16 on: March 11, 2023, 12:57:40 pm »
A 4 byte number could be as long as 10 characters, a 2 byte number could be as long as 5 characters, a single byte number could be as long as 3 characters, ASCII is not the way to go, while it may guarantee that a single start byte will be unequivocally recognized a 3-4 byte starter that would contain some helpful information like length would be far less overhead.
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 9677
  • Country: fi
Re: RS485 communication handling
« Reply #17 on: March 11, 2023, 01:05:30 pm »
One middle-ground option which gives you some level of human interoperability, leaves unused symbols for start/end delimiters, but is less wasteful on comms bandwidth, and less wasteful on CPU number conversion cycles, and what bests, generates fixed-length datagrams from binary data, is ASCII but with hexadecimal numbers instead of decimal. Being constant-length, you can theoretically leave out field delimiters, then it "only" doubles the size compared to binary.

Did I get the premise correctly, all participants are microcontrollers, no PC stuff? If so, to get something quickly, I would start by implementing the packet framing using idle time, as suggested by many. Then just send binary data as is. No need to think about CRCs for the first prototype. Instead, concentrate on RS485 signal integrity; you have to do that anyway! If you do that, bit errors will be rare enough you can implement error checking later.

Remember that RS485 needs biasing (misleadingly called "failsafe biasing"; it has nothing to do with failing safely) to operate correctly; look it up. Some transceiver ICs are fine without, some are marginal, some don't work reliably at all.
« Last Edit: March 11, 2023, 01:07:10 pm by Siwastaja »
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18204
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: RS485 communication handling
« Reply #18 on: March 11, 2023, 02:06:18 pm »
The actual communication seems to be fine. but when I tried receiving data from the other device (ESP32) and then sending it back I was sending back 0's. But there was also some data that changed. So I have become suspicious that I am getting out of sync with the datastream as I have no way of knowing that the byte I just received really is valid.
 

Offline SuzyC

  • Frequent Contributor
  • **
  • Posts: 823
Re: RS485 communication handling
« Reply #19 on: March 11, 2023, 02:18:33 pm »
Do what some TV Remote Control codes formats do.

Very high security esp. for long frame: Send each byte in your frame and then the frame as complement ~bytes and compare each data frame byte to validate frames. This works very well if you have long frames and the time available to put up with the overhead.

Even better is adding to the above a one to 4-bytes fixed preamble and a single fixed valued end byte after an 8-bit CRC.  This protocol can be shortened to apply only to the preamble bytes, adding a 8-bit CRC at the end, if more speed and less security is desired.

The write enable protocol used by some EEPROMs is also very reliable, using a fixed 4-byte preamble followed by the data frame and and a fixed ending byte preceded by a 16-bit CRC.

The possibilities are endless, if you have the time.
« Last Edit: March 11, 2023, 02:29:45 pm by SuzyC »
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 9677
  • Country: fi
Re: RS485 communication handling
« Reply #20 on: March 11, 2023, 02:29:23 pm »
The actual communication seems to be fine. but when I tried receiving data from the other device (ESP32) and then sending it back I was sending back 0's. But there was also some data that changed. So I have become suspicious that I am getting out of sync with the datastream as I have no way of knowing that the byte I just received really is valid.

Well, you have to debug your system, look at the signals carefully with scope, save and print intermediate values, compare, whatever is needed. You can toggle extra IO pins from your code so that you can see that something happened in synchronization with the RS485 data on scope.

Any communication strategy is going to require some actual work and unless you are a mega genius, nothing will just work out of box. Try to work out what's wrong with your current code first.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18204
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: RS485 communication handling
« Reply #21 on: March 11, 2023, 02:47:31 pm »

Any communication strategy is going to require some actual work and unless you are a mega genius, nothing will just work out of box. Try to work out what's wrong with your current code first.

Indeed. And the first task in a protocol receiving data is to ascertain that what was received is the start of a message, looking at the whole message for validation and not just relying on a byte appearing in the buffer with no further checks.
 

Offline pcprogrammer

  • Super Contributor
  • ***
  • Posts: 5002
  • Country: nl
Re: RS485 communication handling
« Reply #22 on: March 11, 2023, 03:40:19 pm »
... unless you are a mega genius, nothing will just work out of box. Try to work out what's wrong with your current code first.

And that is the real skill of programming.  >:D Being able to figure out why something that in your mind should work is not working.

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18204
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: RS485 communication handling
« Reply #23 on: March 12, 2023, 12:25:27 am »
the datasheet (SAMC21) states:

31.6.2.6 Data Reception
The receiver accepts data when a valid start bit is detected. Each bit following the start bit will be sampled according
to the baud rate or XCK clock, and shifted into the receive shift register until the first stop bit of a frame is received.
The second stop bit will be ignored by the receiver.
When the first stop bit is received and a complete serial frame is present in the receive shift register, the contents
of the shift register will be moved into the two-level receive buffer. Then, the Receive Complete interrupt flag in the
Interrupt Flag Status and Clear register (INTFLAG.RXC) will be set, and the optional interrupt will be generated.
The received data can be read from the DATA register when the Receive Complete interrupt flag is set.

I'm not entirely clear here. If I read this literally the buffer will just keep accepting the "data" until the line goes high, so if there is a spurious low pulse I will get a "0" byte if it lasts longer than 9 bits worth.
 

Offline pcprogrammer

  • Super Contributor
  • ***
  • Posts: 5002
  • Country: nl
Re: RS485 communication handling
« Reply #24 on: March 12, 2023, 07:02:54 am »
That is how a UART works. A start bit is when the line goes low and stays low during a bit time. Then the shift register gets filled with what it sees on the line. If that is zero for the duration of full data set, you will see a zero.

A modern UART uses oversampling and other techniques to reduce error, but it still boils down to seeing a start bit and then clock the data into a shift register. If the stop bit is not seen at the right time it can raise a framing error, but you have to check for it. Think it will still signal a data set received.

To get an insight you could read this article about an implementation in VHDL or verilog.


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf