Gateway Tag Change Script Triggered with no Reason

Hello,
I have written before similar topic, but I have not get any reply, so I am still trying to find solution. So here is the case: Ignition 8.04, Windows Server 2016,
the gateway tag change script below calculates the daily output (counter current value - counter starting value (StartCount4 Tag); if the counter is reset (which may happen with running at high speed machine as well, so in the transaction group zero value sometimes is not caught and visible), the counter previous value is assigned to PreviousBatchValue Tag, and in this case the output will be PreviousBatchValue + Counter (current value) - StartCount :

‘’'if not initialChange:
currentValue = event.getCurrentValue().getValue()
previousValue = event.getPreviousValue().getValue()

if  currentValue - previousValue < 0:

	sc = system.tag.readBlocking(["[default]GZPT32_Room4/StartCount4"])[0].value
	brb = system.tag.readBlocking(["[default]GZPT32_Room4/BatchResetBit4"])[0].value 
    pv=system.tag.readBlocking(["[default]GZPT32_Room4/PreviousBatchCount4"])[0].value
                                                 
	tagPaths = ['[default]GZPT32_Room4/PreviousBatchCount4', '[default]GZPT32_Room4/BatchResetBit4']
	values = [pv+previousValue, brb+1]
	system.tag.writeBlocking(tagPaths,values)


if currentValue > previousValue:

	sc = system.tag.readBlocking(["[default]GZPT32_Room4/StartCount4"])[0].value 
	cc = system.tag.readBlocking(["[default]GZPT32_Room4/Counter"])[0].value
	tt = system.tag.readBlocking(["[default]GZPT32_Room4/DailyOutput4"])[0].value
	pv = system.tag.readBlocking(["[default]GZPT32_Room4/PreviousBatchCount4"])[0].value
	
	total = pv - sc + cc 
	system.tag.writeBlocking(["[default]GZPT32_Room4/DailyOutput4"],[total])'''

Now, as you can see on the picture below, showing the transaction group, though the counter has not been reset, the script triggered and DailyOutput4, PreviousBatchCount and BatchResetBit has been updated.
Capture_20200911.PNG
N.B. BatchResetBit is just integer showing the number of Counter resets (at the beggining it was boolean tag , but after it turn out that the Counter might be reset more than once during the shift, so I left the tag name, despite the fact it is integer in fact, and not bit.
So, any ideas why the script executes randomly, about 8 -10 times per shift?

Your code quoting messed up and your indentation looks wrong. Please edit your post to ensure your code has three backquotes (these: `) above and below the code block.

Hope it is better now:

```if not initialChange:
        currentValue = event.getCurrentValue().getValue()
        previousValue = event.getPreviousValue().getValue()

        if  currentValue - previousValue < 0:

             sc = system.tag.readBlocking(["[default]GZPT32_Room4/StartCount4"])[0].value
             brb = system.tag.readBlocking(["[default]GZPT32_Room4/BatchResetBit4"])[0].value 
             pv=system.tag.readBlocking(["[default]GZPT32_Room4/PreviousBatchCount4"])[0].value
                                             
             tagPaths = ['[default]GZPT32_Room4/PreviousBatchCount4', '[default]GZPT32_Room4/BatchResetBit4']
             values = [pv+previousValue, brb+1]
             system.tag.writeBlocking(tagPaths,values)


       if currentValue > previousValue:

             sc = system.tag.readBlocking(["[default]GZPT32_Room4/StartCount4"])[0].value 
             cc = system.tag.readBlocking(["[default]GZPT32_Room4/Counter"])[0].value
             tt = system.tag.readBlocking(["[default]GZPT32_Room4/DailyOutput4"])[0].value
             pv = system.tag.readBlocking(["[default]GZPT32_Room4/PreviousBatchCount4"])[0].value

             total = pv - sc + cc 
             system.tag.writeBlocking(["[default]GZPT32_Room4/DailyOutput4"],[total])```

What is updating the batch reset value (in this case 8 to 9)?

If the counter has been reset, i.e. Counter’s previousValue > currentValue, Batch Reset will be incremented with 1, and previousValue will be assigned to the tag" PreviousBatchCount".

I recommend adding the following line to the beginning of your event script:

system.util.getLogger("Test").infof("Tag change initial=%s, event=%s", initialChange, event)

After the next unexpected trigger, look at your gateway log to see what event conditions showed up that you didn’t expect.

Thank you, pturmel, will do that and revert.

All right. Interesting results.


Indeed, the results for Counter current value (524306) and previous value (589906) , explain why the script was triggered (because currentValue - previousValue < 0), but they do not have physical meaning - the transaction group shows that the Counter was running normally and has not been reset (timestamps 12:15:18 - 12:16:18). Despite that the BatchResetBit has been changed.
Any comments?

Might be a bug in previousValue. I generally don’t use previousValue, so I’ve never seen this. (I tend to save currentValue in a project script global cache and use that instead.)

I am afraid I did not catch that, how exactly to avoid previousValue usage and use currentValue instead?

In your event, have a one-liner, like so:

someScript.myEventFunction(initialChange, event)

In someScript, use something like this:

myCache = {}

def myEventFunction(initialChange, event):
    cv = event.currentValue.value
    if 'someKey' in myCache:
        pv = myCache['someKey']
        # do something with pv and cv
    myCache['someKey'] = cv

I see. Thank you very much, pturmel!

Note that if you have many tags attached to the event script, you can use the tag name as the key, keeping them all in the same cache.

Well noted, thanks a lot!
By the way, I forgot to tell that I checked the logs from 3 machines (where the script was triggered wrongly), and always the difference between the current value and the previous value was appr. 65500 (close to 65536 (!)). So, it must be some bug indeed. Secondly, is there any chance this bug to being fixed in the latest versions?

Is the counter spanning two 16-bit registers? If so, you are probably seeing the side effect of reading the two registers when the PLC is updating the count. What kind of processor is this?

Also, I would expect you to have log entries showing that odd reading as the currentValue just ahead of the log entries showing it as the previousValue.

Yes, this is Modbus TCP/IP protokol and the counter is spanning two 16-bit registers. There are two different kinds of PLC involved in this case - Omron CJ1M and Unitronics SM35. This “effect” is observed on both.

It is a limitation of the protocol. It has no way to prevent PLC code from changing the values in the middle of a Modbus read operation. In this case it is rollover of the LSW where modbus gets the LSW just before rollover and the MSW right after rollover.

More advanced processors (like AB Logix) guarantee no such splitting if reading true 32-bit data elements, and no splitting when the PLC code uses the appropriate synchronous copy instruction for larger data blocks. (Yes, this kind of attention to detail is one of the reasons I’m a big fan of the Logix family.)

AB generally is not very common in Europe compared to the other brands. However, I have done few courses with AB and indeed, they seem very good. So, to solve my case, I see two solutons:

  1. Move the arithmetic operations ( logic) to the PLC. I already have done that for Unitronics and the problem is solved. For OMRON is more complicated, since stops (downtime) of the machines are not allowed in this moment, nor foreseen in near future.
  2. Use your tip above for project script global cache.

I suspect (2) won’t really help, as you really are split-reading a changing value.