Advanced FBD programming

 Level Up Your FBD Skills – Building Reusable Function Blocks (UDFBs) Like a Pro

Let me ask you something. Have you ever copied and pasted the same logic over and over again—just for different motors, valves, or pumps?



I have. And I'll be honest—it feels fine at first. A quick Ctrl+C, Ctrl+V, change a few tag names, and you're done. But then you realize you need to change the timer from 5 seconds to 10 seconds. And now you're updating it in 17 different places. One mistake, one missed update, and your machine behaves differently on Line A versus Line B.

That's not engineering. That's chaos.


Today, we're going to fix that permanently. We're going to turn our humble motor control logic from the last article into a reusable, parameterized Function Block—a UDFB (User-Defined Function Block) that you can drag, drop, and configure in seconds.


Think of it like this: instead of writing the same recipe from scratch every time, you're creating a template where you just fill in the ingredients. And when you need to change the recipe, you update it once, and everything using it updates automatically.


What Exactly Is a UDFB?


In Siemens TIA Portal, a Function Block (FB) is a code block that can hold data in memory—even between scans [11†L5-L6]. When you create your own FB, it becomes a User-Defined Function Block.


Here's the key distinction that trips up most beginners:


Block Type Memory Behavior Best For

FC (Function) No memory—all variables are temporary Pure calculations, simple conversions

FB (Function Block) Has memory—data persists between calls Anything with "state" (motor running? timer counting?)


Every time you call an FB, you must assign an Instance Data Block (Instance DB). This DB stores all the FB's data—so Motor_1 keeps its state separate from Motor_2, even though they run the exact same logic.


This is the magic of reusability.



Step 1: Create Your Reusable FB


Let's take our motor control logic and give it superpowers.


1. In TIA Portal, go to "Add new block"

2. Select "Function block" (FB)

3. Name it: "FB_Motor_Control"

4. Language: FBD

5. Check "Add new and open"

6. Click OK


Now we're inside the block editor. But instead of hardcoding tag names like Start_PB or Motor, we're going to define them as parameters.








Step 2: Design the Interface – Inputs, Outputs, and InOuts





This is the most important step. The interface defines how the outside world talks to your block.


Here's our parameter list:


Inputs (data that comes into the block):


Name Data Type Default Value Comment

Start Bool FALSE Start command

Stop Bool FALSE Stop command

Reset Bool FALSE Resets latches

Run_Time Time T#5s Minimum run time (optional)


Outputs (data that goes out of the block):


Name Data Type Comment

Motor_Output Bool Motor control signal

Status_Running Bool Indicates motor is running

Fault Bool Indicates a fault condition


InOuts (data that goes both ways—rarely used, but useful for complex data):

We'll skip these for now to keep things simple.


Static variables (internal memory that persists):


Name Data Type Comment

Latch_Internal Bool Internal latch for running state

Timer_DB IEC_Timer Timer instance for delay logic


Notice that Latch_Internal isn't an input or output—it's an internal memory bit that only exists inside this instance. Motor_1 and Motor_2 will each have their own copy.


Step 3: Write the Logic – Using Parameters Instead of Fixed Tags


Now build the exact same latching circuit from Article 2, but replace every hardcoded tag with a parameter pin.


Your FBD network should look like this:


Start ──┐

        ├─ OR ──┐

Latch_Internal ─┘      │

                       ├─ AND ── Latch_Internal ── Motor_Output

Stop ── NOT ───────────┘


Latch_Internal ── Status_Running


Reset ────────────── (resets Latch_Internal) 



Here's the trick: instead of connecting directly to Motor (which no longer exists as a global tag), you connect to the output parameter Motor_Output. And instead of reading a global Start_PB, you read the input parameter Start.


This makes the block completely decoupled from your actual I/O tags. The block doesn't care if Start comes from a physical button, an HMI touchscreen, or a supervisory computer—it just does its job.



Step 4: The Instance Data Block – Your Block's "Memory Wallet"


Now here's where things get interesting.


Close your FB_Motor_Control and go back to the project tree. You'll see your new FB sitting in the "Program blocks" folder.


To use it, you need to call it from somewhere—usually from Main [OB1] (the organization block that runs cyclically).


Here's how you call your UDFB:



1. Open Main [OB1]

2. From the instructions pane, drag your FB_Motor_Control into the network (it appears under "FB blocks" in the library)

3. When you drop it, TIA Portal will automatically ask you to create an Instance Data Block



Name the first instance: Inst_Motor_Line1


Now your block looks like a little box with pins:


· Left side: Start, Stop, Reset, Run_Time

· Right side: Motor_Output, Status_Running, Fault





Connect real-world I/O tags to these pins. For example:


· Wire Start to your actual PLC input I0.0 (Start button)

· Wire Motor_Output to your actual PLC output Q0.1 (Motor contactor


Step 5: Use the Same Block for Multiple Motors


Here's the payoff.


Add a second instance:


1. Drag the same FB_Motor_Control into another network

2. TIA Portal asks for a new instance DB—name it Inst_Motor_Line2

3. Connect different I/O points (e.g., I0.2 for Start, Q0.3 for Motor)


Boom. Two motors. One block. Two separate memory areas.


What happens behind the scenes:


· Inst_Motor_Line1 stores its own Latch_Internal in DB10

· Inst_Motor_Line2 stores its own Latch_Internal in DB11

· They never interfere with each other


This is why FBs are so powerful—they encapsulate both logic and data.


The "Update Once, Deploy Everywhere" Secret


Now for the killer feature.


Let's say you realize you need an emergency stop override that works differently. Instead of opening 17 copies of the same logic and editing each one, you:


1. Open FB_Motor_Control once

2. Add a new input called E_Stop and wire it into the logic

3. Compile and download


Because every instance (Motor_1, Motor_2, Motor_17) references the same FB code, they all get the new behavior instantly. You don't touch a single instance DB—they just work.


This isn't just convenient. It's industrial best practice and the foundation of professional PLC programming.


Pro Tips from the Trenches


1. Use Default Values Wisely


Notice I set Run_Time default to T#5s. If you don't connect anything to this pin, it defaults to 5 seconds. But if you want 10 seconds for a specific motor, you can override it at the call site. Flexible and safe.


2. Distinguish Between Input and InOut


· Input parameters are read-only inside the block. You can read them, but you can't modify them.

· InOut parameters can be both read and modified—use these when you need to return a value that's also an input (like a counter value you want to keep updating).

· When in doubt, use Input and Output. Keep InOuts for advanced cases.


3. Always Initialize Static Variables


Uninitialized static variables can hold garbage from the last power cycle. In your block's initialization routine, set Latch_Internal := FALSE; and Fault := FALSE; so you start with a clean state.


4. Instance DBs Get Bigger Over Time


If you add a new static variable to your FB, all existing instance DBs need to be recompiled. TIA Portal handles this automatically—just right-click your instance DBs and select "Update block call" when prompted. Ignoring this leads to weird data corruption (speaking from painful experience).



What You Just Learned


✅ Created a parameterized UDFB with a clean interface

✅ Used inputs, outputs, and static variables correctly

✅ Called the FB multiple times with separate instance DBs

✅ Understood the power of "update once, deploy everywhere"

✅ Learned the difference between FB and FC in practice




What's Coming Next


In Article 4, we're entering a completely different domain—safety. We'll demystify the Siemens Fail-Safe Data Block (F-DB) and explore how safety programming differs from standard logic.


You'll learn:


· Why safety blocks have strict data restrictions

· How to create and manage F-DBs in TIA Portal

· The critical role of F-DBs in safety communication (F-Link)


Because let's be real—when you're dealing with safety, copy-paste shortcuts don't exist. Every safety signal must be explicitly managed, and F-DBs are the tools that make it possible.



Your Turn


Take the FB_Motor_Control we built and modify it to include:


· A fault detection – if the motor is commanded ON but the feedback contact says OFF after 2 seconds, set Fault := TRUE

· A Reset input that clears the fault


This is exactly the kind of logic you'll use in real factories. Try it out, simulate it, and see how the instance DB behaves.


Next up: Safety First – Demystifying the Siemens Fail-Safe Data Block (F-DB). Stay safe, and see you there!




Comments

Popular posts from this blog

Capacitive Level Sensors

Radar level measurement

Top 50 Instrumentation Interview Questions