Tag Structure, UDT setup, and Best Practices

We are developing new UDT's to support our process. I wanted to get an idea from the community on what has worked best for them. All previous topics have added immense value but sometimes the discussions stopped, and I wasn't sure what the person ended up doing in the end with all of the information. We are only using Vision and we do not attach the UDT to displays.

Thank you!

1) Folder with multiple UDT's vs UDT consolidation into a single UDT
We have many motors that each have a Motor Output, Current Monitoring, and breaker monitoring. We have individual UDT's for the motor control (motor control UDT), current (analog input), and breaker monitoring (digital input), etc. Each UDT component can contain multiple members/individual tags.

Do you find that it is better to keep the UDT's separate in a folder in the tag provider (shown below)?

Or do you find that it is better to consolidate UDT's into a single UDT?

2) Instance and Tag Naming
There have been some previous posts on this. Some prefer no spaces and some believe this should be readable. For my purposes, I'll use underscores. It seems the instances can have tooltips and documentation but I have found that it is not always visible and will take a second to come up.

Do your users prefer short tag names or more verbose label names?
Or do you hide the tag name and only do the label name?

image

3) For the UDT's, are we correct in using parameters here and referencing those parameters for each UDT member?
I have read where some people don't use parameters but if you have 50 members that all reference the parameter, wouldn't the use of parameters make sense?

Is this the preferred way or is there a different way we should be utilizing?

We put in the PLC Device Name, program (if applicable), PLC Tag Name. Each member of the UDT references OPC_Item_Path and adds the tagname to it.


References (not in any particular order)
Full stops in tagnames - Ignition - Inductive Automation Forum
Large Overbuilt UDT vs Folders of UDTs - Ignition - Inductive Automation Forum
Where do i find good example project explaining how to work with complex templates/UDTs? - Ignition - Inductive Automation Forum
Best way to structure UDTs - Ignition - Inductive Automation Forum
Special characters in the tag name - Ignition - Inductive Automation Forum
Tag naming conventions - Ignition - Inductive Automation Forum

2 Likes

Keeping multiple UDT's under one folder allows you to customize unused items. If you make a 'monolithic' udt with multiple udt's under them you are stuck with a fixed tagsize that can get very large in some cases and all those tags get loaded into memory I believe, even if disabled.

1 Like

Yes. This makes modifications and configuration of new instances much easier.

1 Like

I have strong opinions on this topic:

  1. Do not consolidate. More specifically, do not create UDTs that will have unused member tags. If there are just a few variants, create a "base" UDT as a parent, with the few variants inheriting from that.

  2. Ignition will allow you to use just about anything in tag and tag folder names. Don't do it. Use names without spaces or special characters. I recommend using names that are legal python variable names, as that is a least common denominator for many related naming restrictions. Consider using the translation subsystem to convert common tag/folder "programmer-friendly" names to user-friendly names at the point of display.

  3. Yes, use parameters. I recommend including the type's name in parameter names, to avoid parameter name clashes when UDTs are nested as members of other UDTs.

I avoid consolidation unless I'm very certain that there's never going to be any variation.

If you start adding motors without the current or without breaking monitoring, or with additional components later down the line, you'll have more flexibility, and you won't have to create a new motor UDT or let tags go unused (like @pturmel mentioned).

This is a good idea. Is this what you mean? For example, replace the generic OPC identifier I had in my example with the unique UDT name.

This seems interesting but I don't fully understand how you implement this. Can you share an example or what you mean by this?

Similar. I generally use a single parameter to pass a "root" OPC Item Path, to which everything within the appends (for hierarchical target devices like Rockwell or newer Omron). So, opc_AInUDT for your sample UDT. Some device types may need more than that.

Pass the final name of a tag path to system.util.translate() in a script, or to the translate() expression function in a binding. For display in the UI. That's it.

Can't you just let the translation manager to do this natively? Not sure about Vision, but it works in Perspective. I've re-labelled the alarm status table headers in this way by adding translation terms for "Display Path" and "Label".

If I understand correctly, instead of my 7 parameters, you put everything into 1 parameter? What advantage do you find with doing that?

Uniformity when nesting UDTs as members of other UDTs. You bind the inner UDT's opc_InnerUdtTypeName to {opc_OuterUdtTypeName}someSuffix. I tend to also do something similar with the tag group, binding grp_InnerUdtTypeName to {grp_OuterUdtTypeName}. This is important for optimization in OPC drivers that are symbol based.

That is, all members of a top-level tag in Rockwell or Omron processors (top level == controller tag or program tag) need to be polled at the same pace, or optimization of separate paces will yield pathological performance. I find that passing a UDT parameter down the hierarchy is the least maintenance that conforms.

1 Like

Whether it works or not on dynamic data seems to vary, and I'm not so sure such should be automatically translated. If someone types something in an input field that you display in a label on the next page, do you want that auto-translated? Or if it comes from your database?

Automatic translation of built-in parts of a component's UI is a no-brainer. Anything else, not so much.

If there are just a few variants, create a "base" UDT as a parent, with the few variants inheriting from that.

For clarity, see the following documentation on inheritance:
https://docs.inductiveautomation.com/display/DOC81/UDT+Inheritance

To further clarify, you can use the "parent data type" field of a structure to inherit common items from a UDT and then add items to customize your instance from there.

2 Likes

I came across a project that uses a lot of UDT's, but it took a more blanket approach with consolidating many of them (what's called Nesting in the manual). After analyzing the tag provider, it has 932,000 tags, of only which 126,000 are actively subscribed to the OPC server, 17,000 that can be taken out (opc path doesn't exist), leaving around an astounding 800,000 disabled!
The downside to this as I read is taking up RAM space, but thankfully not CPU, but still wasteful and cluttered. Also searching through tags, importing and exporting would be more cumbersome, is this correct? Any other downsides for performance?

Here are some additional questions:

  1. To look at this another way, basically, would it be best to create more base UDTs (even if many) that share all the possible tags, also with some UDT Inheritance where it makes sense, then create your tag instances in a folder structure that can choose which UDTs you need?

  2. For a scripted, more automated way of adding new sites/locations, would this then make more use of the system.tag.getConfiguration, tag.configure, and/or tag.deleteTags functions?

    • In contrast, using the UDT consolidated blanket approach, everything is there, but makes heavy use of the tag enabled property binded to a parameter on it's UDT to enable or disable the tag. So for adding new sites (instances), the UDT is added and just needs a system.tag.write to write a 0 or 1 to the enabled parameter.
  3. Is it possible to convert a heavily consolidated (nested) udt tag structure as above and maintain the tag's historian linkage?

    • I would be afraid of the historian table retiring many of these and creating new id's for the tags (even if I persevered the path; some UDTs turn into folders, path name stays the same) and thus not being able to trend tags back before the conversion.
  1. Judgement call. When the number of variations is more than the fingers on one hand, I prefer the folder approach.

  2. Yes. Consider scripting that reads a json or yaml file, or perhaps uses Apache POI to read a spreadsheet. That keeps the scripting relatively generic and reusable. Plan to not ever use deleteTags. If you screw up a scripted process, delete all the folders and run it again.

  3. Not sure, but the historian meta data can be altered after the fact if needed. Even to different tag paths. As long as you know before and after paths, you can make history conform.

1 Like

Another thought and question I have is that one difference between having a folder vs a UDT at a parent level is the UDT allows parameters which can be very powerful. Is there a way to handle this with folders?

For example, say we have a a main UDT that have 5 UDTs nested under it. You can put parameters on the main UDT that propagate down to all 5 underneath if needed. This saves having to have to change the same parameters on each of the 5 every time.

Compare this to having a folder with 5 UDTs under it. Those UDTs, even if sharing similar parameter names will need to each be individually updated when needed.

Am I correct in this thinking?

Yes, that's correct, and a parent UDT is the best choice for a specific case like that.

But if you don't know how many child UDTs might be needed, or which types, then you would need many parent UDT definitions to cover all the cases. Use a folder in that situation.

1 Like

Is there a best recommended way to group tags into UDTs? For example, by Device, Type, etc.. Can someone post examples?

For example, would a good tag structure organization look like this:
(to UDT or not to UDT?)

Area1 (folder)

-Site1 (subfolder)

---Tanks (subfolder)
------Tank1 (tank UDT?)
----------Volume (tag)
----------Temp (tag)
----------HiHi Alarm (tag)
----------Hi Alarm Setpoint (tag)
------Tank2 (tank UDT?)
-----------*same as Tank1

---PumpControls (subfolder)
------Pump1 (pump UDT?)
------Pump2 (pump UDT?)

-Site2 (subfolder)
--*same as Site1 above

I'm looking at a project migrating from ClearScada to Ignition. Conveniently, I can export a query from ClearScada that shows all tags (points), source, device IP and port, register addresses (all use Modbus TCP). I then analyze it in Excel doing compares and such. Most stuff looks standard, but with one-offs here and there.
The tag structure is organized by main area > Sites > device types (tanks, valves, pumpControls, VSD, etc).> devices(tank1, tank2, valve1,valve2, etc..).

Last question, is it normal to have to do a lot of manual inputting when first building a tag structure during a migration?

It depends on your project needs. There's a lot to consider.

If you had more going on, like if the volume and temperature tags both had multiple alarm configurations, setpoints, min/max values, etc, I might suggest an analog input UDT nested within the tank UDT. If it's just those four individual tags and every tank will look the same, then that looks like a great way to organize it.

If it were me, I would probably skip the "Tanks" and "PumpControls" subfolders because I'd expect the tanks/pumps to be grouped alphabetically and easy to find. If you have hundreds of tanks, then the subfolder may make more sense.

If the pumps are the same, then a UDT probably makes sense. If you have some on/off and some VFD pumps, then you may want separate UDTs.

Hypothetically, if your sites were all going to be exactly the same (which I doubt), you could make a site UDT and it would save you the trouble of organizing every site individually. But if the sites are different it would likely result in headaches from customizations and unused tags.

Basically, for anything that's repeatable it's best to use a UDT to reduce needless repetition and potential for mistakes.

4 Likes

I would argue that there's a lot less manual inputting in creating Ignition udts than there is creating ClearSCADA templates, in particular if you've got access to the plc and it supports browsing. Then you can drag in the tags from the OPC browser to create your udts definitions, and the data types and plc addresses are set for you. It's then just a matter of bulk find/replacing* the parts you want to make parameterised, add any alarming and history, and the UDT params themselves and you're done.

While ignition doesn't have the same automation interface that clearscada has for utilising external tools (technically you could create some thing using a webapi though via the WebDev module to facilitate this), you can do much the same inside of Ignition using its scripting functions as clearscada's AI let's you do

*important to note that when you add a reference to a udt parameter, you're actually creating a binding which converts the value of the prop into an object in the tag json. So if you simply copy json, find replace your plc addresses by adding {param name} into them, this is actually going to be static and not create the binding. I have a set of tools, one of which converts these into bindings, which I use. But without a tool, after importing back into ignition, you simply edit each tag's props with "static bindings" and just save them and they will be created then in the tag editor

If using the folder approach, with many components underneath, mostly comprised of UDTs, how can you set parameters from above? Scripting or json copy/paste only? Any way without doing those, but still being able to have top level parameters in the top level folder structure?

There is a lot of power of having parameters set at the top, here are a few:

  • I can disable a whole site at once (every tag's enabled property is binded to a parameter)
  • Alarms that go out to the site's route members based on the custom alarm property binding (you can have 10 sites, each with different members assigned to each)
  • A base OPC path, where the main site has the same device connection and such.

I understand the downsides of top level UDTs nested, mostly having many potential disabled wasted tags. However, you can argue in the UDT approach, that if you need to enable to disable a tag in the future, you still have it's historical trends available at a moment's notice without going through much extra work.