Custom Functions and Function Blocks (FBs)
Why Create Your Own?
The purpose of functions and function blocks is to share programs: instead of several people each writing similar programs separately, combine them into one program that everyone uses
● It reduces programming effort compared with several people separately creating similar things
● Using the same program keeps program quality consistent
Create a Function or a Function Block? Which One?
If the processing can output a result in one scan, use a function
For calculations, create a function unless a very large amount of calculation is needed
If the processing needs multiple scans, use a function block
Processing that needs multiple scans includes communication, motion and file operations
Rough criteria for choosing FUN or FB
| Processing | Recommended |
|---|---|
| Arithmetic | Function |
| Unit conversion | Function |
| String processing | Function |
| Timer | FB |
| Communication | FB |
| File operations | FB |
| Motion control | FB |
Differences between Execute type and Enable type
| Item | Execute type | |
|---|---|---|
| Start | Rising edge | Continuous while ON |
| Busy | Yes | Usually none |
| Done | Yes | Usually none |
| Use | Communication, file operations | Continuous monitoring |
Rules (etiquette)
In-out
When a value is entered at the input, the result is output at the output
Match the inputs and outputs to one of the following three basic forms
In practice there will be multiple inputs and outputs, but if there are many input variables, say 10, it is a good idea to group related variables into a structure
Function
| Variable name | Description | ||
|---|---|---|---|
![]() | Input | EN | Execute Executes the processing inside the function while ON |
| Input | Input parameters | ||
| Output | ENO | ||
| Blank (Out) | Return value Output here when not BOOL |
Execute-type FB
| Variable name | Description | ||
|---|---|---|---|
![]() | Input | Execute |
Start The inside of the FB is always running Processing starts on the rising edge of Execute Processing continues until complete even if Execute turns OFF When processing completes, either Done or Error turns ON |
| Input | Input parameters | ||
| Output | Done | ON at normal completion | |
| Busy | ON while executing | ||
| Error | ON at error completion | ||
| ErrorID | Error code output | ||
| Output | Processing result |
Make each Execute-type flag behave as in the following timing chart
Enable-type FB
| Variable name | Description | ||
|---|---|---|---|
![]() |
Input | Enable |
Execute The inside of the FB is always running When Enable turns ON, Enabled turns ON and processing runs When Enable turns OFF, Enabled turns OFF and processing ends |
| Input | Input parameters | ||
| Output | Enabled | Executing | |
| Output | Processing result |
Points to Watch
Input variables, output variables and in-out variables
Input variables and output variables are passed by value (ByVal)
In-out variables are passed by pointer (ByRef)
Normally, use input variables and output variables
When you want to pass a large variable (for example an array of 10,000 WORDs) as an input variable, it is better to make it an in-out variable
The reason is...
For input variables, the value is copied into a variable inside the FB instance before the program in the FB runs
The result is copied into the output variable to pass the value outside the FB (because input and output variables are passed by value, large arrays incur copy costs, creating overhead and making processing slower)
This happens where the programmer cannot see it, so note that the scan time increases by the time spent copying
In contrast, in-out variables read and write the variable's value directly without copying
Because no copying takes place, making a large variable an in-out variable does not increase the scan time
External variables
As a rule, avoid them
Only system-defined variables are acceptable
As soon as user-created global variables are used here, the Fun/FB can no longer be a reusable component and becomes usable only in that project
If you want to use user-created variables, make them input variables
Input checks
Do not forget error handling for unexpected values on input variables
Also set initial values where needed in case nothing is connected to an input variable
Values to put in ErrorID
ErrorID basically outputs the ErrorID of the instruction used inside the FB as-is
If there is an ErrorEx, also add ErrorIDEx to the output variables
If you assign your own error IDs, put a code indicating an original error in ErrorID (for example #FFFF) and the detailed error ID in ErrorIDEx to make them easy to distinguish
FAQ
When creating your own, should I choose a Function or a Function Block?
Processing that can return a result in one scan suits a Function; processing that spans multiple scans, such as communication or motion control, suits a Function Block.
What is the difference between Execute-type and Enable-type FBs?
An Execute-type FB starts processing on a rising edge and uses Busy, Done and Error. An Enable-type FB keeps operating while the Enable signal is ON and is mainly used for monitoring and similar processing.
How should I use input variables, output variables and in-out variables?
Normal input and output variables are ByVal. When handling data with a high copy cost, such as large arrays, using ByRef in-out variables keeps the scan time from increasing.
Should external variables be used in FBs?
As a rule, avoid them and pass the necessary data as input variables. Depending on external variables reduces reusability.



