Tag Change Script Help

I have an OPC tag capturing photo eye sensor information and the value is the total number of items seen since the photo eye was installed. For example, it might read 9,456,789 and when it sees an item it changes to 9,456,790. Let’s call this tag Out Count.

On the Out Count tag I have a change script which writes the timestamp to another tag when the previousValue.value != currentValue.value. So I get a time stamp every time the photo eye sees an item.

I then calculate the minutes between the timestamp and now on a Duration tag. So I have a duration of 0 if there are items consistently being counted by the photo eye, and I have a duration >0 when there are no items consistently being counted.

I created a State tag by putting a tag change script on the Duration tag:

If the currentValue.value = 0 write the value of “Running” to the state tag and if the currentValue.value >0 write the value of “Down” to the state tag.

I have recently been asked to only change the state to Running if the photo eye sees an item consistently for 2 minutes. Due to the dependency of the duration on the state tag, I am struggling to figure out a way to keep the state from changing to Running and not lose the down duration when it sees an inconsistent new item. The other option I was given was to only return to a Running state if 88 items are seen. I need someone to take a fresh look at the logic and see if they can help give me some ideas.

I forgot to mention, that I have an alarm when the duration = 30 minutes. So I need to make sure the down duration doesn’t get reset if an item randomly passes the photo eye.

First I wouldn't do this. I would create an expression tag with the following expression:

if(not {path/to/duration/tag},'RUNNING','DOWN')

Second, if I had to do this outside of the device, which IMO is where it should be done, then I would probably use another tag to capture when the duration changed to 0 and modify the expression to something like this:

if(not {path/to/duration/tag} and dateDiff({path/to/duration/change/time},now(),'sec') > 120,'RUNNING','DOWN')
1 Like

Thank you @lrose, I made the changes and have been checking to make sure that if it has been a while since the last time the duration changed to 0, that this doesn’t create a false running state if the state tag evaluates before the change time is recorded. I have a tag change script that writes to the running timestamp tag when it = 0.

Now I just need to resolve for how long the state has been in the down state so when that duration gets to 30 minutes I can send an alarm. I tried to capture the timestamp when the state is down using a tag change script on the state tag, however, it appears that it is seeing a change in value which must be milliseconds because the eye doesn’t see a state change but the same timestamp is recorded as when the value changes to 0. How would you capture the time that the duration changed to 0 or the time has been in the down state? Is there a way to do this in an expression that wouldn’t evaluate if it saw a split second change?

Option 2: use a diagnostic level alarm on your duration tag. Set Active and Clear delays values.
My example is on a tag named Duration with an alarm named Down status
EDIT: Just saw where you were wanting to use an alarm. Feel free to up the priority. :wink:

Then, the expression on the status tag stays similar to what @lrose showed, just drilling down a bit farther:

if({[~]Duration/Alarms/Down status.IsActive},'DOWN','ACTIVE')

Thank you both. I went ahead and went with the expression tag @lrose provided. I solved my issue with the down timestamp updating when the state tag evaluates by changing the tag change script:

"offTime = currentValue.timestamp
onTime = previousValue.timestamp
time = system.date.secondsBetween(onTime,offTime)

if currentValue.value == “Down” and time >5:
system.tag.write("[.]Down Timestamp",system.date.now())"