Reusable data and reusable logic have separate definitions. A DDT (Derived Data Type) defines a data structure for variables that share the same fields. A DFB (Derived Function Block) is your own reusable logic block with private memory for each instance. You can create ten instances of the same block type and give each its own state. The examples below let you compare a shared data definition with separate running block instances.
The left panel defines the DDT T_Valve. The right panel shows three valve variables using that type. Select ➕ add a field and the simulation adds it to each valve. The shared definition keeps their field structure consistent, unlike individually declared valve1_open, valve2_open tags that must be maintained separately. Real project changes still need the appropriate build and download checks.
The DFB FB_PumpHours accumulates a pump's running hours in its private instance data. It's instanced twice, as Pump_1 and Pump_2. Run either pump and inspect its own meter. Both instances execute the same block definition while keeping their accumulated values separate; a change to one pump's state does not update the other pump's stored hours.
FUNCTION_BLOCK FB_PumpHours // PRIVATE (retained per instance): runHours : REAL; // runs each scan: IF Running THEN runHours := runHours + dt; END_IF;
Fix a bug in FB_PumpHours and the shared block definition changes for both instances. Pump_1 and Pump_2 still hold separate hour totals. Use a DDT to define the fields that belong together and a DFB to define repeated behaviour with instance data, so the project can reuse definitions without sharing every runtime value.
You need a reusable conveyor controller that holds its own state machine and a timer, dropped onto 8 conveyors. What do you build?