Customization · Guide

Using custom UDTs with code generation

Add your shop's UDTs to PLCflow so I/O Code, Alarm Code, and Parameter Code generate against them instead of the system defaults. End-to-end walk-through for getting your existing UDT structures into the library and wired to the generators.

Pro Updated May 11, 2026 7 min read
Pro+
Required to upload or build custom UDTs
Once
Add the UDT, every project uses it
Per-category
Each UDT scoped to one module's consumers
The 2-minute path

These four steps produce an L5X ready for Studio 5000 import. The full guide below covers every option in detail.

  1. 1 Add · Upload your UDT from L5X, or build one in the editor.
  2. 2 Bind · Bind UDT members to the generator slots for the category.
  3. 3 Use · Pick your UDT in the row's UDT column in the generation editor.
  4. 4 Generate · L5X output references your UDT. Import to Studio 5000.

Overview

PLCflow includes system UDTs (UDT_MotorSimple, UDT_MotorVFD, UDT_ValveDiscrete, UDT_ValveAnalog, UDT_SensorAnalog, UDT_Setpoint, ALARM_UDT) that work out of the box. These are reasonable defaults but rarely match an established shop’s existing standards. The way to bridge that gap is to add your own UDTs to the library and have the generators use them instead.

This recipe covers the full workflow: get your UDT into the library, bind its members to the generator slots, use it in a generation, import the result. Once a UDT is in the library, every subsequent project on the same account can reference it.

Use this recipe when your shop has standard UDTs you want PLCflow to generate against, when a customer requires their own UDT structure for delivery, or when the system defaults are close to what you need but missing a specific member.

Pro and above. Uploading custom UDTs and creating new ones in the editor are both Pro-tier features. Free-tier accounts can use the system UDTs in any generation, but the Upload UDT and New UDT buttons in UDT Library are disabled with an upgrade tooltip.

Step 1. Add your UDT to the library

Open UDT Library from the dashboard. Two ways to get your UDT in.

Option A. Upload from L5X

If your UDT already exists in a Studio 5000 project, this is the fast path.

  1. In Studio 5000, right-click the UDT in the Data Types folder, click Export Component. Save the L5X to disk.
  2. In UDT Library, click Upload UDT in the top-right.
  3. Drop the .L5X file in the dialog (or click to browse).
  4. Set the Category for the UDT. This is the critical step. The category determines which generation module sees this UDT. Valid categories:
    • MOTOR, VFD_MOTOR for fixed-speed and variable-speed motors
    • VALVE for on/off valves
    • AI, AO for analog inputs and outputs
    • DI, DO for discrete I/O (rarely customized; the defaults usually fit)
    • ALARM for Alarm Code’s alarm structures
    • PARAMETER for Parameter Code’s setpoint structures
  5. Optionally set a Name Override to rename the UDT during import.
  6. Click Upload. The UDT lands in your User-scope library.

Option B. Build manually in the editor

If you want to build from scratch (no existing L5X):

  1. Click New UDT in the top-right of UDT Library.
  2. Fill in the Name (must be unique in your scope), Category, and Description.
  3. In the All Members panel, click Add Member for each member: name, data type, default, description, required flag.
  4. Bind members to the Required Fields generator slots that show up for the selected category (see Step 2 below).
  5. Click Create UDT.

Either way, the UDT now lives in your User-scope library and is visible to every PLCflow project on your account.

Step 2. Bind members to the generator slots

This is where most “I added my UDT but the generation does not work” issues come from. Each category has a set of generator slots the modules need filled. For example, a MOTOR-category UDT needs members bound to the “run command”, “run feedback”, and “fault” roles. The names of your members can be anything (Run_Cmd or Cmd_Start or Drive_Enable), but the binding tells PLCflow which one to drive.

The edit dialog has a Required Fields panel that lists every slot for the chosen category. Each row:

  • An orange marker for required slots, grey for optional ones.
  • The slot’s purpose (the human-readable role).
  • A small chip showing the role identifier.
  • A dropdown to pick which of your members fills that slot.

Pick a member from the dropdown for each required slot. The dialog blocks save until every required slot is bound and surfaces a message naming the unfilled slot.

Members not bound to any slot are kept as internal. They become part of the UDT’s structure and ship in the generated L5X, but the generator doesn’t drive them. Useful for HMI-only fields, timestamps, operator IDs, and other metadata.

Open a system UDT first to see the slot layout. Click any system UDT’s name in the library (UDT_MotorSimple for motors, UDT_Setpoint for setpoints) to open it in view mode. The Required Fields panel shows the slot list for that category. Build your custom UDT with the same slots filled and the generator behaves the same.

Step 3. Use the UDT in the generation editor

Open the target generation module (I/O Code, Alarm Code, or Parameter Code) and either upload a spreadsheet or add rows manually.

Each row has a UDT column with a dropdown showing every UDT in the library that matches the row’s category:

  • In I/O Code, the dropdown filters by device type (MOTOR rows show MOTOR UDTs, VALVE rows show VALVE UDTs, etc.).
  • In Alarm Code, the dropdown shows ALARM UDTs.
  • In Parameter Code, the dropdown shows PARAMETER UDTs.

Pick your custom UDT in the UDT column for any row that should use it. The generated L5X references that UDT by name; the AOI calls resolve member references based on which member is bound to each slot in the UDT definition.

If you have an existing Tag Database populated under the matching category, Import from DB pulls those rows in with the UDT reference already set.

Step 4. Generate and import

From the populated editor:

  1. Click Validate to confirm every row passes, including that the UDT reference resolves to a library entry with all required slots bound.
  2. Click Generate Code. The console streams progress.
  3. The generated L5X references your custom UDT by name throughout. The Required Components panel includes the UDT L5X for import into Studio 5000.

Studio 5000 import

If your custom UDT already exists in your Studio 5000 project (you exported it from there in Step 1), Studio 5000’s import dialog defaults to Use Existing. No collision, no extra import needed.

If your custom UDT does not yet exist in the target project (you built it in PLCflow):

  1. Right-click the Data Types folder.
  2. Click Import Component.
  3. Select the UDT L5X from PLCflow’s Required Components.
  4. Click OK.

Then import the main routine:

  1. Right-click the program you want the routine in.
  2. Click Import then Import Routine.
  3. Select the routine L5X.
  4. Set the routine name if prompted.
  5. Click OK.
  6. Review your code before deployment. Walk through a few rungs; confirm they reference your custom UDT.

Common pitfalls

  • Wrong Category on the UDT. A PARAMETER-category UDT will not appear in I/O Code’s dropdowns. A MOTOR-category UDT won’t appear for VALVE rows. If the UDT shows in the library but not in the editor’s UDT column, the category is usually wrong. Edit the UDT and fix.
  • Required slot left unbound. The library lets you save a UDT only after every required slot is bound. If a save is blocked, the dialog names the slot. Pick a member from its dropdown. If your UDT genuinely lacks a member for that role, add one in the All Members panel first, then bind it.
  • Custom UDT structure too different from system shape. PLCflow’s generator targets a specific set of roles per category. Slots map to those roles. If your UDT can’t fill a required slot (e.g. a motor UDT with no run-feedback equivalent), the generator can’t produce working code against it. Either add the missing member or restructure your UDT closer to the system baseline.
  • Forgetting to import the UDT L5X before the routine. Studio 5000 fails the routine import with an “unresolved type reference” error if the routine references a UDT it doesn’t know about. Always import UDTs (Data Types folder) before routines (Program folder).
  • UDT updated in library but downloaded L5X still uses old structure. Each generation captures the UDT definition at the time of generation. After you modify the UDT, existing downloaded files are unchanged. Re-generate to refresh.

FAQ

What if my UDT has Studio 5000-specific features like initial values?

The L5X upload preserves member metadata, including default values on members. When you save defaults on a member in the editor, those flow through to the generated L5X. Round-trip is preserved.

Can I share custom UDTs across team members?

User-scope UDTs are visible only to the user who created them. Project-scope UDTs (visible to everyone on a project) ship with the Projects module. Org-wide libraries are on the roadmap. In the meantime, export the UDT to L5X and have each team member upload it.

How do I know what slots PLCflow expects for a specific category?

Open the matching system UDT in UDT Library and look at its Required Fields panel. That shows every slot the category supports, marked required vs optional. Build your custom UDT to fill the same slots.

Can I have multiple variants of the same UDT (T_MOTOR_v1, T_MOTOR_v2)?

Yes. Each is a separate library entry under a different name. Different generations can use different variants. Useful when migrating a fleet of projects from one structure to another.

My custom UDT works for some rows but not others. Why?

Most often the UDT category doesn’t match the row’s type. The dropdown only shows UDTs that match. If a row falls back to the default unexpectedly, double-check the UDT’s category against the row’s device type.

  • UDT Library. Where the custom UDTs live and where the slot-binding happens.
  • I/O Code, Alarm Code, Parameter Code. The three primary consumers of custom UDTs.
  • Tag Database. Tags carry the UDT reference. After setting up custom UDTs, populate the Tag Database to lock in shop-wide naming.
What's next

Related modules

Was this helpful?

Honest feedback. We read all of it.

Try Using custom UDTs with code generation on real data

Free tier, no credit card. Bring a real spreadsheet, see what comes out.