Jump to content

Modbus RTU message framing


Recommended Posts

I'm working on a Modbus Server (aka Slave) implementation for Serial communication.   Has anyone experience with this?   My immediate question is about the "RTU" format.   Standard serial format uses CRLF characters to mark the end of messages, but RTU uses "3.5 characters of silence" on the serial line.   I have no idea how to detect "silence" in a reliable way.  Past Modbus in LabVIEW implementations I've looked at seem to put waits in to create silences, but don't use the silence for defining a received message.  I am worried that this is vulnerable to error.

Link to comment

Basically the RTU slave should continuously check its serial port, and if there is any data there it should recheck the port until no new data has been received for those n milliseconds. Then it should process the received message. If the message is intended for a different ID it should just discard the data (clearing its serial buffer for another message).

Using 3.5 character silence time can be a bit challenging yes. Windows at least seems to add delays every now and then (it's not deterministic...), so even in a tight loop you can get into that kind of territory (typically you will see this as a problem that increases the longer the Modbus messages are, as the probability of an incorrectly detected halt will then increase...).

Luckily most of the time the Modbus Master can be configured to put more silence between polls (interframe delay or similar configuration), making it easier for slaves to clear their input buffer between polls to receive separate messages. We have dealt with most of the control systems used in the oil and gas industry over the years, and have never had an issue after the initial setup  (All of them can extend the silence time if needed, and/or chop the messages into shorter ones). Instead of 3.5 byte times at a baud rate of 19200 for example, we might end up using 10-30 ms.

Edited by Mads
  • Like 1
Link to comment
2 hours ago, drjdpowell said:

I'm working on a Modbus Server (aka Slave) implementation for Serial communication.   

 

Just curious, but why bother when there are multiple native LabVIEW implementations already? There was the "original" NI library , the LVOOP NI implementation, and I believe at least one third party implementation. 

  • Like 1
Link to comment
1 hour ago, MarkCG said:

Just curious, but why bother when there are multiple native LabVIEW implementations already? There was the "original" NI library , the LVOOP NI implementation, and I believe at least one third party implementation. 

^^

3 hours ago, drjdpowell said:

I'm working on a Modbus Server (aka Slave) implementation for Serial communication.   Has anyone experience with this?   My immediate question is about the "RTU" format.   Standard serial format uses CRLF characters to mark the end of messages, but RTU uses "3.5 characters of silence" on the serial line.   I have no idea how to detect "silence" in a reliable way.  Past Modbus in LabVIEW implementations I've looked at seem to put waits in to create silences, but don't use the silence for defining a received message.  I am worried that this is vulnerable to error.

Yeah, I can tell you from personal experience that actually trying to use the 3.5 char of silence is not a great idea. You do need a read timeout and polling, but you should parse the packet as you read it to determine how long its supposed to be, and then check the crc. As mentioned above, the serial software stack you're going through (labview->visa->os) is not conducive to waiting for silence. The packet should be parseable and if you just keep in mind that a modbus packet is limited to a pretty tiny maximum size, there are a lot of checks you can do to eliminate issues and basically "close the connection" if a problem is encountered. The issue with that is that both master and slave need to back off appropriately, clear buffers, etc, to make sure that any communication error can be resolved without rebooting the system on either side.

  • Like 1
Link to comment

You do need a read timeout and polling, but you should parse the packet as you read it to determine how long its supposed to be, and then check the crc.

The problem with that is that the instrument could be on a multi-slave RS485 line, with units from other manufacturers that may implement function codes (including User-defined codes allowed by the Modbus spec) that we don’t understand and thus can’t identify the end of.  The advantage of the “silences” is that it is independent of message content.

Link to comment

Just curious, but why bother when there are multiple native LabVIEW implementations already? There was the "original" NI library , the LVOOP NI implementation, and I believe at least one third party implementation. 

My reasoning may be wrong but I rejected:

1) NI implementation as it is part of the DSC and requires a runtime license on each unit.

2) NI Labs free version because it is both unsupported AND password protected (a deadly combination).

3) Modbus Master by Plasmionique because it doesn’t do Slave/Server (though I’m using it as a guide).

4) Old NI library because it is very old.   Unsupported for more than a decade (and it was very old back then).  

Also, it may seem strange to say, but these libraries aren’t solving enough of my problem.  Building and parsing strings is the easy part; Modbus isn’t that complicated.  It’s shoehorning my complex data into a bunch of U16 registers that seems harder.   I think the above solutions maintain internal models of these registers, which I must continually update.   Instead, I plan to do an event/message-based solution where I build the command responses directly from the application data.

Link to comment
3 hours ago, smithd said:

but you should parse the packet as you read it to determine how long its supposed to be, and then check the crc

+1. You scan the bytes as they come it and start parsing when a byte equals the address. If the CRC doesn't check out, you discard. If it does, then pass it up. This method is very robust.

Link to comment

Using 3.5 character silence time can be a bit challenging yes. Windows at least seems to add delays every now and then (it's not deterministic...), so even in a tight loop you can get into that kind of territory (typically you will see this as a problem that increases the longer the Modbus messages are, as the probability of an incorrectly detected halt will then increase...).

I imagine there is no real problem with non-broadcast messages, since the Master will wait for a replay much longer than 3.5 characters, but it would be a problem with broadcasts (as the Master expects no reply and could send several broadcasts with only a short delay between).

Link to comment
12 hours ago, ShaunR said:

+1. You scan the bytes as they come it and start parsing when a byte equals the address. If the CRC doesn't check out, you discard. If it does, then pass it up. This method is very robust.

Personally I prefer the modbus way here; using silence time as markers for the end of messages. And I really do not want to chew on that data in a hunt for an ID with a CRC that just probably indicates a valid message (although the chance of a false positive is low, we are dealing with a *lot* of messages here...). Calculating lengths is also messy with modbus, as many messages have unpredictable lengths (Modbus should have had a header with the length in a fixed position...Instead each function code is different, not to mention user defined ones).

As for not using any of the libraries already out there I share many of your sentiments James. Linking the modbus handling tightly with the rest of the application though is something we have mostly avoided. We use an in-house library that deals with the fundamentals of  generic modbus only, and have other code add layers on top of that instead just using the registers. I  did have to insert some user defined function code forwarding into the library once to make a generic robust file transfer (ZMODEM inspired) and command protocol on top of modbus though...That solution allows us to upgrade the software on our subsea embedded PACs, and use various TCP/IP based protocols transparently over a serial Modbus RTU link when no Ethernet is available :-) It would have been nice to have something like that be part of the Modbus standard instead though.

Edited by Mads
Link to comment
3 hours ago, drjdpowell said:

My reasoning may be wrong but I rejected:

1) NI implementation as it is part of the DSC and requires a runtime license on each unit.

2) NI Labs free version because it is both unsupported AND password protected (a deadly combination).

3) Modbus Master by Plasmionique because it doesn’t do Slave/Server (though I’m using it as a guide).

4) Old NI library because it is very old.   Unsupported for more than a decade (and it was very old back then).  

Also, it may seem strange to say, but these libraries aren’t solving enough of my problem.  Building and parsing strings is the easy part; Modbus isn’t that complicated.  It’s shoehorning my complex data into a bunch of U16 registers that seems harder.   I think the above solutions maintain internal models of these registers, which I must continually update.   Instead, I plan to do an event/message-based solution where I build the command responses directly from the application data.

Fair enough. I will say that the old library did the job pretty well though, never had a problem with it, even running on something as old as a fieldpoint. I actually modified to make it faster on reads as well, and also to make communications library for a flowmeter that used a proprietary bastardized version of modbus. The core logic of it is pretty solid and worth looking at. 

Link to comment
25 minutes ago, drjdpowell said:

I imagine there is no real problem with non-broadcast messages, since the Master will wait for a replay much longer than 3.5 characters, but it would be a problem with broadcasts (as the Master expects no reply and could send several broadcasts with only a short delay between).

Oh non-broadcast messages can pose a challenge too, if you have multiple other slaves on the same line replying instantly after 3.5 byte times...

Broadcasts on the other hand are seldom used in the systems we deal with, and when they are, its mostly directed towards our non-Windows targets (which in our case means sensors running assembly or Visual-DSP based code instead, with no problem handling such short silence times).

Edited by Mads
Link to comment

How many of you have done Modbus Slaves (rather than Masters)?  Master communication is easy, as you just clear buffers, send command, and wait for response in known format. Retry on any failure.  Slaves must listen to a stream of messages to multiple units, including unknown formats.

My experiments with 3.5 byte silences are going poorly (30% failure rate).

Link to comment

We do both. As I mentioned 3.5 byte times is extremely short for a Windows-machine, at least at higher baud rates but most control systems for example make this time configurable anyway. That's the main point - the master should not issue commands too quickly in a row. It's not really a problem if there are slaves that will reply faster, because getting non-relevant messages garbled by having both the poll and reply together in the same serial buffer is no problem (it should just be discarded anyway). The problem is if the master shoots another message addressed to your slave too quickly after getting the previous reply. Then you are not able to separate that relevant data from the previous irrelevant messages.

Link to comment
2 hours ago, drjdpowell said:

How many of you have done Modbus Slaves (rather than Masters)?

I've written 8 drivers that supported slaves for various companies. The last 6 supported master as well. (Wow. Was the first one really in 1999?)

 

1 hour ago, Mads said:

Then you are not able to separate that relevant data from the previous irrelevant messages.

You are able. You are just finally forced to do what smithd and I have already suggested.

Link to comment

Yeah, so my issue with the 3.5x times is that the visa bytes at port aren't always accurate, especially in my case on linux targets. To give you an example, lets say you have a single master single slave and the master sends 134 bytes. Polling the bytes at port gives you:

  • 0 ms -- 0 bytes
  • 5 -- 20
  • 10 -- 20
  • 15 -- 20
  • 20 -- 40
  • 25 -- 40
  • 30 -- 40
  • etc...

So if 3.5 character times is (in this example) <15 ms, we'd start trying to parse after only getting 20 bytes. I eventually got hold of linux guys in R&D who explained that this is fundamental to how ni visa and the linux serial driver interact and the behavior couldn't be made more sensible.

If you imagine this on a multi-device network, its possible that you accidentally merge requests because you have no way of detecting the silence between messages.

If you just use the CRC it is as mentioned above quite expensive, and its possible (if unlikely) to hit a byte string where the CRC method provides a false positive.

Assuming you know all of the function codes (I know you don't) the right answer is to try to parse the packet using timeouts as a guide for error handling.

Since you don't know all the function codes I think you have to go through some hoops to use all three together. IF the function code is known, parse it. If you read the function code and its unknown, use the CRC method in combination with silence times. However the silence has to be pretty flexible and you have to expect that you will miss a silent period if baud rates are high.

Link to comment

I've been experimenting with different ideas all day.  I can't seem think of a way to avoid all possibility of a deterministic failure.  Non-deterministic failures correct themselves when the Master retries the command, but a deterministic failure (such as a long message to another unit that by chance appears to contain a shorter message to us) will reoccur every time.   I can rely on "silence" for identifying the end of a message (since the Master is waiting for us to respond), but I can't identify the start except through pattern matching the message.

Link to comment

In the end I found I could support both methods as an option: a "strict silence framing" mode where there must be a long silence (30ms+) in front on the message (to allow me to be sure there is a silence and clear the buffer) and a faster mode that uses pattern matching (but has a very small chance of deterministic failure if other slaves share the serial line).

Link to comment
On 11/2/2017 at 2:48 PM, ShaunR said:

I've written 8 drivers that supported slaves for various companies. The last 6 supported master as well. (Wow. Was the first one really in 1999?)

 

You are able. You are just finally forced to do what smithd and I have already suggested.

That was kind of implied. Instead of going that probabilistic route though, we just get the masters to pause enough in front of the messages to our slaves to avoid the issue. It's never been a problem to get the control system operators to accept that (they are normally quite strict on things, but not that particular configuration).

Link to comment
  • 8 months later...
  • 4 weeks later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.