I’m looking to create better comms between Ignition and my Allen Bradley PLC, specifically in the area of optimized PLC tag structuring. I’ve read many posts about optimizing comms, but I can’t quite find exactly what I’m looking for (or maybe it’s being said, but visual examples for me to grasp the concepts aren’t necessarily provided and the whole depth and complexity of comms optimization is fairly overwhelming). @pturmel’s #7b below is what I’m looking to do, but I’m trying to figure out the best way to accomplish it while still keeping the PLC code clean and readable.
In short, we use UDTs in our PLC code and we use those UDTs as InOut parameters for corresponding AOIs that handle all the logic. We instantiate the AOIs, but don’t use the AOI tag instances anywhere. All logic and HMI statuses refer to the UDT. Below is out Photoeye UDT structure as well as the AOI definition.
I’m grabbing values from different members from all over the UDT (for example, I’m pulling the Jammed value from PEXXXX.Faults.Jammed but pulling the Photoeye status from PEXXXX.Status.HMI and the Jam Time Preset from PEXXXX.Parameters.JamTimePreset). I understand it would be way more efficient to group these all in a .HMI member structure in the Photoeye UDT, but my problem is I have certain tags (primarily manual run/jog controls for things like motors) that I’d like to have a very quick poll rate so the HMI doesn’t feel slow to respond when manually controlling devices. But I don’t want to overload the comms by making everything a super quick poll rate. On-screen statuses like conveyor running status doesn’t have to update quite as quick and things like device descriptions that I pull from the UDT and display on popups can have really slow poll rates because they won’t be changing often if ever.
Am I better off clumping everything together in the UDT in a single HMI member structure and having it update super quick because it’ll pull it all at once and be plenty efficient? Or would making separate HMI member structures based on update rate be better? Within the HMI member, I’d imagine I’d just have a relatively small array of each data type I need (bool[10], dint[10], float[5], string[5]) and I’d just map different things to each one based on the main UDT type. Either of these methods I believe would be better than how I have it, but is it enough? Or do I need to go so far as to make arrays of HMI structures for each poll rate and correlate members of those arrays to each existing device (e.g. PE123_4 would correspond to HMI[1]). This would require making the HMI tag instance an InOut parameter of my device AOI or making a new AOI for each device type to map the statuses to the HMI instance. This would also require correlation in Ignition as well. I’d rather not have to know to add HMI[1] as the PLCTagName parameter for PE123-4 instead of just PE123_4. That all just seems overcomplicated, but I have no idea if it’s necessary or totally overkill (even for a larger system). I haven’t had a chance yet to toy with one method vs another, but I figured I’d ask the question to hopefully get pushed in the correct path. Thanks in advance for any and all help!
I know what the best practice answer will be as far as grouping members of UDTs by like poll rates, but as a practical example, I'm finishing up a job with 100K tags spread across 12 Logix PLCs that includes as an example a motor UDT that has forward, reverse and stop PBs in it along with status, faults, amps, speed, etc. Even though the best practice would be to have the PBs as one poll rate in its own UDT, I have PBs as tag groups of 150ms, and the rest at a 1000ms poll rate in that one motor UDT and I have not seen any detrimental performance. My PB actions are instant (no lag), all my devices are at 0% load for all tag groups, and my gateway is just motoring along. I’m aware that it’s perhaps not the most efficient it could be because the multiple poll rates cause additional reads/writes the way the Logix driver works, but it has worked flawlessly for this install.
As for arrays of UDTs, I do leverage this where practical. I have an array of EStop_Input UDTs for example in CLX that covers all the estop PBs/Pullcords. But I still prefer individual Valve, Motor, Tank type UDT instances instead of an array of Motors. There’s a tradeoff between the best possible ignition comms efficiency and the readability of the PLC code for troubleshooting and maintainability.
I do something similar, but with your single UDT that's an InOut parameter, I read all of those at the same fixed rate. In my case that's 1000ms. I have tags on my AOIs that I do use though and use leased tags on them to read them slowly (60 sec when not leased and 5 sec when leased due to it being only Faceplate configuration tags). For strings that are pretty much static, I read them at a fixed 60 sec rate amd put them in a separate UDT.
As for what Robert said, I personally don't believe there's any need for pushbuttons to read at that rate. Writes are sent immediately, not on a poll, so there's no need to read them quickly.
On our PLCs, we're reading 45k on our safety system and 55k on the process controller with 0% overload.
That’s interesting in regards to instant writes. We went to the 150ms poll on PBs as a standard on a much earlier install where there was button response lag. The faster poll rate did resolve the lag, and we’ve just carried over that standard practice since. I was only involved on the tail end of that install as my first intro to Ignition and never questioned it as it worked. Now, I’m questioning it Did anything perhaps change between the legacy CLX driver and now, or has this always been the case and part of the fundamental architecture of the driver?
I wouldn't think anything has changed as that's not really driver specific but just the way Ignition and OPC works in general I believe. On any tags with longer subscription times, I do have optimized writes enabled with a time 2 seconds longer than my subscription time. So for a 5 sec tag group, my optimized write timeout is 7 secs.