2D Array with Siemens PLC (OPCUA)

I am new to using Siemens in Ignition and I'm having some issues taking in the array from a Siemens PLC. I have an array of 5200 tags with two tags under each array element. When using the OPCUA method I can only access first portion of the array and I am not getting the 2nd.

I was able to make a UDT for this but i cant understand how to do generate all of these tags with the multi instance wizard in the format that i need. The tag is built as a 20,20,13 array structure.

Ultimately I want to take a query from a recipe sql database and write to all of these tags at once to push the recipe to the PLC.

  1. What can I do to read the data like I normally can with Allen Bradley tags?
    A. Do I need to use a different driver?
    B. What format for the multi-instance wizard to format it and create 5200 tags in a 20x20x12 array?
  2. What is the best way to have a SQL query write to a tag array in the structure I have?



Thank you.

Hi @smoye,
i think you will be better to create a opcua tag from type document how read CurrentRecipe_Details and do the split inside ignition with derived tags. otherwise would will get really fast to the limit of the OPC UA server of your PLC.

See this post from @Kevin.Herron

regards

What happens in the Tag Browser if you change the datatype to Document instead of Dataset?

What you have here in the PLC is a 3d array of a structured type, which is not something Ignition supports very well. Ignition tags have no support for multidimensional arrays at all.

If I do it in a document type it still doesn't look right. I only get an index of 0-5200.
I can't reference a specific array location like 0,0,0 or 15,9,11 for example.



CurrentRecipe_Details.txt (370.7 KB)

Hmm, yeah, looks like it still gets flattened into a 1d array. I think that might change in Ignition 8.3, but not helpful here.

You might be better off if you just don't create tags for this at all. If you only need to to a bulk write to set the recipe then you can just do it from scripting.

The OPC Item Paths should be predictable - navigate to and drag in just the first "Enabled.EN" tag and "InspectionType.PV" and take a look at the path. It should be easy to build the entire list of paths to write in script.

1 Like

I was able to export the tag list, write a scrips to generate all of the tags and import them back into the tag browser but i now am encountering a TooManyMonitoredItems error.

In the image above I have the dataset returned from the DB in a label and the dataset returned from the base tag "NewRecipe_Details" but I dont know how to write a script to get the data from one dataset to the other.

Yes, unsurprisingly the PLC is telling you that you can't subscribe to this many tags.

As a workaround you can put them all into a tag group where the OPC data mode is "Polled".

Better, I'll suggest again, is to not make tags for these, and to read/write them via script when it's necessary. You can stuff the results of the read into a dataset memory tag if that's easier for you to work with.

1 Like

@smoye ,
Here is a little script to read/write the data of a specific position in your array without creating Tags

opcServer="SIMATIC.S7-1500.OPC-UA.Application:PLC_1" #Name of opcUA connection in gateway
nameDB="Recipes" #Name of DB in plc
nameDBArray="CurrentRecipe.Details" #Name of array in DB
#Position to read in plc
pos1=0 #First position
pos2=0 #Second position
pos3=0 #Third position

#Creation of itemPath
itemPath=('nsu=http://www.siemens.com/simatic-s7-opcua;s="%s"."%s"[%s,%s,%s]')%(nameDB,nameDBArray,pos1,pos2,pos3)

#Read tag data
tagData=system.opc.readValue(opcServer, itemPath)
print tagData

#write to tag
value= {"Enabled.EN":True,"InstectionType.PV":25}
system.opc.writeValue(opcServer, itemPath, value)

If you need to read write multiple tags you would then use the readValues and writeValues function

Here is my test db in TIA

Regards

3 Likes

Thank you for this. I modified the code to be in a for loop for all positions and did it in a readvalues and writevalues but it takes so long. I will not be able to write them one by one.
I stopped it at 10 minutes of running and it only got though 1/20th of the work.

# Parameters
opcServer = "Rocket_Park_NG_Panel_Thickness_PLC"  # Name of OPC UA connection in gateway
nameDB = "OP10_Recipe_DB"  # Name of DB in PLC
nameDBArray = "NewRecipe.Details"  # Name of array in DB
print opcServer
# Create list to hold item paths for all combinations
itemPaths = []

# Generate all item paths
for pos1 in range(20):  # 0 to 19
    for pos2 in range(20):  # 0 to 19
        for pos3 in range(13):  # 0 to 12
            # Append each itemPath to the list
            itemPath = ('nsu=http://www.siemens.com/simatic-s7-opcua;s="%s"."%s"[%s,%s,%s]') % (nameDB, nameDBArray, pos1, pos2, pos3)
            itemPaths.append(itemPath)

# Read all tag data at once, if supported by the OPC UA client
tagDataList = system.opc.readValues(opcServer, itemPaths)  # Assuming `readValues` method supports multiple item paths
print opcServer
# Check the results
for idx, tagData in enumerate(tagDataList):
    print itemPaths[idx]
    print tagData
    
    # Write values if needed (Typically requires individual paths unless batch writing is supported)
value = {"Enabled.EN": True, "InspectionType.PV": 25}
writeStatuses = [system.opc.writeValue(opcServer, path, value) for path in itemPaths]  # Batch write if supported

# Check write statuses
for idx, writeStatus in enumerate(writeStatuses):
    print itemPaths[idx]
    print writeStatus

You need to use the bulk variant of the read and write calls as he suggested.

On my side i just use your script to read bulk of tags and i have a time between 4 and 8 sec

The issue in your script is that the write is done one by one where you could also use a bulk write
Here is my code

timeStart = system.date.now()
# Parameters
opcServer = "SIMATIC.S7-1500.OPC-UA.Application:PLC_1"  # Name of OPC UA connection in gateway
nameDB = "Recipes"  # Name of DB in PLC
nameDBArray = "CurrentRecipe.Details"  # Name of array in DB

# Create list to hold item paths for all combinations
itemPaths = []
itemValues = []
# Generate all item paths
for pos1 in range(20):  # 0 to 19
    for pos2 in range(20):  # 0 to 19
        for pos3 in range(13):  # 0 to 12
            # Append each itemPath to the list
            itemPath = ('nsu=http://www.siemens.com/simatic-s7-opcua;s="%s"."%s"[%s,%s,%s]') % (nameDB, nameDBArray, pos1, pos2, pos3)
            itemPaths.append(itemPath)
            itemValues.append({"Enabled.EN": True, "InspectionType.PV": pos3})

# Read all tag data at once, if supported by the OPC UA client
tagDataList = system.opc.readValues(opcServer, itemPaths)  # Assuming `readValues` method supports multiple item paths
timeRead = system.date.now()
print "Time to read in millis: " + str(system.date.millisBetween(timeStart, timeRead))
system.opc.writeValues(opcServer, itemPaths, itemValues)
tagDataList = timeWrite = system.date.now()
print "Time to write in millis: " + str(system.date.millisBetween(timeRead, timeWrite))

Here is the result on 3 times read write on a 1513 on firmware 2.9.

Hi there a possibility to change the udt to contains all 13 last positions enabled0 to enabled12.
So instead o reading and writing 5200 tags you would only do it for 400.

Regards