TwinCAT HMI Symbol Data and Binding
(Video tutorial at the end)

In TwinCAT HMI a variable is called a symbol, in another system, it may be called a tag as well. This symbol can be mapped or linked to the PLC variable. Some symbols can be local to the HMI server. That means it is not read from PLC. HMI server’s responsibility to keep up to date all the symbols that have been mapped.

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

Download the complete working source code Symbol_Data_Hemelix.zip

A binding links any symbol to a property of a control. A binding automatically updates the property of the control when the value of the symbol changes. There are two types of binding:

=>Data binding, also called variable binding, a variable is linked to any property of control then we say variable is bound to the property (see the image below). If we don’t use any variable then we can’t bound it. See the images below.

=>Function binding, basically it means we can use a function for the control property. Note that when we use function binding then fx is highlighted. A function binding can be created for all control properties if the JavaScript functions return a suitable value for the property of the control.

 

See the following screenshot to understand the difference between data binding and function binding. We are passing MotorName as function binding (note the highlighted fx). The field returns a javascript object ‘Motor One’ (note the Apostrophe), without the Apostrophe data will not be passed, and the control will not display it.

MotorStartTime will be displayed as it is written as ‘3’

MotorRotationMinute will not be displayed as it is not variable binding nor function binding

MotorStopTime will not be displayed as it expects variable for real but we are passing a text.

Tip:

When we add a function by copy-paste then sometimes it shows 404. One solution is  expanding the field and it will be OK,

Also, a good idea to check with the console.log  method. This causes unwanted text to be inserted (newline or CR or similar)  and  it does not work.

Anatomy of binding:

 

TcHmi.Binding.createEx =>Creates a binding between a symbol and a control attribute using the attribute setter function, takes 3 parameters

Symbol expression (for example, HMI internal variable,  ‘%i%MyInternalSymbol_1%/i%’,  Server variable  ‘%s%PLC1.MAIN.varIntPlcVariable%/s%’, parameter variable %pp%someRealParameter%/pp%)

Name of the control setter function (for example, setText, setLeft  etc setter function for control properties)

Reference to the control instance (  for example,  var myControl = TcHmi.Controls.get(‘TcHmiTextbox_1’);)       

var myControl = TcHmi.Controls.get('TcHmiTextbox_1');
if(myControl){
}
TcHmi.Binding.createEx('%i%MyInternalSymbol_1%/i%', 'setText', myControl);

CreateEx does not return anything if we want to sure may be a good idea to check by the following way:

var result = TcHmi.Binding.exists('Text',TcHmiTextbox_1);
if(result){
console.log('Binding does exists');
} else {
console.log('Binding does not exists');
}

TcHmi.Binding.exists => Test if there is existing binding between control property and control. The binding can be established by the createEx function by program or by using the graphical tools. exists takes 2 parameters. If either has not been done then it will return false.

propertyName:  Name of the property, for example, Text, Left, Top, etc. These properties can be set.

Control: (reference to a control,   for example,  var myControl = TcHmi.Controls.get(‘TcHmiTextbox_1’);)

 

TcHmi.Binding.resolveEx => Returns a symbol expression (for example ‘%i%MyInternalSymbol_1%/i%’,  ‘%s%PLC1.MAIN.varIntPlcVariable%/s%’  etc) if a binding exists between a symbol and the control attribute or null if no binding exists.  This function takes 2 parameters:

propertyName:  Name of the property, for example, Text, Left, Top etc. These properties can be set.

Control: (reference to a control,   for example,  var myControl = TcHmi.Controls.get(‘TcHmiTextbox_1’);)

var myControl = TcHmi.Controls.get('TcHmiTextbox_1');
if(myControl){
    var result = TcHmi.Binding.exists('Text',myControl);
    if(result){
         console.log("Binding exists");
    } else {
         console.log("Binding does not exist");
    }
    var symbolExpression = TcHmi.Binding.resolveEx('Text',myControl);
    if(symbolExpression){
         console.log(myControl.getId() + '::Text is bound to symbol expression: ' + symbolExpression.toString());
    } else {
console.log(myControl.getId() + '::Text is bound to symbol expression: ' + symbolExpression.toString());
    }
}

 


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 a route for searching Beckhoff PLC.

=> If the PLC is running on the local PC, we add the localhost address “127.0.0.1.” + “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 establishes 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 ADS protocol.

 

 

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

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

 

1 => Shows all the variables in the PLC Main

2 =>Mapped Symbol (the variables which have been mapped)

3 => Internal symbol to the HMI server

4 => Localization of this application (see more).

5 => Built-in function provided by TwinCAT framework.

 

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

=>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 hemelix.com and test.

Here is a short description of what the test application does.

1=> An internal symbol is displayed here (the internal symbol has been bounded manually),

2=>If we press on this button the internal symbol will increase by one,

3=>Internal symbol will decrease by one,

4=>If we press on this button it will read the value of edit box 5 and set it to PLC, this button’s left property is bound with the internal symbol, so if we increase or decrease the internal symbol, this button will move left or right.

5=>Display the current value of the PLC variable if there is binding. If there is no binding then it will be empty

6=>If we press on this button the PLC variable (we have a single variable) will be bound to the edit box at 5

7=>If we press on this button the PLC variable (we have a single variable) will be unbounded to the edit box at 5 and it will display nothing (because it is not bound to anywhere)

8=>Display the binding status if we press on 6 or 7 or even during the initialization of the program.

We embedded JavaScript code for binding and unbinding. For test purpose we have embedded JavaScript for editbox (5). The code can be found in the downloaded zip file.

var myControlInt = TcHmi.Controls.get('TcHmi_Controls_Beckhoff_TcHmiTextbox_IntPLCVariable');
if(myControlInt){     var result = TcHmi.Binding.exists('Text',myControlInt);     if(result){          console.log("Binding exists with IntPLCVariable");     } else {          console.log("Binding does not exist with IntPLCVariable");     } }
if(myControlInt){     var symbolExpression = TcHmi.Binding.resolveEx('Text',myControlInt);     if(symbolExpression){                   console.log(myControlInt.getId() + '::Text is bound to symbol expression: ' + symbolExpression.toString());     } else {          console.log("Binding does not exist with IntPLCVariable, symbol expression is null");     } } 

We have embedded the following code for button number 6 (to make the binding), for unbinding, we have a little bit of different code that can be check by copying the code.

 

var myEditBoxControl = TcHmi.Controls.get('TcHmi_Controls_Beckhoff_TcHmiTextbox_IntPLCVariable');
var myMsgBoxControl = TcHmi.Controls.get('TcHmi_Controls_Beckhoff_TcHmiTextblock_Message');
if (myEditBoxControl && myMsgBoxControl) {
    TcHmi.Binding.createEx('%s%PLC1.MAIN.varIntPlcVariable%/s%', 'SetText', myEditBoxControl);
    var result = TcHmi.Binding.exists('Text',myEditBoxControl);
    if(result){
        myMsgBoxControl.setText('Binding Done');
    } else {
        myMsgBoxControl.setText('Binding not Done');
    }
}

Tips 01: Why my HMI does not updated with initial value set in the server or in server extension?

Data need to changed if we want to display data on the UI. One way to configure the UI with custom events as shown in the following image.

Tips 02: I see warning symbols besides my mapped variables, why it is shown in the following image.

The reason for this you have a running runtime with previous variables mapped (from other PLC programs).

Sol: just unmap these variables (if those variables are not needed in the current program) or check if the PLC is in run mode.

 

Tips 03: If all variables are marked with the symbol then your route has been lost, if you add the target PLC in TwinCAT route then it will be fine again.

Tips 04: We can see this type of error sometimes in the console.

TcHmiFramework.js:744 [2021-11-08T07:50:48.925Z][Error] [Source=Framework, Module=TcHmi.System.TriggerManager, Event=%i%System_Mode%/i%, ObjectType=WriteToSymbol] Code: 3005/0xbbd, Message: E_SERVER_COMMAND_ERROR

  Reason: %s%PLC1.SystemMode%/s%: Error in command for symbol: ‘PLC1.SystemMode’ in response from server with id: ‘9’.

  Domain: TcHmi.System.Symbol

  as result of: Code: 7/0x7, Message: ADS_API_RETURN_CODE

    Reason: Sum ADS write request of size 13 containing 1 requests failed.

 

    Domain: ADS

Solution: At least, if our route has been deleted for some reason then we can see this type of message.

Tips 05:

When we add a function by copy-paste then sometimes it shows 404. One solution is  expanding the field and it will be OK,

Also, a good idea to check with the console.log  method. This causes unwanted text to be inserted (newline or CR or similar, not exactly known to me, if you know you can post to our Google group)  and  it does not work.

 

Download the sample from the link given above.

Next, let’s try to understand user control at https://www.hemelix.com/scada-hmi/twincat-hmi/twincat-hmi-user-control/

Ask questions related to Hemelix sample code and design at Google group https://groups.google.com/g/hemelix