Keeping loose tags such as valve1_open, valve2_open, valve3_cycles consistent takes repeated edits. A User-Defined Type (UDT) defines a shared data structure. Create the definition once and use it for each piece of equipment. When you change the definition, every instance uses the changed structure. Each instance still holds its own values, as the valves below show.
On the left is the type definition "Valve". On the right are four valves that use that type inside "Plant".valves, an ARRAY[1..4] OF "Valve". Click ➕ add a field to the type and watch all four instances grow it at once. The definition determines which fields each valve has; you do not add the field separately to each valve.
Without the shared type, you would repeat that edit across 40 valves, a dozen DBs and the HMI. A UDT puts the definition in one place. Every use of that definition follows the same structure, so you can maintain the fields together instead of editing separate tag lists.
Use a UDT wherever the project needs that data structure: as the type of an FB's in/out, a tag in a global DB, an array element, and the structure an HMI faceplate binds to. Define "Valve" once, then use that definition wherever the project needs the same valve data.
🧠 As an FB interface. FB_ValveCtrl takes io : "Valve". Passing the whole valve then takes one wire instead of eight separate tag connections. A field added to the type also becomes part of that interface.
🖥️ As an HMI binding. A faceplate bound to "Valve" works for valve 1, 17 or 200. Point the faceplate at a different instance to bind its fields to that valve's data.
A plant has 60 identical mixing stations. Mid-project you must add a "lastCleanTime" field to each station's data. What's the clean way?