How to synchronously get tag values

Hi,

I wanted to have a bit more information about how scan classes are functioning. Indeed, after some research and experimentations, my colleagues and I have noticed unexpected (from our comprehension view) behavior from how scan classes perform.

Current situation: all of our scan classes are set in “Subscription” mode (as recommended) with multiple granularity according to the type of tags. On the other hand, we have a custom module using a TagChangeListener that allows us to retrieve tag values on the fly and this works well enough.

What we want now would be to get the tag values in a synchronous way: even if the value doesn’t change, we want to get it for every fixed period of time. But currently, tagChanged() only reacts when the value changes, so that doesn’t help us anymore. I thought I could have those values by using the tag historian but no, values aren’t logged on scan class rate.

So I was wondering if there was a better way to achieve that than just simply browse and read manually tag values every time (which kind of sound as a brute force solution for me)?

Thank you in advance for your help !

Synchronous access to a collection of tags, without regard to changed values, is always going to be a problem with anything coming from an OPC subscription. By definition, OPC subscriptions only report changes, and no faster than the subscription pace. And arrival of change notifications is explicitly unordered. The behavior you are seeing is by design.

Some things to consider:

  • Setting tags to OPC Read instead of Subscribe will produce additional traffic between Ignition and the OPC server–internally for the built-in server–but will not produce any additional tag change events, IIRC.

  • Transaction groups can perform recording as you describe, to wide tables of your own design, based on time or a subscribed trigger followed by OPC Read mode for the other items. Necessary if you need to ensure values are read from the source after the trigger changes.

  • The above transaction group behavior can be implemented in scripts that use system.opc.read*(). Typically using a tag change event on a trigger. While more work to create and maintain, this offers hand-shaking options with PLC logic that transaction groups cannot do. And avoids the purchase of the SQL Bridge module, if that is a concern.

2 Likes

Hello @pturmel thank you for the response and sorry for the late reply.

My team will see if the purchase of the SQL Bridge module is worth it or not. Meanwhile, I’m investigating on my side to find work around solutions. I didn’t quite understand the way you’re suggesting to implement the same behaviour.

When you say “using a tag change event on a trigger”, are you suggesting that it is possible to modify the trigger of the tag change event ? This sounds weird. Otherwise the only way I can think of to produce the same result would be using the “Timer” Gateway event script. But for use, that would be way better if all the logic could be in a custom module, not scripts.

Thanks again !

1 Like

No. What I mean is, if you have a single value from the PLC that changes to signal the need to record everything else, then use on OPC tag to subscribe to that value. When it changes, the tag change script would read all of the other PLC values using system.opc.read...() without having those values in OPC tags. If there are multiple PLC values that are needed to determine when to record, a timer script probably is the best solution. But in either case, using a OPC read after the trigger is what ensures consistent data.

Hello @aimee.banmber ,

Did you ever figure out how to archieve this? I’m developing something similar, I need to get the tag values every number of seconds so I can do a moving average using Apache descriptive statistics .

In order to do this subscribing to the tag change, I would need to save the timestamp and do the calculations based on this. Is there any other option? I fear that registering a thread that uses GatewayHook.getGatewayContext().getTagManager().readAsync() will result in performance and concurrency problems.