Installation, IDE, Architecture and First Example (Linear Gauge)

We need to install few software before we start developing SCADA/HMI in Beckhoff platform. As we have already understood the differences between HMI and SCADA, we shall mention only HMI in this page. Download the following software in your hard disk.


=> .Net 4.7.2 developer pack or equivalent

=> Visual Studio (2013, 2017 or 2019) community or pro version

=> TwinCAT 3.1 – eXtended Automation Engineering (XAE), version 3.1.4024.7

=> TE2000 | TC3 HMI  , version 1.10.1336.404

Beckhoff software has engineering version and run time version. We shall use engineering version for developing the application and on the other hand run time is used for only executing the program. One good example is that when we install Beckhoff TwinCat Software to PLC, we install only the run time version. Even it is not possible to install engineering version to PLC due to memory constraint. Engineering version offers all the development, debug etc tools on top of run time.


Download all the software and run those executables as administrator. Good to install visual studio before installing TwinCAT 3.1


Architecture, how HMI works in Windows platform

A Windows sockets (Winsock) is an application programming interface (API) that allows for communication between Windows network software and network services, such as Transmission Control Protocol/Internet Protocol (TCP/IP). Winsock is based on the Berkeley Unix sockets interface. These works on client server basis.

Operating systems Windows includes a data link layer named winsock.dll, which helps to make the Windows programs and the TCP/IP services work together. If you are more interested you could take a look in this link to know how these work. Since our job is to develop HMI we don’t need to know these in details. Beckhoff has done it for us.

First Example (Linear guage)

We assume that the necessary software are installed. We shall build a project and test  and publish it to remote HMI server.

STEP 1: Start Visual Studio and open a new TwinCAT HMI project.

STEP 2: Select Tool Box (if not visible select View | Tool Box)

STEP 3: Drag and drop Linear gauge on the desktop view, make one of those vertical (properties | appearance | orientation)


The linear example final one is shown below. If we press on Start button then it will start reading the pressure sensor and display on the left side linear gauge. The Start button will be changed to Stop. If the PLC is already running then it will the status of the variable and set the text as needed.

PLC Source code behind the HMI

Since we don’t have actual pressure sensor, we are using a small piece of  structured text code for generating pressure sensor value. That pressure value is shown on the linear gauge. When the startTimer variable is TRUE then then timer will start and generates data (pressureValue). pressureValue is shown on the Beckhoff HMI.




pressureValue : REAL := 0.0;

myTimer : TON;

startTimer : BOOL := FALSE;

directionPlus : BOOL := FALSE;


//Body of the program

myTimer(IN:= startTimer, PT:= T#50MS);

IF myTimer.Q = TRUE THEN

myTimer(IN:= FALSE);

IF pressureValue >= 100 THEN

pressureValue := 100.0;

directionPlus := FALSE;


IF pressureValue <= 0 THEN

pressureValue := 0.0;

directionPlus := TRUE;


IF directionPlus = TRUE THEN

pressureValue := pressureValue + 1.0;


pressureValue := pressureValue – 1.0;



HMI and the simulator PLC code relation

Above picture shows pressureValue is linked to Lineargauge and StartTimer is linked to Start button.

How to build the HMI

Few  steps are needed before reading the data from PLC (we assume that Button and Linear gauge are placed on the UI)

We need to bring those PLC variable available to the UI project. These are done for us by the framework, we just use those. More will be discussed in the next tutorial (Symbol Data)

First we need to configure the  HMI Server

STEP 1: Select from the Menu  TWINCAT HMI | Windows | TwinCAT HMI Server configuration

STEP 2: Click on ADS | Runtimes | PLC1 and make the necessary changes  as shown in the following figure. If we want to read from actual PLC, we shall use actual AmsNetId. The PLC should be in the same network (for more see our network tutorial)


Now we shall have a connection to our PLC but we need to tell the framework  which variables we want to manipulate  or want to listen. This process is called  symbol mapping

STEP 3: Now go back to  HMI Configuration Select from the Menu  TWINCAT HMI | Windows | TwinCAT HMI  configuration 

STEP 4: Select Server Symbols | All Symbols | then expand the ADS | PLC1 | MAIN | Map Symbol

STEP 5: Select pressureValue and startTimer variables and map it, these will be added to Mapped Symbols



Now let’s configure the button

STEP 6: Go to button events and pressed on  the edit icon,  drag  and drop  General | Condition to the right pane. Drag and drop WriteToSymbol to the THEN box and to ELSE box

STEP 7:  Select small square and Create data binding

STEP 8: Insert the Text field (selected control | Start | Common | Text)  and the value to STOP, this will indicate if the startTimer is TRUE then the button text will be Stop (more in the localizations tutorial)

Final STEPS:  Do the same for  .onPressed for the button  and for value for the linearGauge case as shown in the next few images. If you press on the Live view or debug with google chrome we see that value changes when we press the start button and stop when we press the stop button

Following figure shows how to configure the text of the button when the button is created by the framework. This is good place to check or set the text of a button or similar control


Following figure shows how to configure onPressed event for button. Write To Symbol statements are used 2 times in if branches.


Value property of the lineargauge has been configured  to the pressureValue variable in PLC

We shall add a video here soon, please do visit us again

Symbol Data

In TwinCAT HMI a variable is called a symbol. This symbol can be mapped or linked to PLC variable. Some symbols can be local to HMI server. That means it is not read from PLC.

Mapping is the event of telling HMI Server where the needed symbols are located in PLC

Binding is a process of linking between 2 variables from target devices (PLCs) with ADS protocol.

How to make PLC data available to HMI Server

=> First we need to give access to the PLC. The PLC can be in the local network, remote network or even the local machine (PLC program is running in the same machine). The PLC is identified by the Ams NetId.

=> If the PLC is in the network then the HMI Server computer (where the HMI Server is running) should have the route, for details see how to add route for searching Beckhoff PLC.

=> If the PLC is running in the local PC, we add the local host address “” + “1.1”

=> For remote machine, it is wise to set the AmsNetId to  IP address + .1.1,  this help to remember the AmsNet Id, see how to change Ams Net Id

=> You can bring the left hand side setting dialog by selecting HMI Project | Server   and then from the menu  TWINCATHMI | TwinCAT HMI Server Configuration.

=> Set Enabled  to true, AmsNetId and the port number and press accept.

Note: In some smaller controller Symbol name is not supported, in this case the data can be accessed directly by using indexGroup and indexOffset (in that case,  we press on Symbols and then Add)

Mapping variables to TwinCAT HMI

Adding Ams Net Id establish a link between the HMI Server  and the PLC. HMI Server does not know what kinds of variables are available in the PLC yet. The mapping process establishes a  connection between HMI Server and the PLC so that HMI Server can read those data over the Beckhoff ADS protocol.



=> Select the HMI project and then Server in the solution explorer

=>Now select the HMI Configuration as shown in the left image



=> Select the HMI project and then Server in the solution explorer

=>Now select the HMI Configuration as shown in the left image

=> If we press on the All Symbols then it will show all PLC variables under the MAIN PLC, if this does not show any variables then refresh the configuration

=> To map a variable, we right click on the PLC variable and select and select Map Symbol and press OK. Now this variable will be available in the HMI

=>We can map all the necessary variable one by one or selecting all by in single mapping.

=>Mapped Symbols will show all the mapped variables in the system


Server Symbols

Server symbols can be created centrally in the server under Mapped Symbols. They can also be used offline without a PLC. Clicking on the button Create Server Symbol opens a dialog for adding server symbols. Server symbols can be used to hold some internal variable for processing  business logic. This can be mapped to PLC variable as well. This variable can be persistent meaning if the server restarted the value is saved.

=> Right click on the Mapped Symbols

=> Select create new server symbol

=> Fill the necessary information as shown in the following image

Internal Symbols

Internal symbols are independent of the server and are valid within a browser instance. The internal symbols thus enable variables to be saved individually for each client.

=> Internal Symbol can be created as same way as server symbols

=> Right click on the internal symbol and fill the necessary information as shown in the following image

Test Application

The test application can be downloaded from and test it.

Here is short description what the test application does.

It reads a server internal variable and shows in a edit box, the value can be increased or decreased by pressing 2 buttons. The updated value can be written to a PLC variable. It shows also a text value by reading from a internal symbol

We shall add a video here and explain the project more details, so please visit us again

User Control, View, Region and Content

In TwinCAT HMI, user control is a control which is created by user.  A button that we find in the tool box is a control but it is system control provided by the HMI framework. User control is made by using multiple system controls.  We can make a composite control (by reusing system control as many as needed).  Then the composite control will be reused  as many time as needed. This is like a class in software engineering where we can make instance of it as many time as needed. Each instance can have different value for each class member. A User Control is an object type of its own.

A user control can be designed by following steps: We shall show the user control creation in the context of our home automation project.

In this example, the fictitious house automation has Lock (a device that can be used to lock the door), MainDoor (main gate to enter the yard) and water valve. All these devices have name and IsClosed boolean variables. These common properties will be displayed by the user control.


Final HMI

STEP 01:  Select the HMI project and new item

STEP 02:  Pick as many as needed basic control from the tool box and decorate your control.  In our example, we pick the name of the devices, an image and the status of the IsClosed variable. 

STEP 03: On the user control, press on ‘P’ and add all the needed parameters. We shall pass name (textblock), an icon (an image) , status (a text block) and a status image that indicates if the valve is open or closed.


STEP 04:  In the tool box, under HMI: User Control, we see our control. We drag and drop to the Desktop view 3 times and organize these. At this moment, if we run our example, we see an empty desktop view.

STEP 05: Select the first user control (instance of user control on the Desktop view) and press F4. This will bring the editor for providing parameters, remember we need to supply 4 parameters as our user control has 4 parameters.

STEP 06: Supply the needed parameters. First parameter is coming from the PLC program. 2nd parameter is the SVG image provided the project, this is just a device  symbol. 3rd parameter is Is_Closed variable that indicates if the valve/door is open or closed. Final parameters is also a path of a SVG image that will be shown when  the variable Is_Closed true or false. But the path is created by a Java Script function.



Download the project

We shall create a VIDEO CAST for this, please visit us again


An application can have many views. A user can jump from one view to another view and come back to previous view. All contents of the view is logically combined. By default, HMI engineering offers a default view, the name of the default view is “Desktop.view”. It is the landing page of any HMI system. We can load as many views possible depending on our need.

View can be used for HMI navigation purposes that we shall describe in next section.


We shall have 4 other views to our fictitious home automation system.

Desktop.view, default view, general info about the home automation system

Lockview.view, lock of the house info, status  and manipulation view

Thermometerview.view, it will display current temperature  and Hasoverheated alarm status

WaterValveview.view, shows the status if the valve is closed, is the solenoid valve open, valve opening/closing option

MainDoorview.view, it will display if the gate is closed, obstacle detected, allow user to insert opening time. This will give option to close/open the main gate.

Main view of the application: If we press on the icon, it will create a new view and that is displayed on the screen. We can come back to main view by pressing on the back arrow image.

The view are created by code behind file. We shall define a function for each icon in the code behind file as shown in the following code:

  // put this function block before the previous one otherwise it not work.
var destroyEvent = TcHmi.EventProvider.register(
function (evt, data) {
var v1 = TcHmi.View.get();
TcHmi.View.load(‘Desktop.view’, function (data) {
var v2 = TcHmi.View.get();
// Destroy to free event resources if event is no longer needed.
//But comment out if you need it

TIP 01: Button, Image Id in different view should have unique name

TIP 02: If we want to have back and forth in the navigation then we should keep stuff in the memory by not destroying the event (comment out  destroyEvent())

TIP 03: We might need to reorganize the JavaScript function location inside the file for reference

Down load the source code from the link below. We shall have a YouTube Video on this here, please visit us later.

Region and Content

The region is a container for content controls. The content to be displayed can be defined using the Target Content attribute.

HMI Navigation

The desktop view is the start page for any application on which we can create by using Visual Studio Wizard for visualization purposes. There are no hard rules how we design the user interface. Look and feel, usability are the different factors which define how the UI will be structured.
A good method of increasing the tidiness is to split the visualization into various parts. To do this, divide it into various content objects.
These content objects can be displayed in different areas of the desktop view. For example, the visualization could be divided into
three areas in the desktop view: a status bar, a content area and a navigation bar area. Various content objects can be displayed in the content area during the runtime.
The contents of the status bar area and the contents of the navigation bar area can also be changed as needed. We shall design the HMI for our fictitious home automation system. First page will show the logo and there will be navigation at the bottom. 



ADS and OPC UA Server

We shall continue adding the topics but here we publish a tip that may help to developer.  Default data acquisation interval between HMI and the ADS is 500 ms.  The scale mode is none. These can be changed as shown in the following diagram.

Open the properties of the HMI project and change the value.

Historize Data

 coming soon…


 coming soon…

User Management

 coming soon…

Alarms and Events

 coming soon…


Recipe types and recipes

A recipe type is a general description of a set of symbols, based on these we can create different type of recipes. These are comparable to class (recipe type) in object oriented programming from where we can make instances of class (recipes) with different attributes.

JavaScript, function and Code Behind

 coming soon…

Image rotation

 coming soon…

Filling tank with liquid

 coming soon…

Server Extension

Java script is used heavily in TwinCAT HMI development. What will happen if something can’t be implemented by java script or if we want to isolate our business logic in remote servers and there  it is not possible to implement by java script. TwinCAT HMI provides a way to implement the functionalities and use it as it has been a built in type.  Properties and methods can be configured when a button has been clicked for example. Framework provides the mechanism so that when the button in UI is pressed then a method from the extension is called.

The development of server extensions is done in C#. The development takes place in a separate project type within the Visual Studio. A corresponding project template is available for this purpose.

This extension is a DLL that implements an interface provided by the HMI framework.  HMI can call methods implemented by the custom extension module. So if we try to call method from a random DLL that will not be possible since the framework has no idea about the DLL.

Custom extension and TwinCAT architecture

Relation between TwinCAT HMI client and custom module

We shall show how to build the C# extension module (a C# DLL that will fit into the HMI framework.) The DLL can call methods from our fictitious home automation server over the internet. We shall add a  YouTube video  here later.

Steps for building extension in C#

The module we are developing will read data from our home automation OPC UA server. The OPC UA server that we have developed in other module will be used here. We shall call method from the server by using this extension module. We shall have normal edit box in the TwinCAT HMI to show status. We shall verify the status by using  UA Expert.

STEP 01: In Visual Studio, select,  TwinCAT HMI | Extensibility | TwinCAT HMI Server Extension (CSharp)

STEP 02: Select the HMI version if you have multiple version install and then press Create

At this point, we have created the project and in visual studio it will show something similar.

Now we should be able to build the project successfully.  Browse the generated code  and you can find OnRequest method we have switch case with mapping case “RandomValue”  and “MaxRandom”. We should be able to get these random value from extension to UI if we want. To make it a bit useful to our need, we need to change these or add some switch cases. Under config folder, we have xx.Config.json.  We can edit the symbols and $ref type  to fit our need. We edit the C# file as needed. 

STEP 03: If the project was compiled successfully, the extension can be loaded from the server. Open the context menu in the TwinCAT HMI project under Server/Extensions. Select the Server | Extension | Mouse right click | Manage Extension | Select the extension and press OK

STEP 04: Go to TwinCAT HMI Server Configuration and check if our extension is visible along with other built in extension.

STEP 05: We can map those variable so we can display these on the edit box for example.


We have modified the main source code in a way that status or Main Door and function status will be unknown by default. When the actual function call will be done then the real status will be updated. Here is the modified code.


                        // Use the mapping to check which command is requested

                        switch (mapping)


                            case “MainDoorStatus”:

                                ret = GetMainDoorStatus(command);



                            case “FunctionCallStatus”:

                                ret = FunctionCallStatus(command);




                                ret = ErrorValue.HMI_E_EXTENSION;





         // Retrive main door status from the OPC UA Server

        private ErrorValue GetMainDoorStatus(Command command)


            command.ReadValue = “Unknown”;


            //Call OPC method here

            command.ExtensionResult = ExtensionErrorValue.HMI_EXT_SUCCESS;

            return ErrorValue.HMI_SUCCESS;



        // Gets or sets the maximum random value.

        private ErrorValue FunctionCallStatus(Command command)


            if (command.WriteValue.IsSet && command.WriteValue.Type == TcHmiSrv.ValueType.ValueType_String)


                //Make OPC call here



            command.ReadValue = “Unknown”;


            command.ExtensionResult = ExtensionErrorValue.HMI_EXT_SUCCESS;

            return ErrorValue.HMI_SUCCESS;


Following the final version of the HMI. User can press Open/Close door and the status of the call will be displayed. If the door status is changed then it will be updated in the door status edit box.

We need to establish the bridge between extension dll to opc call (that is missing). We shall make a YouTube video and publish here, so please do visit us again.


When we are creating the module (DLL by the wizards provided by Beckhoff) we have seen it creates RandomValue  and MaxRandom. If we search by visual studio then replace all found items but in next time if you build the whole project then it will appear again. The JSON file is auto created by taking the data from HMI configuration (mapped symbol). If you un mapped the  symbol the it will be removed from the JSON file.

How to publish to HMI Server

When we are satisfied with our development then we need to publish the SCADA /HMI to a remote server so our operator can access it and use it. We need to install HMI Server (not HMI Engineering to the machine). Click on the image below to see how to publish HMI to serves.