Function Block Diagram (FBD) Programming Tutorial
One of the official and widely used PLC programming languages is Function Block Diagram (FBD). It is a simple and graphical way to program any functions together in a PLC program. Function Block Diagram is easy to learn and provides a lot of possibilities.
As one of the official PLC programming languages described in IEC 61131-3, FBD is fundamental for all PLC programmers. It is a great way to implement everything from logic to timers, PID controllers and even a SCADA system in your solution etc.
Most engineers love FBD because it is graphically a very common way to describe a system. Engineers like to put things in boxes. And that is exactly what the concept of function block diagrams is. FBD is very useful when batch control concepts from ISA-88 are applied.
In this tutorial I will introduce you to some of the basic principles of FBD programming and the function blocks.
Content of FBD Tutorial
What is Function Block Diagram?
From systems engineering you might already know something also called function block diagrams. PLC function block diagram is not that different from it. What FBD offers is a way to put functions written with many lines of code into boxes.
Thereby we can easily connect them, to make a bigger PLC program.
As with ladder logic and structured text, function block diagrams or FBD is described in the standard IEC 61131-3 by PLCOpen. Most PLC programs are written with some amount of FBD. Because, even though you might write your functions in structured text. You still, most of the times, have to connect those functions.
In FBD all functions are put into function blocks. They all have one or more inputs and outputs. The function of the block is the relation between the state of its inputs and outputs.
Here’s how a simple function block could look like:
The function block is illustrated with a box. In the middle of the box is often a symbol or a text. This symbol represents the actual functionality of the function block.
Depending on the function there can be any number of inputs and outputs on the function block. You can connect the output of one function block to the input of another. Thereby creating a Function Block Diagram.
There are many standard function blocks provided in FBD.But you can also make your own function blocks. Often, you will have to use the same piece of code in your PLC program multiple times. It could be a function for controlling a valve, a motor etc. With function blocks you can make a function block specific for a motor and use it several times.
Let’s begin by having a look at some of the standard function blocks as described in the IEC standard for PLC programming languages. They provide a variety of functions from very basic to advanced.
Standard Function Blocks
In the standard from IEC a lot of function blocks are described. Here’s an overview of the most important blocks in the official FBD description.
Bit Logic Function Blocks
The most basic functionality of a PLC program is logic. Combined called combinatorial logic. Logic is the simplest form of algorithm that, via the states of its inputs can set some outputs. Basically, there are two different bit logic functions or operations in FBD. With just these two you can derive a whole bunch of other logic functions.
But let’s start with the first one:
OR Logic Operation
At first I would like to introduce you to the OR function block. It takes 2 inputs and has 1 output, and works just like an OR gate.
If one of the inputs is true the output will also become true.
In FBD the block will typically look like this:
As you probably have seen the symbol for an OR operation is >=1. It is basically the condition for the output. If the sum of the two inputs are greater than or equal to 1, the output becomes true.
Just like with all the other bit logic operations false is represented by a 0 and true by a 1. This can be illustrated with a truth table for the OR operation:
The functionality of the OR block is equivalent to a parallel connection of two contacts in ladder logic. If either one of the contacts are closed, the output is set.
When I say output here I mean the output of the function block. We can only connect the output pin to another function block. But what if we want to set an actual output or a bit with the block output?
This leads us to the next function block.
In most cases you will connect the output of a function block to the input of another. But sometimes you will want to use that output to control one or more bits. This could for example be setting an output or a value for a variable.
To do this you need to use the assignment function block. And yes… This is a function block itself. Meaning that you cannot just set a memory address at the output of your block.
Assignment blocks work by assigning its input to a place in the PLC memory.
The function block also has an output you can use to connect to other function blocks. This is very useful because you can assign values anywhere in your function block diagram. Not just at the output of the last block.
The assignment function has the same functionality as a coil in ladder logic.
AND Logic Operation
The next function block I would like to introduce you too is the AND function block. Just like the OR-block this is one of the most fundamental function blocks in PLC programming.
It has two inputs and one output. It is very similar to the OR function but works a little different. Instead of one of the two inputs, this block requires both inputs to be true set the output.
If both the inputs are true the output will also become true.
This is how the truth table for AND block looks like:
If you know a bit of ladder logic, the AND function block is equivalent to a serial connection of two contacts in ladder logic. Both of them has to be true before the block evaluates its output to be true.
Sometimes you will want to invert either the input or output of a block. To do that you have to use negation. It comes in different shapes, depending on the software you use.
In some cases it is a whole blocks itself. And sometimes it is just the small circle you can put on any pins of the function blocks.
NOT, invert RLO or negate assignment practically works by changing the signal to the opposite.
When a signal is inverted or negated it means that, if it is true it becomes false and vice versa. The small circle in the pin of the block represents exactly that function.
Not only is it the outputs that can be inverted. The inputs can also be inverted. Simply by putting the circle on the input pin. You’ll see later that inverting either all inputs or the output has the same effect on the function of a block.
Exclusive OR Operation
This block is a special case of the OR block. The input values on the OR block has to be greater than or equal to 1. But as you can see below, the Exclusive OR or just XOR block requires the two inputs to be equal to 1.
If for example both inputs are true, the output of the XOR will be false, since the sum of the inputs are greater than 1.
Although it can be built with two AND and one OR function block, the XOR block is also provided as a function block itself in Siemens TIA Portal, Codesys and many more.
It is widely used to check if one and only one of two inputs are true.
NAND, NOR ect.
The next two function blocks are also build using the basic blocks. They are negated blocks. It actually just means that the output of the block is negated.
Take for example the NAND block as illustrated below. As you can see, the NAND function block is really just the AND block with a negated output. NAND stands for NOT AND or Negated AND.
The truth table for this block is the exact opposite of the truth table for the AND block.
As mentioned before the functionality of the NAND function block can also be obtained by negating the inputs. Negating the inputs has the same effect as negating the output. Therefore a NAND block could also look like this:
Bistable Function Blocks
The next types of function blocks I will introduce you too are the bistable. I like to think of them as the simplest form of memory. You can either set or reset the output. The output (Q) remembers the last state of the set input (S1).
Give S1 a pulse, and Q1 will be set. Even though S1 then changes state to false, the output will still be true. You can say that Q1 remembers if anything happened at S1. That’s why I like to think of the bistable functions or flip-flops as memory.
The function block is called SR or set/reset and this is how it looks like:
In order to get a better understanding how this function works, let’s look inside the function block. The function block body of the SR block shows that it is made up of 2 bit logic blocks. One AND function and one OR function.
The output of the AND function is connected to the input of the OR function. As one of the inputs on the AND function is Q1 which also acts the output for the whole block.
Many call this a flip-flop function. Q1 will remember that at some point S1 was true. This is until R or reset will be sat to true. Thereafter Q1 will be reset. The output (Q1) remembers and therefore I like to think of the block as a simple memory block.
This type of block always has a priority. If both inputs are true what will happen?
SR-blocks has set priority. So in the case where both inputs are true, the output will be set.
But that’s not always what you want. And that will lead us to the next block.
In some cases you might want to output to be reset when both inputs (S1 and R) are true. That is why we have to RS block.
It basically works in the same way as the SR block, but with reset as priority instead of set.
Again, this block can be derived from two basic logic blocks. But since the SR/RS flip flops are so fundamental in PLC programming, they have their own function block.
There are of course several ways to remember things. And although the flip flops are a very simple way to remember, the next types of blocks might be an even simpler form of memory.
Detecting edges is very useful in both PLC programming and electronics. Of course I’m not talking about the edge of your kitchen table, but rather the edge of signals.
Let’s say you have an input with a push button connected to it. You want to be able to count how many times you press that button.
Normally you would just connect the input to a counter function block (more on those later). But if you remember the basic workings of a PLC you will know that the PLC has a scan time or a cycle time.
This time is usually very short (20-50 ms). When you press a push button (even though you press and release fast), the input will be on for way longer time (typically 100-200 ms). The input will be on for several scan cycles.
Each time the PLC reaches the counter block it will count one up since the input is true. For each time the push button is pressed the counter will count not only one up but 2, 3, 5 or even more.
To avoid this we are going to use edge detection blocks.
R_TRIG Function Block
The one edge we can look at in a digital signal is the rising edge. Sometimes also referred to as positive edge.
It happens when the signal goes from false (0) to true (1). In digital electronics when the voltage goes from 0 to 5V. The rising edge is what happens right when we push the button.
When the input (CLK) detects a rising edge the output will be set. But only for a brief moment, since the rising edge happens so fast. Even though the input might be true for next scan cycles, the output will not be set more than one time. The output generates a pulse when a positive or rising edge is detected.
Here’s a diagram of the function block to make it easier to understand:
It takes a new rising edge to generate another pulse at the output. The block remembers, so to speak, if a positive edge was at the input. So in order to set the output again the input needs to go to false and then true again. Or as in our push button example; you need to release the button and press it again.
F_TRIG Function Block
Just like the rising edges you can of course also detect falling edges. When the signal goes from true (1) to false (0) is the falling edge.
Sometimes the falling edge is also called negative edge. It also works by generating a pulse at the output but with a falling edge at the input.
A typical use for this block is to make something happen when another thing stops.
Let’s say you want a yellow lamp to be turned on when a motor stops. But you only want this to happen when the motor has already been started. So that the yellow lamp is only turned on the moment the motor stops.
Solution: Put and F_TRIG to detect a falling edge on the motor output. This can then generate a pulse to set the output for the yellow lamp.
Timer Function Blocks
With the previous blocks we wanted to make sure a signal was not longer than the scan time. But sometimes you will want to control the length of a signal, or when it happens.
This is where timer function blocks comes into the picture. Timers are some of the most used functions in PLC programming. They are divided into three different types of timers.
If you want to know more about timers and watch how they work in a PLC simulation you can read the article about PLC timers. You will find video tutorials on both the on delay timer, off delay timer and pulse timer.
Some argue that you will only need to use one of them, because with that you can derive all timer functions. But since all three are described in IEC 61131-3 and are provided in most software, I would like to introduce you to them all.
Pulse Timer (TP)
The first timer is called the pulse timer, because it is used to generate a pulse of a specific length.
It takes two inputs and has two outputs. So far, we have only seen function blocks where the inputs and outputs where boolean. This is still true for the IN and Q of the TP block. But it is a little different with the PT and ET. They both take variables of the data type TIME.
PT stands for Preset Time and is an input to the block. This is where you put the time you want to pulse at Q to be. As soon as the input IN is true, the output Q will be set for PT time.
ET stands for Elapsed Time. This is the time Q has been active.
Say you want a ventilation fan to be on for 10 minutes. You will then have to enter 10m at the PT and set the ventilation fan to the output Q. In many cases it is then useful to see how long the fan has been running. That is what ET is used for.
You can see the functionality of the pulse timer a little more detailed in the time diagram above.
On Delay Timer (TON)
The next type of timer is the On Delay Timer or just referred to as TON. But instead of setting the time for the pulse, it is used to set a delay for the pulse.
When the input is on the timer will start counting. After the time PT has elapsed the output Q will be set. This is also the reason for its name.
It turns on the output after a delay
The on delay timer has the same input and output pins as the pulse timer. And again, it still has the ET to see how much time has elapsed.
In the diagram for the on delay timer below the functionality is illustrated:
It is exactly this timer that some people claim is the only one you need. But before explaining why, let me introduce you to the third and last type of timer.
Off Delay Timer (TOF)
The functionality of the off delay timer (TOF) is very similar to the TON. But with one big difference.
It turns off the output after a delay
In the moment the input is set to true, the output will be set. As long as the input stays true the output will stay on until the PT time has elapsed. After that time the output will be turned off.
At first, this off delay timer may seem very similar to the pulse timer (PT). They also are, but with one crucial difference.
The output of the pulse timer will be on for PT time even though the input turns to false in the middle of the timing. This is because the timer looks for a rising edge at the input. With the off delay timer though the time will stop counting if the input comes back.
These three timers are the official ones described in IEC 61131-3. Technically you can build all of them by using only the on delay timer. This is done with a little bit of ladder logic and is shown here by Shady Yehia.
Counter Function Blocks
The next type of function blocks have not only an input and an output more. They also take another data type. It’s time to look at the PLC counters.
Counting is very fundamental to PLC programming. How many products has the machine produced? In which step of the sequence is the tool? There are many reasons to use counters in a PLC program.
IEC provides three different standard counter blocks. One for counting up, one for counting down, and one for counting either up or down.
Let’s look at the first one, and start counting up!
Up Counter (CTU)
This counter block has three inputs and two outputs. Although this seems like a lot, they are all necessary to be able to count. But before looking at the details of each input and output, let me just briefly explain how the up counter block works.
Each pulse on CU will count CV up by 1. When CV >= PV then Q is set.
The input CU looks for a rising edge. When that happens the output CV is increased by 1. To be able to do that, the output CV needs to take another data type: integer.
As the integer is a 16-bit number (with the first one used for signed/unsigned) you can count up to 32767. Both the input PV and the output CV are of the data type integer. PV is the limit for when the boolean output Q is set.
The reset (R) input is used to set the value CV to 0. We usually start counting up from 0 because in that way, the output CV will always represent the number of pulses that occurred on CU.
For you that like textual coding languages here’s the function block body in structured text:
IF R THEN CV := 0; ELSIF CU AND (CV < PVmax) THEN CV := CV + 1; END_IF; Q := (CV >= PV);
Down Counter (CTD)
It is not only a useful thing to count up. Sometimes you will also need to count down. Often you will want you PLC program to do an operation a certain amount of times. Here, the down counter comes in very handy.
Each pulse on CD will count CV down by 1. When CV <= 0 then Q is set.
It works exactly like the up counter, but instead of counting one up it counts 1 down.This brings me to the another difference between the up and down counter. Where to count from?
When counting up we usually just count from 0. But when counting up we need to set some value we can count down from. That is why we have to input LD. When LD is set to true the output CV is set to PV.
The function block body looks like this in structured text:
IF LD THEN CV := PV; ELSIF CD AND (CV > PVmin) THEN CV := CV - 1; END_IF; Q := (CV <= 0);
Now that you’ve learned both how to count up and down it’s time to take a look at the last counter block.
Up Down Counters (CTUD)
It can sometimes be practical to be able to count both up and down. That is why the IEC also provides an official block for counting both up and down.
The counter has 5 inputs and 3 outputs. All of them has the same names as the inputs and outputs on the previous counter blocks. This block is a combination of the two previous blocks. All the inputs/outputs has the same function.
To really get to know how this function block works, let me show you the function block body:
IF R THEN CV := 0; ELSIF LD THEN CV := PV; ELSE IF NOT (CU AND CD) THEN IF CU AND (CV < PVmax) THEN CV := CV + 1; ELSIF CD AND (CV > PVmin) THEN CV := CV - 1; END_IF; END_IF; END_IF; QU := (CV >= PV); QD := (CV <= 0);
This code can look a bit complicated at first. But it really just is a combination of the up and the down counter. CU counts CV up by 1 and CD counts CV down by 1. Each of the outputs QU and QD are set with the same conditions as with the two previous counter blocks.
Comparison Function Blocks
I like to think of the next type of function blocks as asking questions. Is A equal to B? Is CV greater than PV? It is time to compare some numbers!
Comparing is actually something that already happened in many of the blocks we’ve already looked at. Take for example the OR block that compared two boolean inputs. If the total of them were equal to 1, the output would be set.
Now, it is not only boolean data types we can compare in FBD. In fact, we can compare all real numbers (sorry mathematicians, no imaginary yet) and most data types. This is not only handy, I will also promise you that it is something that you will use a lot.
Basic for all the comparison blocks is that they all have two or more inputs and one output. The inputs can take up any elementary data type and the output is boolean. You have to be careful when comparing data types, because it can be a bit tricky.
Let’s begin with the first basic comparator block:
The equality function block is used to see if two variables are equal to each other. If so, the output will be set. I like to think of the block as asking this question:
Is IN1 equal to IN2?
Although this block might seem simple, you have to be a bit careful with what data types you compare here. Comparing integers with this block is probably the data type you will use the most. Let’s say you want an output to be set when the machine is in step 12. IN1 would then be the step variable and IN2 would be 12.
The three dots between the two inputs are there to illustrate that this block can take more than two inputs. For the output to be set, all of the inputs has to be equal. This function is described like this using structured text:
OUT := IN1 = IN2 = ... = INn
Comparing other data types with equality can cause some problems though. If you try to use equality to compare an analog value (real data type) to another real data type, you will see that it is very unlikely that they will ever equal each other.
For this block to set the output requires the two inputs to be exactly equal to each other. Remember that real data types are floating point numbers. You may want something to happen when the temperature reaches 80 degrees. But if you use real numbers here the temperature has to equal 80.0 degrees exactly. For this type of comparison it is better to use a combination of compare blocks. In that way, you can compare it to a range of numbers and not just one.
But when talking about integers and sometimes also words, the equality block is very useful.
But what if you want to check if some numbers aren’t equal to each other? Of course you could just negate the output of the equality block. But that would be rather confusing. And why do that when there’s a block for doing exactly that.
The block works in the same way as the previous, but checking for inequality instead of equality. The question to remember the functionality of this block could be:
Is IN1 NOT equal to IN2?
If so, the output will be set. But only as long as they are not equal. As soon as the inputs are equal the output will be turned off.
To you who are already familiar with structured text you will know the symbol for inequality. It is similar to what in many programming languages is noted like this: !=. But in PLC programming inequality is noted this way <>.
Be aware that this block only takes two inputs.
Less Than (<)
If you remember before we had a problem with comparing real data types with equality. This and the next block might be the solution to that. Because with this block we can check if a variable is withing a range of numbers.
Officially this block is called increasing sequence. But less than is a way more simple name to remember it by. Think of it as asking this question:
Is IN1 less than IN2?
It is basically checking if the value of the first input is less (smaller) than the value of the second input. The block works very well with real numbers, since you can easily check if e.g. a temperature is less than 80.5 degrees.
There’s a reason the official name for this block is increasing sequence. Just like the equality block you can extend this block with more than two inputs. When doing that the official name makes a whole lot more sense.
Because with multiple inputs the values of those has to make up an increasing sequence of values. In1 has to be less than IN2, that has to be less than IN3 and so on. The function can be described textually like this:
OUT := (IN1 < IN2) AND (IN2 < IN3) AND ... (INn-1 < INn)
Greater Than (>)
When you can make an increasing sequence you can of course also make a decreasing sequence. Or put in more simple words. You can also check if some value is greater than another value. The question this block asks is this:
Is IN1 greater than IN2?
But just like the previous block, this block can also take more than two inputs. That’s why this block also has to take a sequence of numbers, but this time a decreasing sequence in order to set the output.
Each next input has to be smaller than the previous, thereby creating a decreasing sequence. Written in a textual language like structured text, the function of the greater than block looks like this:
OUT := (IN1 > IN2) AND (IN2 > IN3) AND ... (INn-1 > INn)
The combination of the greater than and less than blocks can also be very useful. When talking analog values you will often want to check if they are within a certain range. E.g. if a temperature is between 90 and 100 degrees. Here you could check if the temperature is greater than 90, and thereafter check if it is less than 100.
Combining the comparison blocks is widely used. You will often see the equality block combined with either less than or greater than. Although these are just combination of blocks they often have their own function blocks:
- Less than OR equal to
- Greater than OR equal to
Selection Function Blocks
Comparing two or more values is useful. But sometimes, instead of comparing, you will have to choose between values. The selection function blocks give you that opportunity.
What they all have in common is that they give you the option of selecting a value. With or without conditions. The essence of these blocks is really just assignment. You will select on of the inputs and assign it to the output of these blocks.
The first and most simple selection block is the move function block. In fact, you have already seen this block before. Or at least a block with the same functionality. The assignment function block.
What this block does is that it, assigns the input value to its output. And guess what. This block does exactly the same thing. You might wonder why FBD provides two blocks with the same function. They are also similar, but with one crucial difference.
While this block can be used with any data types, the assignment block can only be used with boolean data types. With the move block you can move any data type to any data type.
For you that like structured text, the representation of the block looks as simple as this:
OUT := IN
Provided in function block diagram the move block looks like this:
As you can see this block only has one input and one output. The concept of selection doesn’t really apply to this block, since you only have one value to select. Many times though you will be able to add more outputs to the move block. A move block can thereby be used to move a value to different places.
When I said this block works with any data type, I really meant it. You can move values from any data type to any data type. You don’t even have to put the same data type in the output as the input. You’re free to move e.g. an integer to a real, a TIME to a double word and so on.
This makes the move block a bit tricky. You have to be really careful when moving from one data type to another. For beginners I highly recommend that you only move values to the same data type as the input. As a matter of fact, I would rarely recommend mixing data types even for professionals. It just makes your PLC program complicated.
Binary Selection (SEL)
Binary selection drags us a little closer to the concept of selection. It gives you the opportunity to select between two values to then assign to an output.
The name indicates that you with a binary (boolean) input can select one of two input values. Therefore this block has three inputs. One condition (G) and two values (IN0, IN1). The condition takes a boolean data type and is used to select between the two values.
You will most likely have noticed that the input names are a bit different than with the other function blocks. That is only to make the block easier to understand. Since the condition (G) can take two different values 0 and 1, it makes sense to call the inputs IN0 and IN1.
If G is 0 the input IN0 will be selected. And if G is 1 the input IN1 will be selected. The value of the selected input will then be assigned to the output (OUT).
Again, this functionality can be represented in structured text:
IF G = 0 THEN OUT := IN0 ELSIF G = 1 THEN OUT := IN1 END_IF;
In some cases you may even have more than two values you want to select from. This is where the extensible multiplexer comes into the picture. You might even find the word multiplexer familiar if you know a bit of digital electronics. And this block has the same functionality – to choose one out of many inputs.
Like the precious block, this block has two types of inputs. A condition (selector) and some input values. The block selects one of N inputs depending on the value of the selector.
Unlike the binary selector the condition input, named K in this block, can not only take a boolean data type. In fact, it can take up any elementary data type. Although the only data type that really makes sense to use here is an integer.
As you have to choose between inputs from IN0 to INn it only makes sense to give the condition K a whole number. Actually it is only valid to give K a number between 0 and n. The concept of the function may look like this:
OUT := INK
Where K has to be within the range 0 – n, where n is the number of inputs.
Extensible Minimum Function (MIN)
So far you have seen how to select values using a condition input. That input could be either binary or an integer depending on how many inputs you have to choose between
But sometimes you will want to select a value depending on the values them self. It could be that you want to select the highest or the lowest value among different variables.
With the next two function blocks you can do exactly that.
Choosing the variable with the smallest value is something that I can guarantee, that you will use at some point. The official name for this function block is extensible minimum, but often just called minimum or MIN. It is called extensible because you can add any number of inputs on the block. All the inputs can take any elementary data type, and they can even be of different data types on the same block.
OUT := MIN (IN1, IN2)
What will be assigned to the output of the block is always the value of the smallest input. Or put in other words – the input with the minimum value will be selected.
Extensible Maximum Function (MAX)
When you have a block for finding the minimum value, you will of course also have a block for finding the maximum value. FBD also provides a standard function block for doing that.
It works exactly the same way as the minimum function, but selects the variable with the maximum value and assigns that value to its output.
Also this block takes any elementary data type as input and output.
With both these blocks you should be aware which data type you use at the output. If you are trying to find the maximum value of two real data types e.g. 80.46 and 206.95 and you use integer as output, the output will simply be 206.
OUT := MAX (IN1, IN2)
A smart feature with these two blocks is that you can also compare time and date data types. Say you have a lot of date stamps in your PLC program and you want to find the latest. With the maximum function you can always find the most recent date.
By combining the two previous function blocks we can create a whole new function. This function is not so much about selection, but rather about limitation. That is why this function block is called limiter. More than often you will want to set limits to a range of values in a PLC program.
The limiter function is really just made up by the minimum and maximum functions. This can be seen if we take a look at the function block body:
OUT := MIN ( MAX (IN, MN), MX)
What really happens here is that you set a minimum and a maximum limit for whatever variable you put at the input (IN). The min and max values are set at the inputs (MIN and MAX) and all three inputs can take any elementary data type.
Make your own function blocks
All these function blocks above are most of the ones described in the IEC 61131-3, the official standard for PLC programming languages. There are many more function blocks provided in function block diagram. Actually there are almost a function block for every operation you can do in PLC programming. Among those are:
- Arithmetic Function Blocks
- Bit Shift Function Blocks
- Character String Function Blocks
- Conversion Function Blocks
- Communication Function Blocks
And many more…
I highly recommend that you just start out by playing around in your Automation IDE like TIA Portal or Codesys. Try creating simple PLC programs using function block diagram programming. I find that is the best way to learn about new function blocks.
The point here is that every function block represents a function. Inside the function block body you will find that the function is described in either structured text, ladder logic or another PLC programming language. There are many standard blocks providing you with a lot of different functions. But sometimes it’s just not enough.
This is why you will need to build your own function blocks. This is in fact one of the cornerstones in structured PLC programming. Stay tuned on PLC Academy to learn more about that 🙂