Jump to content

Reading from multiple RS485 MODBUS RTU Slaves


Recommended Posts

I've long been doing this for a large program that I maintain. Depending on the system, we communicate with 2-8 slaves. From each slave, we do a read coils, read holding registers, and preset holding registers. The number of slaves is also dynamic, since they could fail or be disconnected for maintenance. This has caused issues in the past since the functions timeout and retry, slowing down the whole loop. To resolve this, we short circuit if the first read operation fails for a slave, we skip the registers.

In the end, our solution has basically been to use many latching MBs to round-robin through all the requests. We also short circuit if we know the particular setup will have less than 8 slaves. This ends up having a subroutine that has a bunch of rungs that all resemble each other, check a couple of MB to see if the previous request was successful/failed, run this one, set an MB for success/failure. At the end, we reset all MBs and start from the top.

Is there a better way? How do you deal with having slaves that might be temporarily taken out so that it doesn't slow the communication down since it is sequential? It doesn't help that many slaves don't support more than 19200. Is going for MODBUS TCP the ideal solution here? One of the reasons I am seeking alternate solutions is that now we're running into slaves that we have to read from multiple times since the telegram has a size limit, so instead of doing 3 MODBUS functions per slave, we might have 5 or 6, and that just makes for some repetitive and slow loop through all slaves.

Link to comment
Share on other sites

  • MVP 2023
2 hours ago, Manual said:

we have to read from multiple times since the telegram has a size limit, so instead of doing 3 MODBUS functions per slave, we might have 5 or 6,

This sounds  like you are doing the biggest read length you can, and then picking out relevant areas using logic in the PLC.  But is this what is actually happening?  It can make a huge difference to the number of reads needing to be done.  ie read a block of 99 and using PLC logic to pick out 6 totally separate registers spaced well apart in that sequence.

For the retries, you could drop them completely and work on the basis of if you get a response most of the time that will be ok.  I personally retry once, but I know that others here prefer the no retry method.  This would then automatically do the same delay, but might need a self-correction attempt every minute or so, to recognise when the unit comes back online.

cheers, Aus

Link to comment
Share on other sites

23 hours ago, Ausman said:

This sounds  like you are doing the biggest read length you can, and then picking out relevant areas using logic in the PLC.  But is this what is actually happening?

Yes, for the most part. In our typical setup, the slave drives allow us to configure a custom telegram with all the data we want to read, so it happens in a single read. The one that I am having issues with, the customer wanted custom drives, so we're adapting to use those. Unfortunately, this drive doesn't have a way to setup a custom telegram, so we're reading from their standard locations. Normally I would just read one big block of data and selected what I need PLC side, but this drive limits each response to 64 bytes, so I can't get all the data I need.

Any thoughts on the latching MBs? It seems so repetitive and wasteful, not to mention if you need to add more reads like we do in this case, you end up having to shift everything around and add even more MBs. I've been thinking about using an integer and incrementing each time to know which command/response set it's on and it would allow me to skip by incrementing in multiples rather than having all these MBs.

For reference, here is what a single drive communication looks like, it takes 3 MBs to track. One for the status read, one for data, and one for the write. Now with this drive, I have to do 2, maybe 3 more reads, so it'll take 6 round trips with 6 MBs to track. Then just have rinse and repeat 7 times. I just feel like there should be a better way?

 image.thumb.png.a1d16630c120a34eae216f3d0ba384c2.png

Link to comment
Share on other sites

  • MVP 2023

In your case my view is that it might be easier if you worked on a counter system. 

Set up a counter based on SB15.  Then have your various read/writes based around the counter progressing  and using compares to trigger each operation.  Essentially the same as the MB method, but the advantage is that you can tweak timings to best effect, and also easily manipulate the count to jump past non-responding units. 

Once the count reaches the end of the operations for the last unit, it resets to 0 and starts again.  This method works well, and I've used it to good effect.  Your timeout needs to relate to the longest period for the operations you're doing.  You have to allow enough time for the full timeout plus any retry (if you're doing so) and add a few scans to that to ensure you don't run into buffer issues.  Also remember that if there isn't a response in the first place your timeout time X retries is your total time.  But don't forget that you can also monitor your MBus in Progress MB and use that to jump the counter to the next operation if the comms are ok, but again...add a few scans to fully clear the buffer.

I have harped on about the buffer because I have found that the progress MB will signal ok, but doing the next operation immediately can eventually run into issues as the buffer is not fully cleared.  ie The captain of the PLC boat says "Aye me hearties, we've hauled in them there anchor chains.  Crank up the props immediately and get back to your other jobs"  whereas the deckhands go "But we haven't put the safety shackles in and the anchor might run out on it's chain over time and foul the props...you stupid ol' git."

If you find you could do things to a finer degree than is available using 1/10 sec, use a count based on an interrupt routine.  Search help for "1.25" and select Interrupt Routines which should be at the top of the list.   You can use 2.5mS or 1.25mS.

Others will likely chime in with the merits of shifting to TCP, but it might be worth you trying this method and spend some time fine tuning via trial and error for best effect.

cheers, Aus

Link to comment
Share on other sites

I would use a machine state using an MI register to track the current step of each slave, e.g.:

10=reading slave 1 group 1, waiting for response.

12=no response slave 1. Jump to slave 2.

14=response ok slave 1 group 1. Process data

15=reading slave 1 group 2, waiting for response.

17=no response slave 1. Jump to slave 2.

18=response ok slave 1 group 2. Process data

20=reading slave 2, waiting for response.

...

 

In my applications I´ve not needed to add delays between slaves.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
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...