I am working several systems with CompactLogix 5380 PLCs that fill a UDT with data as a part is being made, latch a boolean to trigger a driven tag group to read the UDT, use a gateway event script on tag change (looking at an element in the UDT) to verify valid data, then write the data to a SQL table using a transaction group. On the first system that I setup, this is working without any issues. On the second system, it seems like there is a race condition; after I trigger the driven tag group, the gateway event script executes but not all of the data in the UDT is updated. Is there a better/more robust way to know when the UDT has updated/tag group has finished updating values?
Additional info on current setup:
partUDT definition:
bPassPart (Boolean)
bFailPart (Boolean)
iPartQuantity (Integer)
iDataID (Integer)
iTransactionID (Integer)
dtTimestampPLC (DateTime)
FailureData (UDT, different on each machine)
PartData (UDT, different on each machine)
Once a part is completed, data is loaded into a FIFO with the type partUDT. The FIFO is unloaded to the PLC tag PartDataToLog (controller scoped). Then PartDataToLog.iTransactionID is incremented. Then the boolean TriggerPartLog is latched. Once PLC gets status that the transaction group execution completed, it will unload from the FIFO (or wait for the FIFO to have more data).
On the Ignition side, TriggerPartLog (in a direct tag group) is used as the driving expression for a driven, one-shot tag group. The tag [default]machineA/PartDataToLog is in this driven tag group. There is a gateway event script which runs on tag change for [default]machineA/PartDataToLog/iTransactionID which does the following:
logger = system.util.getLogger("MachineA_LogDebug")
if not initialChange:
dataToLog = system.tag.readBlocking('[default]machineA/PartDataToLog',500)[0].getValue().toDict()
logger.info('bPassPart:' + str(dataToLog['bPassPart']))
logger.info('bFailPart:' + str(dataToLog['bFailPart']))
logger.info('bScrapOnly:' + str(dataToLog['bScrapOnly']))
logger.info('iPartQuantity:' + str(dataToLog['iPartQuantity']))
if (dataToLog['bPassPart'] ^ dataToLog['bFailPart']) and dataToLog['iPartQuantity'] > 0:
logger.info('Latching Trigger Bit')
system.tag.writeBlocking('[default]machineA/PartTransactionTrigger', 1)
else:
logger.info('Latching Error Bit')
system.tag.writeBlocking('[default]machineA/PartLogIgnitionError', 1)
On the first system that I setup, this works without issue. On the second system it does not work. If the current and previous parts both have bPassPart=True and bFailPart=False, it will work fine. When the previous and current part are not both pass or both fail, the log will show bPassPart=False and bFailPart=False. On the PLC side, PartDataToLog.bPassPart XOR PartDataToLog.bFailPart is never true.