Our main use of Ignition is as a reporting tool. I have been asked to develop a mechanism for determining if a tag has not changed its value within a given time interval.
I can think of a few ways to accomplish this:
Set up a Gateway Scheduled Script that pulls history data and verifies that the last change is within the interval.
Use a Tag Value Change script on each tag of interest which records a timestamp to a memory tag on change. Use an expression tag to compare that memory tag with the interval.
Similar to #2 but uses a Gateway Tag Change Script to record the timestamp.
I thought I would ask here if anyone had a suggestion on how they might go about accomplishing this.
The main issue I see with #1 is I would have to either keep a hard coded global list of tags that need to be checked, or run the verification for All historical tags. Both of those things are easy enough to accomplish, but 1 leads to extra maintenance that can lead to points of interest being not being added, and the other could result in nuisance notifications because some historical tags may be expected not to change within the set interval.
With #2, while probably acceptable, I generally try to avoid value change scripts on tags. This can be avoided by utilizing the method of #3, but I'm also not a huge fan of potentially 1000's of memory tags that are utilized for only this purpose.
I don't believe that alarming is a viable option as it may be that a value is within acceptable ranges, but just hasn't changed within the interval. The intent is to only have one interval, although I can see where there might be in the future a desire for multiple.
Depending on the number of tags and how often the list would change,
I might lean towards creating a UDT type for these tags that does #2 internal to the UDT with an alarm state for no change since timestamp + RangeParameter from a parameter on the UDT.
This way you could actually have different ranges for each tag if you wanted.
With this you could even setup a sql table and write them out to it for reporting.
What about using a separate expression tag for each tag in the UDTs that you want to monitor with an expression like (of course adjusting the reference tag and the time period that you want to use:
I know this is using expression tags for these, but with some clever nameing like ReferenceTag_Age or something you could potentially make it easy to pull/filter these tags to see the live "age" of the data.
Does a referenceTags timestamp change only on a true value change? Or does it change when the referenced tags timestamp changes? My understanding is that the timestamps for OPC tags are representative of when the value was last updated, but that doesn't necessarily indicate an actual value change. For instance, in this case I am not concerned with bad quality, so long as the quality issue is resolved within the interval.
I thought the timestamp of tags updated only when changed....since OPC tags are subscribed, the OPC server doesn't send any value updates unless the value or quality actually changes. The polling of the tags happens on the OPC side, but should only be reporting by exception, essentially.
When I say reference tag, I also meant that's just the tag the expression is referencing, which could be any tag...really an OPC tag in the real world.
I have a system in my office right now that's connected to the PLC, but there's no I/O (so I/O points are static) and the values are showing a timestamp of when they last changed....which was 5 days ago (when I upgraded to 8.1.43) even though it's actively polling the PLC, and it has a license, so it's not outdated due to the trial timer timing out.
I guess I didn't realize that function even existed. Definitely an easier solution than the expression I suggested and allows for excluding a quality change if needed. Only difference is that's a true/false and the dateDiff would tell you how old the value is if that's a concern they would have to report on.
Can you elaborate on your PLC Heartbeat method? We read a boolean tag on the PLC that changes on/off every minute. We then have a value change script to write to a boolean memory tag that has alarms for detecting if the value hasn't changed in a certain amount of time (stuck on or stuck off). We don't have alarms directly on the OPC tag because (IIRC) they don't evaluate if the PLC goes offline and comes back online with the same value for an extended period of time.
Your better bet would be to follow what's suggested in this thread. Get rid of the value change script and go with one of the expressions given. It will use less resources and probably be more reliable. Personally, I would probably increase the frequency of the heartbeat tag as well. One minute is an eternity in PLC time. Between heartbeats of PLCs, I have them toggle as fast as possible (For example, I have side A (could be either) mirror the bit state of side B, and side B inverts the value from side A.) In this way, they toggle as fast as possible and both can monitor for a lack in change.
We generally use Rockwell Logix processors but the same methodology should work.
We grab the WallClockTime - Current Value (which is a LINT) that is always changing, as long as the PLC is in RUN Mode. You could do the same with just a simple counter that resets.
Then on the Ignition side, we have a UDT that has the heartbeat value in it that we are reading from the PLC.