I used a ProSoft MVI69E ModBus RTU module in a CompactLogix chassis. It’s a solid setup that I would use again. Unless you know you will only need a small amount of data from one or a few devices and need to save money, I suggest the enhanced version over the lite model. At the time I bought it, I had no plans for the second serial port but ended up using it as a programming port for setting up a sensor from the HMI without needing to break out a computer to use special software to program a sensor. The lite has fixed 240 registers in and 240 out. The enhanced has 10000 registers for in or out. I used 900 in. That would have been a hassle to work around. My only complaint is I had to make my own mounting bracket for the DB9 breakout boards. We use several ProSoft MVI56E-MNET ModBus TCP ControlLogix modules that have been trouble free for years.
Using ProSoft Configuration Builder, it’s easy to create a AOI rung to import that creates all associated PLC tags. The learning curve for me was understanding memory allocation. I was still confused after watching their videos. As the project developed and I understood better, I deleted my first import and imported a new version.
I’ll try to summarize memory: The module has internal memory, register locations 0 to whatever. You setup a range to be read data that’s big enough for data to read plus module and command status that you want to monitor. If you will be sending data, choose a register range for write data. In the example below, module registers 0 to 899 become PLC tags MBS.DATA.ReadData[0] to MBS.DATA.ReadData[899]. Module registers 900 to 959 become MBS.DATA.WriteData[0] to MBS.DATA.WriteData[59].
That was the part that took me a while to understand. The rest is normal ModBus commands. In the example below, I'm reading 22 registers each from a network of 20 or 24 sensors on module port 1. This data goes to module registers 0-599. I'm wasting three bytes between each sensor to have the data start at 0, 25, 50, or 75. Module registers 600-624 are for a single sensor on port 2 of the module.
You can monitor status of the module and commands. For whatever you want to monitor, you will choose a range of your read registers to put that data. I didn’t care about module error/status block pointer and disabled that with -1. I did want to see port 1 command errors and started that data in register 710 to match up with node 10. (command error offset) I'm essentially using part of registers 700-799 and wasting the rest. In registers 800-899, some are used for port 2 command status, the rest are unused.
Module registers 900 to 959 in this example are not used in the module commands. I have a routine that populates some write data to trigger a ModBus write to change node number of a sensor on port 2.
I posted some examples from this project here.
http://www.plctalk.net/qanda/showthread.php?p=785758#post785758 This was before the project was complete and these screenshots show different register numbers than the final version.
Port 1 is reading data from the network of 20 sensors. There’s four more setup if we expand the system. Port 2 is trying to read a range of node numbers to determine if one is connected.
There’s probably some situation where you could read data to a module register that’s not mapped to a PLC tag if you only wanted to write it to another device.
Here’s copy / paste from the final build of ProSoft Configuration Builder:
# Module Information
# Last Change: Jul. 28, 2018 00:00
# Last Download: Never
# Application Rev:
# OS Rev:
# Loader Rev:
# MAC Address:
# ConfigEdit Version: 4.4.17.0
# Module Configuration
[Module]
Module Type : MVI69E-MBS
Module Name : MVI69E-MBS
Module Name : MVI69E-MBS
Read Register Start : 0
Read Register Count : 900
Write Register Start : 900
Write Register Count : 60
Backplane Fail Count : 11
Error/Status Block Pointer : -1
Initialize Input Image : No
Block Transfer Size : 60
Slot Number : 1
[Modbus Port 1]
Start Active : Yes
Type : Master
Protocol : RTU
Baud Rate : 19200
Parity : None
Data Bits : 8
Stop Bits : 1
RTS On : 0
RTS Off : 0
Use CTS Line : No
Response Timeout : 500
Retry Count : 0
Minimum Command Delay : 0
Error Delay Counter : 10
Inter-character Timeout : 0
Command Error Offset : 710
Enron-Daniels : No
[Modbus Port 1 Commands]
START
# Enable Internal Address Poll Interval Register Count Swap Code Node Address ModBus Function MB Address in Device Override Value Upon Error Comment
1 3 0 5 22 0 10 3 5200 0 # Pump 1
2 3 25 5 22 0 11 3 5200 0 # Motor 1
3 3 50 5 22 0 12 3 5200 0 # Pump 2
4 3 75 5 22 0 13 3 5200 0 # Motor 2
5 3 100 5 22 0 14 3 5200 0 # Pump 3
6 3 125 5 22 0 15 3 5200 0 # Motor 3
7 3 150 5 22 0 16 3 5200 0 # Pump 4
8 3 175 5 22 0 17 3 5200 0 # Motor 4
9 3 200 5 22 0 18 3 5200 0 # Pump 5
10 3 225 5 22 0 19 3 5200 0 # Motor 5
11 3 250 5 22 0 20 3 5200 0 # Pump 6
12 3 275 5 22 0 21 3 5200 0 # Motor 6
13 3 300 5 22 0 22 3 5200 0 # Pump 7
14 3 325 5 22 0 23 3 5200 0 # Motor 7
15 3 350 5 22 0 24 3 5200 0 # Pump 8
16 3 375 5 22 0 25 3 5200 0 # Motor 8
17 3 400 5 22 0 26 3 5200 0 # Pump 9
18 3 425 5 22 0 27 3 5200 0 # Motor 9
19 3 450 5 22 0 28 3 5200 0 # Pump 10
20 3 475 5 22 0 29 3 5200 0 # Motor 10
21 0 500 5 22 0 30 3 5200 0 # Pump 11
22 0 525 5 22 0 31 3 5200 0 # Motor 11
23 0 550 5 22 0 32 3 5200 0 # Pump 12
24 0 575 5 22 0 33 3 5200 0 # Motor 12
END
[Modbus Port 2]
Start Active : Yes
Type : Master
Protocol : RTU
Baud Rate : 19200
Parity : None
Data Bits : 8
Stop Bits : 1
RTS On : 0
RTS Off : 0
Use CTS Line : No
Response Timeout : 500
Retry Count : 0
Minimum Command Delay : 0
Error Delay Counter : 0
Inter-character Timeout : 0
Command Error Offset : 801
Enron-Daniels : No
[Modbus Port 2 Commands]
START
# Enable Internal Address Poll Interval Register Count Swap Code Node Address ModBus Function MB Address in Device Override Value Upon Error Comment
1 1 600 5 22 0 1 3 5200 0 #
2 1 600 5 22 0 2 3 5200 0 #
3 1 600 5 22 0 3 3 5200 0 #
4 1 600 5 22 0 4 3 5200 0 #
5 1 600 5 22 0 5 3 5200 0 #
6 1 600 5 22 0 6 3 5200 0 #
7 1 600 5 22 0 7 3 5200 0 #
8 1 600 5 22 0 8 3 5200 0 #
9 1 600 5 22 0 9 3 5200 0 #
10 1 600 5 22 0 10 3 5200 0 #
11 1 600 5 22 0 11 3 5200 0 #
12 1 600 5 22 0 12 3 5200 0 #
13 1 600 5 22 0 13 3 5200 0 #
14 1 600 5 22 0 14 3 5200 0 #
15 1 600 5 22 0 15 3 5200 0 #
16 1 600 5 22 0 16 3 5200 0 #
17 1 600 5 22 0 17 3 5200 0 #
18 1 600 5 22 0 18 3 5200 0 #
19 1 600 5 22 0 19 3 5200 0 #
20 1 600 5 22 0 20 3 5200 0 #
21 1 600 5 22 0 21 3 5200 0 #
22 1 600 5 22 0 22 3 5200 0 #
23 1 600 5 22 0 23 3 5200 0 #
24 1 600 5 22 0 24 3 5200 0 #
25 1 600 5 22 0 25 3 5200 0 #
26 1 600 5 22 0 26 3 5200 0 #
27 1 600 5 22 0 27 3 5200 0 #
28 1 600 5 22 0 28 3 5200 0 #
29 1 600 5 22 0 29 3 5200 0 #
30 1 600 5 22 0 30 3 5200 0 #
31 1 600 5 22 0 31 3 5200 0 #
32 1 600 5 22 0 32 3 5200 0 #
33 1 600 5 22 0 33 3 5200 0 #
END
[Ethernet 1]
IP Address : 192.168.0.181
Netmask : 255.255.255.0
Gateway : 0.0.0.0
[Module Comment]
# Put Comment Here