Skip to content



This tutorial shows how to use CODESYS together with FACTORY I/O through OPC UA. By following this sample you will create a new CODESYS project, configure it to work with FACTORY I/O and program the CODESYS Control Win (SoftPlc) to control the Sorting by Height (Advanced) scene.

The sample code used in this tutorial is based on the solutions found on the book Industrial Automation Practices.

Creating the Project

  1. Start CODESYS and create a new project.

    create new codesys project

  2. Select Standard project from the Templates list and choose a name for the project (e.g. Tutorial). Click on OK.

  3. On the Standard Project window select the Device CODESYS Control Win V3 (3S - Smart Software Solutions GmbH) and Structured Text (ST) for the PLC_PRG. Click on OK.

    select project device

  4. Right-click on Application and select Add Object > Global variable List.... Type FIO as the list name, click on Add.

    add global variable list

  5. Open the FIO list by Double Left-clicking on it and copy and paste the following global variables. These variables will be used to exchange data between FACTORY I/O and CODESYS thought OPC UA (these are the I/O points).

        iAtEntry        : BOOL;
        iLowBox         : BOOL;
        iHighBox        : BOOL;
        iAtTurnEntry    : BOOL;
        iAtLoadPos      : BOOL;
        iAtUnloadPos    : BOOL;
        iAtFront        : BOOL;
        iAtRightEntry   : BOOL;
        iAtLeftEntry    : BOOL;
        iAtRightExit    : BOOL;
        iAtLeftExit     : BOOL;
        oFeederConveyor : BOOL;
        oEntryConveyor  : BOOL;
        oLoad           : BOOL;
        oUnload         : BOOL;
        oTurn           : BOOL;
        oLeftConveyor   : BOOL;
        oRightConveyor  : BOOL;

    global variable list

  6. On the Devices tree Double Left-click on PLC_PRG (PRG) and copy and paste the following variables. These are the variables you will be using in your program.

        F_AtEntry           : F_TRIG;
        F_AtTurnEntry       : F_TRIG;
        F_AtRightEntry      : F_TRIG;
        F_AtLeftEntry       : F_TRIG;
        F_AtRightExit       : F_TRIG;
        F_AtLeftExit        : F_TRIG;
        Pallet_on_left      : BOOL := FALSE;
        Pallet_on_right     : BOOL := FALSE;
        Idle                : BOOL := TRUE;
        Charging            : BOOL := FALSE;
        Turns_charged       : BOOL := FALSE;
        Discharging         : BOOL := FALSE;
        Turns_Discharged    : BOOL := FALSE;
        Turntable_busy      : BOOL := FALSE;
        Discharge_direction : BOOL := FALSE;
        Entry_busy          : BOOL := FALSE;
        Pallet_on_entry     : BOOL := FALSE;
        Count               : WORD := 16#8000;

    program variables

  7. Now, copy and paste the following code. This is the program that will control the Sorting by Height (Advanced) scene.

    F_AtEntry(CLK := FIO.iAtEntry);
    F_AtTurnEntry(CLK := FIO.iAtTurnEntry);
    F_AtRightEntry(CLK := FIO.iAtRightEntry);
    F_AtLeftEntry(CLK := FIO.iAtLeftEntry);     (* A pallet abandons the turntable, being charged onto the left exit conveyer *)
    F_AtRightExit(CLK := FIO.iAtRightExit);
    F_AtLeftExit(CLK := FIO.iAtLeftExit);       (* A pallet abandons the left exit conveyer *)
    (* Pallet_on_left represents the state of the left exit conveyer: if it carries a pallet, then Pallet_on_left = TRUE *)
    IF F_AtLeftExit.Q THEN                      (* When a pallet abandons the conveyer *)
        Pallet_on_left := FALSE;                (* Reset Pallet_on_left *)
    IF FIO.iAtLeftEntry THEN                    (* When theres a pallet at the entry of the conveyer *)
        Pallet_on_left := TRUE;                 (* Set Pallet_on_left *)
    FIO.oLeftConveyor := Pallet_on_left;        (* Left exit conveyer runs for Pallet_on_left = TRUE *)
    IF F_AtRightExit.Q THEN
        Pallet_on_right := FALSE;
    IF FIO.iAtRightEntry THEN
        Pallet_on_right := TRUE;
    FIO.oRightConveyor := Pallet_on_right;
    (**** TURNTABLE CONTROL ****)
    IF Idle AND FIO.iAtTurnEntry THEN
        Idle := FALSE;
        Charging := TRUE;
    IF Charging AND FIO.iAtFront THEN
        Charging := FALSE;
        Turns_charged := TRUE;
    IF Turns_charged AND FIO.iAtUnloadPos THEN
        Turns_charged := FALSE;
        Discharging := TRUE;
    (* The turntable discharges now onto both conveyers. Thus: *)
    IF Discharging AND (F_AtRightEntry.Q OR F_AtLeftEntry.Q) THEN
        Discharging := FALSE;
        Turns_Discharged := TRUE;
    IF Turns_Discharged AND FIO.iAtLoadPos THEN
        Turns_Discharged := FALSE;
        Idle := TRUE;
    IF F_AtTurnEntry.Q THEN
        Turntable_busy := TRUE;
    IF Idle THEN
        Turntable_busy := FALSE;
    (* Computing control outputs according to the current state of the turntable and the direction of the discharge *)
    FIO.oLoad := Charging OR Discharging AND Discharge_direction;
    (* oUnload is TRUE if the discharge is onto the left conveyer *)
    FIO.oUnload := Discharging AND NOT Discharge_direction;
    (* oTurn is TRUE if the discharge is onto the right conveyer *)
    FIO.oTurn := Turns_charged OR Discharging;
    IF F_AtEntry.Q THEN
        Count := ROL (Count,1);
        IF (Count = WORD#16#2) THEN
            Entry_busy := TRUE;
    IF F_AtTurnEntry.Q THEN
        (** Defining the direction of the discharge: the direction of the discharge changes every time a pallet is
        discharged from the entry conveyer onto the turntable. If Discharge_direction = FALSE, then the discharge is onto the right conveyer **)
        Discharge_direction := NOT Discharge_direction;
        Entry_busy := FALSE;
        Count := ROR(Count,1);
        IF (Count = WORD#16#8000) THEN
            Pallet_on_entry := FALSE;
    IF FIO.iAtEntry THEN
        Pallet_on_entry := TRUE;
    FIO.oEntryConveyor := Pallet_on_entry AND (NOT Turntable_busy OR NOT FIO.iAtTurnEntry);
    FIO.oFeederConveyor := NOT Entry_busy OR NOT FIO.iAtEntry;


  8. Start CODESYS Control Win V3.

    codesys softplc

  9. Get back to CODESYS and on the project tree, Double Left-click on Device (CODESYS Control Win V3) and then on Communication Settings. Now, click on Scan network... Select the network path to the controller and click on OK. Note that the device name can be changed by clicking on Device > Rename active device.

    select device

  10. In the toolbar click on Build > Build (F11) to download the program to SoftPLC.

  11. Now, Right-click on Application and select Add Object > Symbol Configuration. On the Add Symbol Configuration window check Support OPC UA features, next click on Add. Now, check the FIO symbols (see image below) and click on Build.

    fio symbols

  12. Next, click on Online > Login (Alt+F8). When prompted to download the program to the PLC, click on Yes.

  13. Finally, click on Debug > Start (F5).

Setting up FACTORY I/O

  1. Open the Sorting by Height (Advanced) scene and click on File > Driver Configuration.

  2. Select OPC Client DA/UA from the Driver list and click on CONFIGURATION.

    select opc driver

    opc driver

  3. Select UA: opc.tcp://localhost:4840 from the OPC Server list. Set "FIO" as the contain filter (see image below), this will filter items containing "FIO" (the Global Variable List defined in CODESYS) in the node ID. Next click on BROWSE.

    select codesys opc server

  4. Map the sensors and actuators tags as shown on the image below.

    tag mapping

  5. Finally, close the Driver window and start the simulation (press F5).