Reading ControlLogix Strings

Using Ignition 8 and RSEmulate v32 for some testing. Trying to get a string tag from my PLC program into Ignition. When using OPC browser I’ll get StringTag.DATA, StringTag.LEN and can pull those into Ignition, however .DATA is just the array of ASCII character codes. I want the Ignition tag to display the string text. How do I configure the tag?

Previously, I could point to StringTag.STRING and Ignition put it all together, but that was Ignition 7 with the legacy ControlLogix driver.

You have an OPC(UA?) connection to it or are you using one of the drivers?

OPC-Com through RSLinx Gateway since I’m testing with RSEmulate

Okay, nothing you can do on the Ignition side then. The server is choosing to show you a folder containing a LEN and DATA tag.

I don’t think you’re the first person to run into this issue/bug, but it’s not on our side.

edit: you might be able to reassemble then DATA bytes into a string using a runScript expression and some Jython trickery, though.

Thanks!

FYI for future readers, I just created a tag to store an ASCII Lookup table, then used an expression to create the string I required.

# Create the tag "ASII Lookup", and run this script once to build the lookup table.

header = ['code','char']
data = []

for i in range(128):
	string_value = chr(i)
	data.append([i, string_value])
	
newDS = system.dataset.toDataSet(header, data)

# Write to ascii lookup tag
system.tag.write('[default]PLC/ASCII Lookup', newDS)

Then create an expression tag “sourceUUID”. For my purposes, I’m reading a 36 character UUID from the PLC, so my tag has the following expression to get the character from the DATA element and concatenate the result. This is all I need for my RSEmulate test environment.

concat(
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_0_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_1_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_2_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_3_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_4_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_5_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_6_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_7_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_8_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_9_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_10_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_11_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_12_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_13_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_14_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_15_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_16_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_17_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_18_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_19_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_20_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_21_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_22_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_23_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_24_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_25_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_26_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_27_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_28_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_29_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_30_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_31_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_32_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_33_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_34_},'',0,1),
lookup({[.]../../ASCII Lookup},{[.]DATA/sourceUUID_DATA_35_},'',0,1)
)

You could also do the following, assuming you are bringing the data back as a list:
In a shared script somewhere (I put it in my shared script project, in a script called “ascii”):

def asciiToString(asciiList):
	return "".join([chr(o) for o in asciiList])
	
def stringToAsciiList(value):
	return [ord(o) for o in value]

Now in an expression tag, put the following:

runScript("ascii.asciiToString",0,{[~]ascii data})

You could also use a derived tag, to get read and write capabilities
For the read expression:

runScript("ascii.asciiToString",0,{source})

For the write expression,

runScript("ascii.stringToAsciiList",0,{value})

This script will run whenever the ascii data tag changes.

1 Like

To access the string version of the tag you simply remove the dot and anything that follows it.

It's different.