Modbus Addressing with String and Script Design

Hello Community,

I have this simple example of what I would like to try, it seems to work but I would like feedback on the best design. I have a field device that I have connected to the Ignition gateway using Modbus TCP/IP.
I want to read the first 35 registers from this device. The value returned from each registers is ASCII number. example return 77 which is chr(77) which is "M".
Less desired option (sample example below):
creating 35 OPC tags each pointing to a register and pulling it all together with an expression tag.


The option above is a very lengthy process and could require 1000s of tags to the device.
I have this script that I have tested and it works pretty quickly in script console and give me the desired output.
image

I was planning to add this code as a script and then have an expression tag running on tag group execution which uses runscript('scriptName_here') which returns a string.

  1. Is there a better design?
  2. I have not tried the above yet because I am running into a road block which is testing the script.
    When executing the script in console, it just keeps running, without any output.

Has anyone ran into this issue?

I know most people will say to try HRS for string. When I try this with an OPC UA Tag, setup as 1.HRS0:35, it will return a value of "M" but nothing else. see as below.

I would rank your options in the opposite order provided:

  1. A tag with HRS
  2. A tag running a script
  3. Many individual tags

I expect playing around with HRS to be the most fruitful. The script can be improved a lot, by the way:

def readStringRegister(start, end, server="Ignition OPC UA Server", device="MLII_X", unitId=1):
	qvs = system.opc.readValues(
		server,
		[
			"ns=1;s=[{device}]{unitId}.HR{i}".format(device=device, unitId=unitId, i=i)
			for i in xrange(start, end)
		]	
	)
	return "".join(chr(qv.value) for qv in qvs)
1 Like

You have start =+1 at the end of your loop. Which is simply assigning a +1 to start over and over. You might have been aiming for the += operator, but you should simply use a for loop with a range().

1 Like

Thanks. Totally my fault. This corrected the script console.

I guess my process was using building blocks.
Your script is very nice! I will keep exploring the HRS route.
I know it brings back a good value but it only presents the first character in the string.
I feel like this has do to with gateway connection setting with the modbus device.
Ill give it another try tomorrow.
Thanks for quick response.

That's because modbus registers are 16-bits, and therefore hold two 8-bit characters. The upper byte of your register is null, which terminates the string.