Loose tags โ valve1_open, valve2_open, valve3_cycles โ rot fast. A User-Defined Type (UDT) is a cookie-cutter for data: design the shape once, stamp it as many times as you like, and when you change the cutter, every cookie changes with it. Watch.
On the left is the type definition "Valve". On the right, four valves stamped from it 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. That ripple is the entire reason UDTs exist.
Imagine doing that edit by hand across 40 valves and a dozen DBs, plus the HMI. The UDT makes it one change in one place โ and it can never drift out of sync, because there's only ever one definition.
A UDT isn't just for DBs. The same type can be the data 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 and it's the shared vocabulary across the whole project.
๐ง As an FB interface. FB_ValveCtrl takes io : "Valve" โ so passing a whole valve is one wire, not eight loose tags. Add a field to the type and the interface updates itself.
๐ฅ๏ธ As an HMI binding. A faceplate bound to "Valve" works for valve 1, 17 or 200 โ point it at a different instance and every field re-binds at once.
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?