Best Practice for Aggregating Multiple OPC Tags into a Single Memory Tag Without Asynchronous Update Conflicts using a Mitsubishi Driver

Hey all — first-time post here, hoping to get some insight into a workflow challenge I'm facing with data aggregation in Ignition Edge.

I'm working on an Ignition Edge Gateway with a local Ignition OPC UA server subscribed to a Mitsubishi iQ-R PLC. The OPC connection is stable, and I've successfully created individual OPC tags from the device registers. These tags represent serial identifiers and a variety of measurement values. I’m trying to combine them into a structured JSON memory tag and store that value once per cycle when the PLC updates the relevant memory block.

The PLC executes a block move to simultaneously populate the memory area for all values. However, in Ignition, I’m observing asynchronous updates across tags. Even though the data is loaded into the PLC memory space at once, the tags in Ignition are updating with delays between them. This results in my JSON expression tag updating multiple times per cycle, with partial or duplicated data, as each OPC tag refreshes individually.

I initially created a string expression tag to format the data into a JSON object:

"{" +
"\"Tag1\":\"" + {[.]../Tag1} + "\"," +
"\"Tag2\":\"" + {[.]../Tag2} + "\"," +
...
"\"Tag_n\":\"" + {[.]../Tag_n} + "\"" +
"}"

This worked structurally, but it updated every time any one of the source tags changed, leading to partial entries or duplicates when historized.

To control write timing:

  • I added an onChange script to each source tag that increments a memory tag (Collection Trigger).
  • When the trigger reaches the expected count (i.e., number of JSON fields), a script reads all tags and writes a final JSON string to the output tag.

This reduced the frequency of writes but failed when one or more tag values didn't actually change (i.e., no onChange fired), causing the count to never reach its threshold and blocking output entirely, so I scrapped this setting.

To mitigate duplicates and race conditions:

  • I used a delayed onChange approach where the expression tag only writes to the output memory tag if the serial number in the current value is different from the previous value.

This method improved consistency but still led to occasional mismatches or stale values depending on tag refresh timing.

Is there a best-practice approach in Ignition (e.g., scripting, tag group settings, or gateway logic) to ensure all tags are fully updated before writing? Could it be on the PLC-side or a driver setting?

Thanks in advance — happy to share further examples or testing results if helpful.

Example Settings



Use scripting to issue a single system.opc.readValues for all the tags you're interested in.

2 Likes

One way to set this up:

  • have a "trigger" tag (looks like you may have this already).
  • have a "reset" tag ("Resultant Tag"? not sure if that's what this is for)
  • use a gateway timer script to periodically read the trigger tag
    • when it's set, issue the system.opc.readValues
    • assemble your JSON object and write it to a document tag
    • write to the "reset" tag to tell the PLC you're done. it should either increment or reset the trigger tag. Never write to the trigger tag from Ignition.

This could also be a gateway tag change event script (not tag event script), instead of a timer script, and then the trigger just needs to be toggling or incrementing.

The point was to avoid a tag event script, in which you shouldn't do long-ish running blocking work like a system.opc.readValues call.

2 Likes