User defined types: naming the thing instead of the address
What a UDT buys, how to decide what goes in one, and the versioning problem on a live system.
Short answer
A user defined type is a structure that groups related tags under one name, so a valve becomes a single tag with members for its command, its feedback, its fault and its timer. It makes the tag table describe the plant rather than the memory map, makes an array of forty identical devices trivial, and centralises a change. The cost is that changing the type on a running system usually requires a download.
A tag table is either a description of the plant or a description of the memory map, and which one it is decides how much of a new engineer's first month is spent working out what things are called.
What a UDT is
A structure. A named type containing named members, instantiated as many times as needed.
Define ValveType with members Open_Cmd, Closed_FB, Opened_FB, Fault, Travel_Timer. Create V101 of that type. Now V101.Fault is meaningful to somebody who has never seen the program.
The alternative is V101_Open_Cmd, V101_Closed_FB and so on as separate tags, where the relationship between them exists only in the naming convention and holds until somebody types an underscore in the wrong place.
What it buys
Arrays become possible. Forty valves is Valves[40] of ValveType, and one routine handles any of them by index. Without the type, forty valves is two hundred loose tags.
A change lands everywhere. Adding a stroke counter to every valve is one edit to the type rather than forty edits to forty tags.
The tag table reads as documentation. Browsing V101 shows what a valve consists of.
HMI and reporting get simpler. A faceplate binds to a valve rather than to five separate tags whose names it has to construct.
Deciding what goes in one
The test: does every instance need this member?
A member that applies to two of forty valves does not belong in the type. It ends up present and unused on thirty eight instances, and the next person to read the type cannot tell it is exceptional.
Where a few instances genuinely need more, either nest a second type, or hold the exceptional data separately and index it alongside.
The other failure is a type with sixty members covering every valve anybody might ever fit. It is not wrong and it is a large amount of memory times forty, and every one of those members appears in every cross reference forever.
Nesting
Types can contain types, and it is useful up to about two levels.
Station containing Valves[4] of ValveType and Motor of MotorType reads well and matches how the plant is described.
Line.Station[3].Valve[2].Timer.ACC is four levels and is where it stops helping, because nobody can hold the path in their head while looking at a rung.
The versioning problem
The one real cost, and it is worth planning for rather than discovering.
Adding a member changes the memory layout of every instance. Most controllers cannot do that online, so the change means a download, and a download means the plant stops.
Three approaches, none of them elegant.
- Get it right first. Realistic on a new machine where the design is understood.
- Leave spares. A few reserved members in the initial definition. Ugly, effective, and it is what experienced people do on systems that cannot be stopped.
- Plan the downtime. Batch structural changes and take them at a scheduled stop rather than one at a time.
Naming
Two conventions worth adopting because they pay for themselves.
Name the type after the thing, not the project: ValveType, not Line3Valve. Types get copied between projects and a project specific name follows them for years.
Name members after what they mean rather than how they are wired: Opened_FB rather than DI_04. The wiring is on the drawing and will change; the meaning will not.
Common questions
- When should I create a UDT?
- When the same group of tags appears more than twice for the same kind of thing. Two valves is a judgement call; six valves each with a command, two feedbacks, a fault and a timer is a UDT, because the alternative is thirty six loose tags whose relationship exists only in the naming convention.
- Can I change a UDT on a running controller?
- Usually not without a download. Adding a member changes the memory layout of every instance, and most controllers cannot do that online. Leaving spare members in the definition from the start is a common and slightly ugly workaround for systems that cannot be stopped.
- What is the difference between a UDT and an add-on instruction?
- A UDT is data with no behaviour. An add-on instruction is data plus the logic that operates on it, packaged and versioned together. Use a UDT when different instances need different logic, and an AOI when the logic is genuinely the same everywhere.
Keep reading
- Safety
SIL or PL: which one does your machine need?
Two standards, two scales, and one machine. Which one applies, how they map to each other, and why the answer is usually ISO 13849.
- Safety
Categories B, 1, 2, 3 and 4, in plain terms
Five architectures, what a single fault does to each, and the practical wiring that goes with them.
- Safety
Safety relay or safety PLC: how to decide
One is a wiring decision, the other is a programming one. The count of safety functions, not the size of the machine, is what settles it.