
The Variant data type is a special data type that accepts almost anything. Similar to the ANY data type, TIA Portal essentially creates a pointer to the data and passes that, but with a few extra elements:
- Start Address – The address that the data starts at
- Length – The length of the data
- Original Type – The data type of the original data
Whilst you cannot access the above data directly, TIA Portal offers functions that do interact with the internal data.
Use Cases
Variants are extremely useful when you have a standard function block that requires the ability to service 2 or more variations of a section of the code.
For example, consider a Variable Speed Pump, you have some standard code that works with your system’s SCADA that allows operators to set speeds, start the pump, stop the pump ect. But, from a hardware point of view, you have 2 variations of manufacturer in your asset range.
With Variants, you can pass the structure for VSD 1 to your standard block, and the block will run a section of code for the VSD. When you pass VSD 2 to the same block, on the same pin, the block knows that it’s VSD 2 and runs a different section of code
I’ve written a simplified diagnostic block, pictured above that explains the concepts behind this.
Variant Usage In Blocks – Example
The first thing to note is that Variants cannot be used in Global Data Blocks, or Instance Data Blocks unless being passed as an INOUT, INPUT, or OUTPUT. IT is not possible to create a variant in STATIC data, but you can in TEMP data.

Data
in the INOUT interface of a FunctionThe above image shows a Variant in use in the Function Diagnostic_Check
. This means that the variable Data
will accept anything
It’s important to understand that a Variant serves to purpose in Logic. You can’t perform many functions on Variables since the instruction cannot determine the type of data, or the data is Complex (A structure for example)
Once the Variant has been passed into the block it is to be used in, the next step is to determine what the data actually is.
The Example from here on in is written in SCL, however you can achieve this in any language with a slightly different instruction set
Checking For Data Type

TypeOf
, check if the data type within the Variant Data
matches a predefined type in the blockThe above SCL code is using the TypeOf
instruction to check the original data type of the Variant Data
. Our interface of our block contains System_A
and System_B
, which are both UDTs of different types:

System_A
and System_B
as TEMP variablesThese are declared in the TEMP scope of the interface and are used in conjunction with TypeOf
to provide a test case in the logic.
If the TypeOf(#Data) = TypeOf(#System_A)
is True
, then we load #A
into a #Type
variable. #A
is a Constant and is simply providing a numerical value to #Type
, so we know which type of system has been passed to the block
At this point, we now know that System A or System B has been passed to the block (or neither if something has been passed)
Moving Data From Variant To Usable Data Type
Now that the Data type is known, the actual data needs to be accessible. This can be done using the BLKMOV
instruction:

BLKMOV
instruction moving Data
into System_A
You cannot use BLKMOV
with Optimized Data.
The BLKMOV
instruction simply overlays data from one area to another, thus moving data from Data
to System_A
, even though the data types do not match (Variant
and UDT_System_A
)
At this point, the data that was originally passed in as UDT_System_A
in a TEMP variable called System_A
that is also the data type UDT_System_A
. This means that System_A
can be worked with from this point in and contains the same values as Data
Performing Logic

System_A
The above code shows that if System A is being worked with (Case #Type Of #A
), then the following OUTPUT variables are updated:
- Type_String –
System_A
- Data_Buffer – Entire
Data
Structure as a DWORD - Additional_Data –
16#AE

These variables are passed outside of the block as OUTPUTS

System_A
DataSystem_A.Fault
is checked and if True
, .Signal
is modified to False
. This works fine, however remember that System_A
is in temporary memory, and is disassociated from Data
. This means System_A
needs to be written back to Data
:

BLKMOV
moving System_A
with updated values, back to Data
The Data
variable will then be passed through the INOUT interface, back to the original data, with the updated values.
Complete Example
Below is a complete runthrough of the example

Global Data Block – Systems
Contains instances of UDT_System_A
and UDT_System_B
. These are passed in the Main
block to the Diagnostic_Check
Functions.

Main (OB1)
Calls two instances of Diagnostic_Check
, the first with "Systems".A
and the second with "Systems".B
These two systems contain different data. A
contains a Bool
data type and B
contains a Real
data type.
Conventional methods would not allow both of these systems to be passed to the same pin (Data
) of the Function because the data types wouldn’t match
Data
is defined as a Variant
, so both system types are accepted

Diagnostic_Check Function
This Function
is taking in the Data
Variant and checking the data type.
If System_A
(UDT_System_A
) is found at the Data
pin, then the Case
#A
is executed
If System_B
is found, then Case #B
is executed
In both cases, data is moved to the output pins and the Signal
is written to a value if Fault
is True
The difference between System_A
and System_B
is that System_A
sets a Bool
value and System_B
sets a Real
value at the Signal
variable.
Conclusion
Variants can be a difficult concept to wrap your head around, and the above is only a basic example.
They can be super powerful in ensuring you don’t have multiple blocks of code that all perform 95% of the same logic, but have differences because of different data types that need to be handled.
Remember that every data type that needs to have logic executed against it needs to exist in your Function or Function Block.
If you have 1 block that accepts 100 different types, that means that 99% of the code is doing nothing but taking up space
You need to evaluate what is best for your project when using variants to ensure you don’t “over-do-it” with flexibility.
If you have any questions on the topic, hit the comments below, or ask me on LinkedIn via the below link
Check Out Another Post
TIA Portal Basics – Setting Up Put/Get
Put/Get communication is very common in TIA Portal applications where more than 1 Siemens PLC is involved. It’s simple to…
In TIA V17 BLKMOV falls under ‘Legacy’, is there an updated instruction we should use for this operation? I notice there are MOVE_BLK and MOVE_BLK_VARIANT instructions also available. It is a bit frustrating that TIA doesn’t allow us to access the size of the data directly :(.
Hi Dennis,
That’s interesting, I’m using TIA Portal V17 daily, but can’t say I’ve paid much attention to the classification of the instruction. I’ll do some digging on this!
What do you mean about accessing the size of the data directly?