1. Overview
When a TIA Portal V16 project for a SIMATIC S7-1500 or SIMATIC S7-1200 accumulates more than a dozen function blocks, the cyclic main organization block (OB1) becomes a flat, sequential list of FB calls that is hard to read, hard to reuse, and hard to fault-find. The original problem statement describes 21 FBs in OB1 and proposes two structural fixes: splitting the work across additional cyclic OBs (e.g. OB1, OB100, OB101 style program-cycle OBs) or grouping them inside three Functions (FCs) that are called from OB1. Both approaches are technically valid, but they have different consequences for instance-DB memory, code reusability, multi-instance nesting, and HMI/SCADA data routing.
This reference covers four organizational patterns that are the standard practice in SIMATIC automation: FC grouping, multi-instance FB grouping, time-deterministic cyclic OB grouping, and program-folder grouping with library reuse. It also includes a feature comparison table, a complete pattern implementation in Structured Text (SCL), TIA Portal V16 configuration steps, and a verification procedure. TIA Portal V16 ships with STEP 7 V16, WinCC V16, and Startdrive V16; the FB/FC features referenced below are documented in the S7-1500/ET 200MP system manual and the STEP 7 programming guideline.
2. Block Architecture in S7-1500 / S7-1200
Before deciding on a grouping strategy, the engineer must understand the runtime model of the four logical block types in the S7-1500/S7-1200 firmware.
| Block | Symbol | Static State | Own Instance DB | Multi-Instance Capable | Typical Use |
|---|---|---|---|---|---|
| Organization Block | OB | No | No | No | Schedules cyclic, time-of-day, interrupt, startup, error, and background execution |
| Function | FC | No (TEMP only) | No (FB calls inside need their own IDB) | N/A | Parameter-passed, stateless math/recipe/format routines |
| Function Block | FB | Yes (STAT section) | Yes (one per call site unless multi-instance) | Yes (FBs can call other FBs, storing their IDs in STAT) | Encapsulated machine objects: heater, conveyor, valve, motor |
| Data Block | DB | Yes (data only, no code) | Self | N/A | Structured data, HMI mirror, global parameter sets |
The S7-1500 CPU firmware (FW 2.5 and later, including the V16 default catalog CPUs 1510SP-1 PN through 1518-4 PN/DP MFP) supports nested FB calls with multi-instance storage. This is the capability that makes pattern 2 below viable: when FB "Group" declares a STAT field of type "FB_Motor", the instance data of every internal motor FB is stored inside the parent's instance DB. The result is a single IDB per machine module, not one per leaf FB. S7-300 historically had a multi-instance limit of six FBs or a fixed byte count; the S7-1500 removes that constraint and supports arbitrary nesting depth (the compiler enforces block-size limits, not a fixed count).
For reference, the relevant manuals are:
- SIMATIC S7-1500 Automation System System Manual (09/2019 ed.)
- SIMATIC S7-1200 Programmable Controller System Manual (06/2019 ed.)
- STEP 7 Basic/Professional V16 and SIMATIC WinCC V16 - What is new?
3. Option 1: Grouping with Functions (FCs)
Option 1 from the source question — three FCs, each calling seven FBs from OB1 — is the simplest improvement over a flat OB1. In this layout, OB1 contains three FC calls, and each FC contains seven FB calls. The runtime cost is one extra block call per group (negligible; the S7-1500 call stack handles hundreds of nesting levels efficiently). The benefit is the visual grouping in TIA Portal: each FC becomes a labeled container for a logical subsystem.
A complete FC signature in SCL for a motor group is shown below.
// FC_MotorGroup: container that calls 7 motor FBs
FUNCTION "FC_MotorGroup" : VOID
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
iEnable : Bool; // master enable from OB1
iModeAuto : Bool; // 1 = automatic, 0 = manual
END_VAR
VAR_OUTPUT
oGroupFault : Bool; // OR of all FB fault flags
oGroupRunning : Bool; // OR of all FB running flags
END_VAR
VAR_TEMP
tInfo : Struct
idx : Int;
END_STRUCT;
END_VAR
BEGIN
// 7 motor FBs declared as separate instance-DBs in DBs folder
"FB_Motor_1"(iEnable := iEnable, iMode := iModeAuto);
"FB_Motor_2"(iEnable := iEnable, iMode := iModeAuto);
"FB_Motor_3"(iEnable := iEnable, iMode := iModeAuto);
"FB_Motor_4"(iEnable := iEnable, iMode := iModeAuto);
"FB_Motor_5"(iEnable := iEnable, iMode := iModeAuto);
"FB_Motor_6"(iEnable := iEnable, iMode := iModeAuto);
"FB_Motor_7"(iEnable := iEnable, iMode := iModeAuto);
oGroupFault := "DB_Motor_1".oFault OR "DB_Motor_2".oFault OR "DB_Motor_3".oFault
OR "DB_Motor_4".oFault OR "DB_Motor_5".oFault OR "DB_Motor_6".oFault
OR "DB_Motor_7".oFault;
oGroupRunning := "DB_Motor_1".oRunning OR "DB_Motor_2".oRunning OR "DB_Motor_3".oRunning
OR "DB_Motor_4".oRunning OR "DB_Motor_5".oRunning OR "DB_Motor_6".oRunning
OR "DB_Motor_7".oRunning;
END_FUNCTION
The OB1 then becomes:
// OB1 - Main program cycle
ORGANIZATION_BLOCK "Main_OB"
VERSION : 1.0
VAR_TEMP
tInfo : OB_CYCL_INFO; // system-supplied cycle info
END_VAR
BEGIN
"FC_MotorGroup"(iEnable := TRUE, iModeAuto := "DB_Control".bAuto);
"FC_ValveGroup"(iEnable := TRUE, iModeAuto := "DB_Control".bAuto);
"FC_PumpGroup"(iEnable := TRUE, iModeAuto := "DB_Control".bAuto);
END_ORGANIZATION_BLOCK
Pros: minimal refactor, no STAT modeling required, FB declarations stay independent and can be called from multiple sites. Cons: each motor FB still needs its own instance DB in the project tree (21 IDBs for 21 FBs), and group-level state (interlocks between motors) must be implemented via global DBs, MERKER, or passed VAR_IN_OUT through the FC, which is awkward.
4. Option 2: Grouping with Multi-Instance FBs
Option 2 — call a grouping FB from OB1 and let that FB call its leaf FBs as multi-instances — is the pattern most experienced SIMATIC engineers prefer for machine code. The grouping FB declares a STAT field whose type is the leaf FB; the S7-1500 compiler stores the leaf's instance data inside the parent's IDB.
// FB_MotorGroup - group FB with multi-instance children
FUNCTION_BLOCK "FB_MotorGroup"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
iEnable : Bool;
iModeAuto : Bool;
END_VAR
VAR_OUTPUT
oGroupFault : Bool;
oGroupRunning : Bool;
END_VAR
VAR
// STAT holds 7 motor multi-instances. No separate IDBs needed.
statMotors : ARRAY[1..7] OF "FB_Motor";
END_VAR
BEGIN
"FC_SumFault"(motors := statMotors, fault => oGroupFault, running => oGroupRunning);
END_FUNCTION_BLOCK
Call from OB1:
// OB1: only one call, one IDB per group
"iDB_MotorGroup"(iEnable := TRUE, iModeAuto := "DB_Control".bAuto);
"iDB_ValveGroup"(iEnable := TRUE, iModeAuto := "DB_Control".bAuto);
"iDB_PumpGroup"(iEnable := TRUE, iModeAuto := "DB_Control".bAuto);
This is the architectural pattern recommended in the STEP 7 V16 "What is new?" documentation, the S7-1500 system manual chapter on block architecture, and Siemens' own programming style guide for modular machine code. It collapses 21 IDBs into 3 IDBs, makes the group re-usable across machines, and keeps interlock logic local to the group STAT section. This is the correct answer to the source question.
Concrete S7-1500 limits that affect this design (CPU-family dependent, see system manual for your exact MLFB):
| Resource | CPU 1511-1 PN | CPU 1515-2 PN | CPU 1518-4 PN/DP |
|---|---|---|---|
| FB nesting depth (call depth) | 32 | 32 | 64 |
| Multi-instance size limit (work memory) | No fixed count; bounded by total load memory and IDB work memory (default 1 MB work memory on 1515-2 PN, expandable) | ||
| Number of blocks (FB+FC+DB+OB) total | 6 000 | 6 000 | 6 000 |
| Max number of FBs | 5 000 | 5 000 | 5 000 |
These numbers are documented in chapter 4 ("CPU properties") of the S7-1500 system manual. With a target of three group FBs containing seven multi-instance motors each, the design is well under all limits on every S7-1500 CPU.
5. Option 3: Time-Deterministic Grouping with Cyclic OBs
If the 21 FBs are not all on the same execution class — for example, fast current-loop control at 1 ms, medium-speed sequence at 10 ms, and slow HMI refresh at 100 ms — the correct grouping is by cyclic interrupt OB, not by FC or FB. S7-1500 OBs in the 30–38 range are time-triggered at fixed phase offsets relative to OB1:
| OB | Name | Default Priority | Typical Use |
|---|---|---|---|
| OB30 | Cyclic interrupt 0 | 7 | Fast closed-loop control |
| OB31 | Cyclic interrupt 1 | 8 | Fast sequence |
| OB32 | Cyclic interrupt 2 | 9 | Medium-speed sequence |
| OB33–OB38 | Cyclic interrupt 3–8 | 10–16 | Background groups |
| OB1 | Main program cycle | 1 | Default, lowest-priority free-running cycle |
The phase offset and period are configured in the CPU properties → "Cyclic interrupts" dialog. Two OBs with the same period but different phase offsets are guaranteed not to overlap. This is the only S7-1500 mechanism that gives engineers deterministic jitter on a portion of the program. If your 21 FBs include current regulators, use OB30 for those and OB1 for the rest. Mixing 1-ms and 100-ms code in OB1 is the most common cause of S7-1500 cycle-time overruns.
Note that the original question's suggestion "create two more main [OB] program cycles" is a misreading of the TIA Portal block catalog. S7-1500 supports only one OB1 (Main) per program execution level. Additional OBs must be the cyclic, time-of-day (OB10–OB17), delay (OB20–OB23), cyclic interrupt, startup (OB100/OB101/OB102), or error (OB82, OB83, OB86, OB121, OB122) variants. The S7-1500 system manual chapter on OBs lists every OB type and its priority.
6. Folder Organization and Library Reuse
Independent of the FC/FB/OB question, the field report correctly emphasizes that the TIA Portal project tree supports user folders under Program blocks. The recommended layout for a machine with three functional groups is:
Program blocks
├── 00_Cyclic
│ ├── OB1 (Main)
│ ├── OB100 (Startup - warm restart)
│ └── OB82 (Diagnostics - module fault)
├── 01_Group_Motors
│ ├── FB_Motor (type / master copy)
│ ├── FB_MotorGroup (group with 7 multi-instances)
│ └── iDB_MotorGroup (single instance DB for OB1)
├── 02_Group_Valves
│ ├── FB_Valve
│ ├── FB_ValveGroup
│ └── iDB_ValveGroup
├── 03_Group_Pumps
│ ├── FB_Pump
│ ├── FB_PumpGroup
│ └── iDB_PumpGroup
├── 04_Types
│ ├── UDT_ConveyorParams
│ ├── UDT_MotorParams
│ └── UDT_AlarmConfig
└── 05_HMI_Interface
├── DB_HmiMirror (read-only structured mirror for WinCC)
└── DB_Alarms (structured alarm data)
Every grouping FB should be type/version-managed as a master copy in a project library ("Libraries → Project library → Master copies"). A new machine project then drags the master copies from the library into its program tree, regenerates instance DBs, and reuses the group without recoding. This is the workflow used by OEM machine builders shipping SIMATIC standard libraries.
7. FC vs FB vs OB: Feature Comparison
| Criterion | Group via FCs | Group via FB (multi-instance) | Group via cyclic OB |
|---|---|---|---|
| Number of instance DBs for 21 FBs | 21 (each FB call site has its own IDB) | 3 (one IDB per group FB) | 21 (no change in IDB count) |
| Group-level state retention | None (FC has no STAT) | Yes (STAT section of group FB) | Yes (STAT inside each leaf FB) |
| Reusability across machines | Medium (FC and its 7 FB calls must be copied together) | High (single FB block + its type FBs) | Medium (OB and its block set must be copied together) |
| Deterministic timing for the group | No (still rides OB1 jitter) | No (still rides OB1 jitter) | Yes (OB30–38 phase offset) |
| Complexity of refactor from flat OB1 | Low | Medium (add group FB, convert to multi-instances) | Medium (create OB, set phase/period, move FB calls) |
| Watchdog / OB1 cycle time impact | Negligible | Negligible | Improves (load shifts off OB1) |
| Recommended for | Small visual cleanup, stateless math | Object-oriented machine modules | Fast loops, time-staggered sequences |
The original poster's question implies all 21 FBs are at the same priority, in which case the FB multi-instance pattern is the most correct because it provides grouping, state encapsulation, IDB reduction, and library reusability in one mechanism. If the 21 FBs are heterogeneous in timing, the OB split is correct on top of the FB grouping.
8. Practical Pattern: Structured FB with Multi-Instances
A complete, copy-paste-ready pattern for a three-group layout is shown below. Each group FB owns its leaf FBs as multi-instances, and a single global DB carries the inter-group interface.
// UDT_GroupInterface - common HMI/control interface
TYPE "UDT_GroupInterface"
VERSION : 1.0
STRUCT
bEnable : Bool;
bAutoMode : Bool;
bManual : Bool;
bFault : Bool;
bRunning : Bool;
rActSpeed : Real;
rSetSpeed : Real;
END_STRUCT;
END_TYPE
// DB_GroupIfc - one struct per group, global interlock DB
DATA_BLOCK "DB_GroupIfc"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
STRUCT
Motors : "UDT_GroupInterface";
Valves : "UDT_GroupInterface";
Pumps : "UDT_GroupInterface";
END_STRUCT;
END_DATA_BLOCK
// FB_Motor - leaf FB (single motor)
FUNCTION_BLOCK "FB_Motor"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
iEnable : Bool;
iCmd : Bool;
END_VAR
VAR_OUTPUT
oFault : Bool;
oRunning : Bool;
END_VAR
VAR
statTmr : TON_TIME;
statRun : Bool;
END_VAR
BEGIN
statTmr(IN := iEnable AND iCmd, PT := T#3S);
statRun := iEnable AND iCmd AND NOT statTmr.Q;
oRunning := statRun;
oFault := statTmr.Q;
END_FUNCTION_BLOCK
// FB_MotorGroup - group FB with 7 multi-instances
FUNCTION_BLOCK "FB_MotorGroup"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
iEnable : Bool;
END_VAR
VAR_OUTPUT
oFault : Bool;
oRunning : Bool;
END_VAR
VAR
statMotors : ARRAY[1..7] OF "FB_Motor";
END_VAR
BEGIN
"FC_DriveMotors"(motors := statMotors, iEnable := iEnable);
"FC_SumStatus"(motors := statMotors, oFault => oFault, oRunning => oRunning);
END_FUNCTION_BLOCK
Notice that the leaf FB FB_Motor uses an internal TON_TIME IEC timer, an S7-1500 system block. This is the recommended pattern for timers inside FBs: declare statTmr : TON_TIME in VAR, and the timer instance is part of the multi-instance DB — no global timer resource consumed.
9. Implementation Procedure (TIA Portal V16)
- Create a new project in TIA Portal V16. Add the S7-1500 CPU (or S7-1200) from the hardware catalog. Confirm the firmware version supports the multi-instance features you intend (S7-1500 FW 1.8 or later, S7-1200 FW 4.4 or later — see the S7-1500 system manual for the firmware/catalog matrix).
- Plan the groups. In a table, list every FB, its inputs/outputs, and which logical group it belongs to (Motors, Valves, Pumps, etc.). Confirm no FB needs to be called from two groups at the same time, or wrap that FB in a higher-level object.
- Create UDTs for common interfaces (UDT_GroupInterface, UDT_AlarmConfig, etc.) under Program blocks → Add new block → Type. TIA Portal V16 added type-side accessible UDTs for HMI integration; reference the STEP 7 V16 "What is new?" page.
- Author the leaf FBs (FB_Motor, FB_Valve, FB_Pump). Test each with a small watch table before composition.
-
Create the group FBs (FB_MotorGroup, FB_ValveGroup, FB_PumpGroup). In the FB interface's STAT section, add a multi-instance field:
statMotors : ARRAY[1..7] OF "FB_Motor";. Compile. - Create one instance DB per group (iDB_MotorGroup, iDB_ValveGroup, iDB_PumpGroup) by right-clicking the group FB → "Add new instance DB".
- Edit OB1 to call only the three group FBs. Remove the 21 individual FB calls.
- Create the HMI mirror DB (DB_HmiMirror) with read-only structs that copy from DB_GroupIfc. Wire the HMI tags to DB_HmiMirror only.
- Compile the project (Project → Compile all). Resolve any "instance-DB already assigned" errors by deleting the old IDBs of the 21 leaf FBs that are now multi-instances.
- Download to the PLC and verify in online mode that the group FBs execute in the expected order.
10. Verification and Diagnostics
After download, run the following checks to confirm the refactor:
- Block count check: In the project tree, the number of instance DBs should drop from 21 to 3 (plus the three group IDBs themselves). If a leaf FB still has its own IDB, it was not converted to a multi-instance and is being called from somewhere outside the group FB.
-
Online watch: Open the group IDB in "Monitor all" mode. The STAT section should show
statMotors[1]throughstatMotors[7]with their TON_TIME and statRun values. This confirms multi-instance storage is active. - Cross-reference: Use Show usage on each leaf FB. The result should show exactly one call site — inside the group FB. If you see two call sites, you have an accidental double-call and IDB bloat.
- Cycle time: Open Online & diagnostics → Cycle time. The OB1 cycle time should not increase beyond 5% after the refactor; the multi-instance pattern has no measurable runtime overhead on S7-1500.
-
Watch table test: Force
iDB_MotorGroup.iEnable := TRUEand confirm all seven motors start, theoRunningaggregate goes high, and the OB1 cycle remains stable. - Error OB behavior: If the program touches I/O points, OB121 (Programming error) and OB122 (I/O access error) should remain passive. Triggering them in the test indicates a missing instance or uninitialized tag.
11. Best Practices and Common Pitfalls
- Prefer FBs over FCs for grouping. FBs give you STAT state and multi-instance storage. Use FCs only for stateless parameter transforms, math, recipes, formatting, and short utility routines.
- Never use MERKER (M) bits for interlock state. M-bits are global, undocumented, and survive neither versioning nor project diffs. Use STRUCTs in a group or global DB instead.
- One OB, one purpose. OB1 should contain only top-level calls to group FBs (or, for time-deterministic code, OBs in the 30–38 range). Do not put business logic directly in OB1.
- Use accessible UDTs for HMI mirroring. In TIA Portal V16, mark the HMI DB as accessible from HMI and use UDT-based structs so a new field added to the UDT is automatically available in WinCC without manual tag reconnection.
- Time-of-day and delay OBs are not for grouping. OB10–OB17 (TOD) and OB20–OB23 (delay) are event-triggered; do not abuse them as cyclic groups. Use OB30–OB38 for any cyclic timing.
- Reuse via type FBs and master copies. The library workflow is described in the S7-1500 system manual chapter on libraries. Use a project library so a fix to FB_Motor propagates to every machine project via "Update types".
- Avoid global instance-DB access from HMI. HMI should read from a dedicated mirror DB, not from the multi-instance IDB. This keeps SCADA decoupled from control state and limits the blast radius of any HMI-side modification.
- Use SCL for grouping FBs, LAD/FBD for leaf FBs. SCL's syntax for multi-instance arrays and STRUCT composition is concise; ladder is easier for discrete I/O. The combination is normal in TIA Portal V16.
- Respect nesting depth. Even though S7-1500 allows 32 or 64 levels, keep nesting shallow (5 or fewer) for readability and online diagnosis.
12. FAQ
Should I group my 21 FBs into multiple FCs or into one grouping FB with multi-instances?
Use a grouping FB with multi-instances (Option 2 from the original question). It collapses the 21 instance DBs into 3, gives you a STAT section for group-level state, and produces a single reusable block per machine module. FCs are appropriate only when the grouped FBs are stateless and the project has no machine-object model.
Can I create more than one OB1 in TIA Portal V16?
No. The S7-1500/S7-1200 firmware allows only one program-cycle OB (OB1) per execution level. To split work by timing, use cyclic interrupt OBs (OB30–OB38) with different period and phase offsets; to split work by startup, use OB100 (warm restart), OB101 (hot restart), or OB102 (cold restart). See the S7-1500 system manual for the full OB list.
What is the multi-instance limit on an S7-1500 CPU?
The S7-1500 has no fixed multi-instance count. Limits are block-size-driven and bounded by the CPU's load memory and the configured IDB work memory. A CPU 1515-2 PN with default 1 MB work memory comfortably supports hundreds of multi-instance FBs. Nested FB calls are limited to a call depth of 32 (CPU 1511, 1515) or 64 (CPU 1518).
Do multi-instance FBs need their own instance DB?
No. When a leaf FB is declared as a STAT field of the grouping FB, the leaf's instance data is stored inside the grouping FB's instance DB. The leaf has no separate IDB in the project tree. This is the whole point of the multi-instance model and is documented in chapter 5 of the S7-1500 system manual.
Is the FC grouping pattern ever the right choice?
Yes, when the 21 blocks are stateless (math, formatting, recipe scaling, alarm-formatting) and you need only visual grouping, not state retention. In that case, FCs are simpler and have no IDB overhead. The moment a block needs a timer, a counter, or a remembered state, convert it to an FB and use the multi-instance pattern.