Tutorial CodeSys V3 controller via OPC UA

With PLC-Lab a virtual plant can be used to test a PLC program for CodeSys V3 controllers. The communication between PLC-Lab and the CodeSys controller is realized via OPC UA.

PLC-Lab supports the device OPC UA as of version

The following steps are necessary for this in the CodeSys project:

  1. Create the user defined data type (DUT): PlcLabData.

  2. Create the global list of variables (GVL): PlcLabConnector.

  3. Create the program organization unit (POU): PlcLabSync.

  4. Call the function "PlcLabSync" in PLC_PRG.

  5. Enable the access of PlcLabConnector via OPC UA inside the symbol configuration.

  6. Change the plc settings: Always update variables.

In the following example a plant is created and used to test a PLC program for a CodeSys V3 controller. The PLC program is to be processed by a CODESYS Control Win V3-SoftPlc. The procedure with a hardware PLC from e.g. Wago or Schneider Electric is identical.

In the example the programming software CODESYS V3.5X is used. However, IEC programming tools from other manufacturers such as e!COCKPIT, Machine Expert, TwinCAT etc. can also be used. The terms are partly identical.

Start of the CodeSys programming software

The first step is to create a new project in CodeSys, but you can also open an existing project. If a new project is created, you can use a standard project as a template.

Afterwards the context menu is opened in the project tree at the node "Application" and a folder is added.

The folder is given the name "PlcLab". The objects required for communication with PLC-Lab are to be stored in this folder.

Creating the user defined data type (DUT): PlcLabData

Now the folder is selected and a "data unit type (DUT)" object is added using the context menu.

A structure is selected as type and the name "PlcLabData" is assigned.

The structure has the appearance shown in the following picture.

Enclosed the code, which can be directly copied and pasted into CodeSys.

TYPE PlcLabData :
    CntBytes:WORD; //how many bytes?
    Addr:WORD; //Ofs addr
    IoOfs:WORD; //IO offs addr

Creating the global list of variables (GVL): PlcLabConnector

The next step is to insert a global variable list in the "PlcLab" folder. The previously created data type is then also used here.


The name "PlcLabConnector " must be entered, because this name is required for communication via OPC UA.

The following picture shows the GVL.

The content of the GVL (seen in the following box) can be copied and directly inserted into CodeSys.

    _SIZE_AREA_I_ARRAY : WORD := 10; //how many areas are defined? 
    _SIZE_AREA_Q_ARRAY: WORD := 10; //how many areas are defined? 
    _SIZE_I_ARRAY : WORD := 1024;
    _SIZE_Q_ARRAY : WORD := 1024;

    SIZE_Q_ARRAY : WORD := _SIZE_Q_ARRAY;    //1024
    Inputs: ARRAY[0.._SIZE_I_ARRAY-1] OF BYTE; //is written by PLC-Lab
    Outputs: ARRAY[0.._SIZE_Q_ARRAY-1] OF BYTE; //is read by PLC-Lab
    AreaInputs: ARRAY[0.._SIZE_AREA_I_ARRAY-1] OF PlcLabData; //is written by PLC-Lab
    AreaOutputs: ARRAY[0.._SIZE_AREA_Q_ARRAY-1] OF PlcLabData; //is written by PLC-Lab

Creating the program organization unit (POU): PlcLabSync

The variables from the GVL are used in a function. This function must first be created.

On the dialog that appears, a function is set as the type and the name "PlcLabSync". The implementation language is "ST".

After confirming the input, the function is generated. The code can be seen in the following picture.

In the following the code of the function is shown again, it can be copied directly and pasted into CodeSys.

    BytePtr:POINTER TO BYTE;  

IF Inputs THEN
    //Write sensor data of PLC-Lab to the PLC Inputs
    FOR a := 0 TO PLCLabConnector.SIZE_AREA_I_ARRAY-1 DO
        IF PLCLabConnector.AreaInputs[a].CntBytes=0 THEN //nothing to do anymore
        FOR b := 0 TO PLCLabConnector.AreaInputs[a].CntBytes DO

IF Outputs THEN 
    //Write PLC outputs to the PLC-Lab outputs
    FOR a := 0 TO PLCLabConnector.SIZE_AREA_Q_ARRAY-1 DO
        IF PLCLabConnector.AreaOutputs[a].CntBytes=0 THEN //nothing to do anymore 
        FOR b := 0 TO PLCLabConnector.AreaOutputs[a].CntBytes DO

Calling the function "PlcLabSync" in PLC_PRG

Thus all program parts necessary for the communication with PLC-Lab are available. The function "PlcLabSync" must only be called as the first operation within "PLC_PRG". In the picture the call is shown in the implementation language ST.

Behind it, you can then add your own code.

Now the code of the call as code snippet:

//Sync the PLC-Lab data with the inputs and outputs
PlcLabSync(Inputs:=TRUE, Outputs:=TRUE);

Adding the symbol configuration

To make the structure "PlcLabConnector" accessible via OPC UA, it must be set in a symbol configuration as accessible via OPC UA. For this purpose, a symbol configuration must first be added as an object. The object is to be added to the application, so this node is used to call the context menu.

The next picture shows the dialog with the option "Support OPC UA Features" which must be selected.

Now the PLC program must first be created, i.e. translated, so that the variables appear in the system configuration. This can be initiated at the top edge of the symbol configuration.

As a result the variables of the project are listed in the window and the variables that are to be accessible via OPC UA may be selected. In the example this is only "PlcLabConnector".

PLC code for the example

For the example with PLC-Lab a small PLC program is necessary. Here, output QX0.0 is set to status 1 (true) via input IX0.0. As soon as input IX0.1 has the status 1 (true), the output is set to the value 0 (false).

Changing the plc settings: Always update variables.

In order for the reading of the outputs and the writing of the inputs by PLC-Lab to work, a certain setting must be made within the PLC settings. For this purpose, the context menu is called at the "Device" node and the menu item "Edit object" is selected.

As a result, the settings of the PLC can be seen. Here the section "PLC settings" is selected and the setting "Activated 2 (always in bus cycle task)" is selected at the property "Always update variables".

Starting the SoftPlc or connecting the hardware plc

In the example the PLC program is executed in the SoftPLC "CODESYS Control Win V3". This must be started first, if this is not already the case. For this purpose the right mouse button is pressed in the Windows tray above the symbol to display the context menu.

This is started by means of the menu item "Start PLC".

If a hardware PLC is used, it must be switched on accordingly and connected to the PC.

Login and changing of the operating mode

For logging in, the menu item "Online->Login" is executed.

This transfers the PLC program and the configuration to the PLC. If the PLC is in the "Stop" operating mode after this process, it must be switched to "Run".

Now all preparations on the CodeSys PLC side are done and the creation of the virtual plant in PLC-Lab can be started.

Starting PLC-Lab and creating of a new device

After the start of PLC-Lab a new project is created with the button "New".

The symbol table is located in the lower area of the newly created project. Here a new device can be created.

To do this, press the button marked in the above image. The dialog "Create new device or connection" is displayed. Select "OPC UA" as device type and enter a name for the device.

The dialog to set the parameters of the OPC UA device appears.

IP-Address (1)

The IP address of the PLC to be addressed must be entered here. In the example the SoftPLC to be addressed has the IP address "".

Port-Address (2)

Port 4840 is normally used as port address. This should only be changed if the setting in the PLC has been changed.

Polling rate (3)

The polling rate in milliseconds indicates how often the status of operands is read from the PLC. In the example the value 50ms is set.

Name of container-variable (4)

The variable name of the container on the PLC side is permanently set to the name "PlcLabConnector". For this reason it was also important that the global variable list in CodeSys has this name. From this container, the data of PLC-Lab are read or written into it.

Address mode

Since the example communicates with a CodeSys PLC, the "Address mode for CodeSys systems" must be set as the addressing type. Otherwise the access to the operands or their values will not be correct. Especially for word and double word operands.

Once all settings have been made, the dialog is exited via "OK".

Creating the symbols of the operands

Three operands are required for the example. The symbols are to be created in the symbol table for these operands. First the device has to be selected, in the example the device "CodeSysViaOpcUa".

Afterwards, the symbols can be inserted using the button with the plus symbol. This is shown below.

The two input bits I0.0 and I0.1 and the output Q0.0 are required. Alternatively, the German syntax can be used for the operands (E0.0, E0.1 as well as A0.0). The operands are assigned symbols which describe their task.

Creating the first switch-object

For the example, two switch objects are required, which are to be configured as pushbuttons. The two are taken from the section "Switches"->"Switches not illuminated". First the first switch object.

After the switch has been placed, its properties can be seen within the table with the properties of the objects. In the example, the operand to which the switch object is connected is to be specified first. This is influenced when the switch is activated. There are several possibilities for specifying the operand:

First option "Autocompletion": In the first option, in the cell for the operand, the device name followed by a period is specified first; in the example, this is "CodeSysViaOpcUa.". Then use the key combination Ctrl + Space. As a result, all symbols of this device are now displayed in a list. Select the symbol you want to use with the cursor keys (../up or down) and confirm with the return key. The selected symbol is then entered as an operand. These steps are shown below:

Second option "drag & drop": With the second option, you select the line of the operand in the symbol table and then drop it on the description of the operand property or the properties editor using drag & drop.

Third option "drag & drop" to the switch object: Now for the third option. In this case, you also select the operand from the symbol table and then drag and drop it. But here the target is the switch. This means that the operand is dropped directly on the object. For switch objects, the operand you have inserted is automatically inserted as the operand that is affected by the switch.


The advantage of the options 2 and 3 is that the symbol of the operand is automatically used to label the switch object.

When you have used one of the options, the switch is connected to the symbol "Start" and thus to the I0.0. Now the switch object must be defined as a push-button. Furthermore, "Start" should appear as text with a font size of "12" in the switch object. The properties required for this are shown below:

Drawing the second push-button

Now we move on to the second switch object that we need. We want to create this switch from a copy of the first switch. Select the first switch and press Ctrl + D. A copy of the selected switch is then placed next to the source object.

To display the properties of the new switch in the table, click on a free space in the draw-window and then select the new switch with the mouse. Now the properties are displayed and can be changed.

In the first step you have to adjust the operand of the switch. This is supposed to be the "Stop" push-button. We will do this using the third option described above. The operand with the symbol "Stop" in the symbol table is dropped over the switch object using drag & drop.

This action also changes the label because the symbol of the new operand is used as the label of the switch object.

Drawing a lamp

Finally, we need a lamp object to signal the "Start" state. For this purpose, select a green indicator light in the object selection "Lamps->Indicator lights".

The lamp can then be placed on the drawing board.

In the next step, assign the operand with the symbol "Lamp" to the object. This is also done via drag & drop on the object.

Now you have set the operand as a lamp operand. You can remove the caption from the lamp.

This means that no more text is displayed in the object.

After these actions, the drawing board looks as follows:

The PLC-Lab project is now complete.

Starting the simulation

Since the CodeSys PLC is already connected and is in the operating mode "run", the simulation can also be started in PLC-Lab. For this purpose, the following button is pressed in PLC-Lab:

PLC-Lab then tries to establish the connection via OPC UA. Once the connection has been established, the display in the lower area of PLC-Lab changes as follows:

Testing the PLC program

In the next step the buttons in PLC-Lab can be pressed and the reaction of the PLC program can be observed. In the following picture the start button was pressed. As a result, output Q0.0 is set to status 1 and the lamp lights up.

In this way, even more extensive PLC programs can be tested by operating the system in PLC-Lab and observing the effects in the programming tool.


The example was used to show how a CodeSys project can be supplemented so that PLC-Lab can access the PLC to be programmed via OPC UA, thus enabling simulation via a virtual system in PLC-Lab.