Modbus Slave/Server to Generate Read Only Tags

I have been working on creating modbus tags that directly mirror an OPC-UA tag.
The module I am utilizing is the Advanced Modbus Module from Automation-Pros.

For safety and security reasons, I want to allow certain tags to be read by a customer without them accessing the controls network. Some customers can pull the OPC-UA tags and avoid this altogether but some customers require modbus.
I had a brief phone discussion with Phil Turmel about achieving this and have set up a time to video chat and work through the challenge next week.

In the meantime, I have been trying a few different things to get this working and feel like I am pretty close to achieving the desired outcome.
Here is the current gateway script which is working as I intend for a single tag:

My next goal is to get multiple tags to continuously update and mirror to their designated modbus addresses. Here is what I have tried so far:

Here was my first unsuccessful attempt

Here was my second unsuccessful attempt

Anyone have thoughts on how to accomplish this?

1 Like

I think I solved my issue.

Firstly, I had a syntax error in the second modbus tag I was trying to write to.
It should have been:
"[default]Slave1/Unit 1/(4) Holding Registers/Group _ 1: 1_HR0-999/1_HR00001 aka 400002 (Short)"
Instead of:
"[default]Slave1/Unit 1/
(4) Holding Registers/Group _ 1: 1_HR0-999/1_HR00000 aka 400002 (Short)"

Secondly, I decided to use a timer script instead of a tag changed script. This way the values will be updated all the time, especially upon gateway startup when there haven't been any tag changes yet.
Here is the timer script that is working correctly:

Also, avoid including the aka 400001 (Short) fragment and grouping fragments in your tag names. That happens when you drag and drop from the OPC Browser to Ignition's Tag Browser.

Drag and drop is not appropriate for large quantities of tags--use it just to get OPC Item Path examples that can be used, after renaming, in UDTs or in scripted tag creation.

You might want your destinations to be 1.IRxyz instead of 1.HRxyz, as the former is fundamentally read-only from any external client.

Phil, I was exploring more options for adding tags to the slave device and was hoping to get your opinion.

I have a tag list that I import into the browser for device 1 and I took this same list, used find/replace to change the device name to slave 1. I then imported this new list into my slave device. Almost all of the tags seem to be functioning correctly except the Uint16 registers. (any idea what might be wrong with the Uint16 tags?)
Here is an example of the tags paths:

[default]_Slave1_/AllTags/Binary Points/5th Harmonic Inhibit 1136

I want the registers to be read only so I will have that box checked for the tags in the slave device but was curious if this is how you would recommend setting up the tags vs using a script to pair device tags to slave tags.

Bit references within registers are not allowed with US or any other modifier. Just use 1.HR1136.4

See page 4 "Modbus OPC Addressing" in my user manual.

You cannot make holding registers read-only that way, or any way. Setting the Ignition tags read-only will prevent Ignition from writing the tags. A connected client will still be able to use the write function codes for holding registers.

If you want read-only for connected clients, use IR instead of HR.

Perfect! I must have missed that point when reading.

So Importing the same tag list into the slave device after changing all of the HR's to IR's would be the better alternative to scripting tag pairs? This method would be much faster for me on the front end development.
What would stop a connected client from knowing this and just changing the IR's back to HR's?

Do you mean another Ignition instance that is a client pointing at the instance with my module? If so, yes.

If you are only writing the live data into IR, then accessing HR would be meaningless. You could even turn the HR address range off.

Yes a slave device within the advanced modbus manual.

I will look into turning the HR address range off after making these changes.


I changed all of the OPC Item Paths from HR to IR in the JSON file and after importing them into the designer tag quality now shows bad for all the tags. Am I missing something here?

Did you enable any range of IR registers? Are these the tags that point at the slave to which you are publishing? (Don't change the tags that are pointing elsewhere.)


Huh. Looks fine. Can you read/write that address with the Quick Client? (What do the tag diagnostics say? Have you restarted the device after changing settings?)

Yes I have restarted the device and the designer

Look for typos. Try recopying the OPC Item Path from the OPC browser to paste there.

Just closed everything and restarted my laptop and the values now show up with good quality!

Phil, last question for today.
I thought I had the values in the slave device matching the ignition device but I was wrong and now I'm struggling to figure out how to link the two.

Could you give me a quick rundown on how to make the slave device tags match the existing ignition device tags?

There's no automatic link. You must use scripting to write to the slave addresses. You can use tag valueChange events on every source tag, or a gateway tag change event subscribed to all of the source tags, or use a timer event to bulk read the source tags on a pace.

Whichever method you choose for handling incoming values, you must take them and either write them directly to the slave OPC items (with system.opc.writeValues()), or write them to other Ignition OPC tags (with system.tag.writeAsync()) that point at the slave OPC items. From your OP, you've chosen the latter approach. One way or another, you must have some configuration list, or some algorithm, that can be used in your script to direct the value to the correct item in the slave.

In your OP, you just used constants for a single source and single destination. That won't scale, of course, but is very simple for a small number of tags. Or, perhaps, simply make a folder heirarchy where the source and destination tag path are identical except for the first folder name. Then you can "compute" a destination tag path with simple string manipulation.

However, if I were to do this, I would write a script that can parse the OPC Item Path of a source tag and reassemble it with the substitutions needed for your destination. Then you don't have to make a second set of tags--just write directly to the destination OPC items.

Thanks for the response! This one has me a bit stumped. I have tried a few different methods and still no luck. Any chance you could provide a sample script?

Give me a bit. I'm creating a comprehensive example.

1 Like