Situation:
So, I've got a few AB ControlLogix L83s that control assembly processes. I do not control the programming of the logic in them. The PLC guy has a program that takes 5 data points and updates PLC tags specific for ignition. My program looks one OPC tag, and when it's greater than 0, asynchronously collects the other OPC tags using the system function and logs it to a DB through a value change script on the gateway tag. This value changes every event, at between 4 and 8 events every 33 seconds. The individual events can happen within half a second from each other, so I have the scan rate of the OPC tag at 250 ms. Ignition clears the tags as the 'handshake' to show ignition got and attempted to log the data
I have a few questions:
Am I doing this the best way possible?
Ideally, I'd have 100% accuracy on this as long as there's a connection between the PLC, Ignition, and the DB server. There's very few hang ups and disconnects, but they do happen when saves/edits to the PLC happen.
Rebrowsing Tags on Edit/Changes to the PLC:
When there's a PLC change, the OPC tags stall for a moment. I understand this as a feature, not a bug. I also know you can turn this off. What are the downsides to not rebrowsing on all changes, given that I don't need to worry that any of the PLC to Ignition tags are being changed?
Is there a way to use store and forward through scripting?
I want to avoid downtime if the database disconnects, and still log that data when available? Would I have to make my own system for that? I don't want to use the transaction groups, since they don't restart automatically, but am I wrong for wanting that?
For #1/#2, I would think turning off the rebrowse would be fine since none of your tags are changing. You could always use @pturmel's driver which does this more gracefully than the IA driver.
No, but close. Two flaws, and one potential flaw. More below.
Instances IDs and data types cannot change on any tag that is used by running logic, so turning off rebrowse is safe if only on-line edits are made. A rebrowse is required after any program download.
Yes, use system.db.runSFPrepUpdate().
Recommendations:
Do not use a tag value change event for this kind of script, as you are invoking system functions that can take many seconds to complete in some cases. Tag valueChange events run in a limited thread pool and it only takes a few scripts dwelling on long calls to freeze all tag scripting in the entire system. Use a Gateway Tag Change Event instead. (In the project's gateway events, not defined on the tag.)
If you are using system.tag.readBlocking() to retrieve the other values you need to push to the database, you cannot be certain you have the latest values. Use system.opc.readValues() to gather the freshest values.
Do not clear the trigger tag from Ignition. That can race with the PLC and make a big mess. Instead, echo the trigger tag to another PLC tag to acknowledge that you've handled that one. Ideally, the PLC would hold back on further changes when the trigger and echo do not match. (You would want your script to always echo the trigger, even when zero, to ensure synchronization.) Your system.opc.readValues() call should also reread the trigger and the echo at the same time as the others, so you can catch PLC overwrite conditions.
Consider asking the PLC guy to set up a ring buffer (queue) for several seconds worth of events, where the PLC moves the next set of data into the Ignition tags whenever the trigger and echo match. This would let you ride through communication disruptions.
Thank you. I didn't think to have a separate bit for call and response. At first look I was like, "why would it be any different?", but thinking on it, it really puts it so that the PLC is handling PLC stuff, and Ignition is handling Ignition stuff with minimal smearing between the two, while still communicating which step of the process both processes are at, in a way.
Kind of embarrassed that I completely missed runSFPrepUpdate(), but that explains why I couldn't find much on the forums for not being able to use S&F.
I'm currently working with the PLC guy to set up a functional buffer, and hopefully this becomes standard for all of our PLC to DB logging in the future.
A bit curious, are there a lot of advantages to using the Gateway Tag Change Event vs calling system.util.invokeAsynchronous() from a tag change script other than the limited thread pool size?
There are pros and cons. (Numerous discussions here on those.) But it is almost always preferable to system.util.invokeAsynchronous(). Starting new threads is a performance killer, and can run wild if you aren't careful.
Discussions like these (and more, if you tweak the search terms):