
TwinCAT Software Testing
What is Software Testing
Software testing is the process of checking the quality, functionality, and performance of a software product before deployment to the actual devices. We shall focus on this article while we develop our software when the actual hardware is not available yet. There are many different kinds of testing in software engineering.
In most cases, the PLC software reads, processes, and update the output variables for controlling the devices. The PLC program does some output and then the automation system signals (by input sensors) that it has done the desired work. PLC monitors the input variables for a certain time, if the desired input is not set within that time, PLC signals with an alarm for that device.
As we see in the following diagram, our program continuously reads the inputs and decides what to do, if the program instructs to do an output then it does. The output normally activates the actuators. It can be solenoid valves, it can be a motor contactor. Actuators are devices that perform actions, such as opening valves, moving robots’ arms, or switching lights, based on signals from PLCs.

Figure 01: Typical PLC cycle
We can also test the PLC program by creating another task in the PLC program, where we can signal the input to the desired level. Here we are doing similarly but using HMI Software. The test cases can be flexible and visually observable.
Knife Gate Valve (Case Study)
In this tutorial, we shall use a simple knife gate valve. We assume that this one is a pneumatic valve. The valve is opened when a solenoid is active (the output is ON). When the solenoid is ON then compressed air pushes the valve’s blade to the upper direction and the blade goes up. There are two proximity sensors for the valve. When the valve is fully open, the blade is in the upper position, and both proximity sensors are ON. If the lower one is ON and the upper one is OFF then the valve is half open. When the solenoid is OFF then the valve’s spring force pushes the blade to close the valve. When the valve is closed then both proximity sensors are OFF.
The valve is shown in the following diagram.

Figure 02: Pneumatic valve, 2 proximity sensors, and a solenoid valve (not shown here)
In the following code snippet, we command the valve to be opened by an action where we put the solenoidOutput variable ON (TRUE)
VAR
(* input *)
upperProximitySensor AT%I*: BOOL;
(* input *)
lowerProximitySensor AT%I*: BOOL;
(* output *)
solenoidOutput AT %Q* : BOOL;
(* analog *)
pressureRawValue AT%I*: DINT;
(* analog *)
temperatureRawValue AT%I*: DINT;
(* analog *)
terminalState AT %I* : WORD;
END_VAR
Note from the above code that few variables are commented as input, output and analog. By this way, we scan the variables and identify which variables are related to hardware device. For example, when the solenoidOutput is active (ON) then the valve should be in open state and the two proximity sensor should be active (ON) in ideal case. When the solenoid if inactive then the valve should be in closed position and the two proximity sensors should be inactive (OFF)

Figure 03: Pneumatic valve closed, partially closed, and fully open (right side of the image) and status of proximity sensors
We shall develop our test system without any physical valves, when our SW is tested then we just activate our program to the PLC then we are done! Following diagram shows possible commands and related results, we can develop similar cases based on our devices and process.

Figure 04: Valve Open and Close command and the possible results of the command
Different devices will have different inputs, outputs and command. These are just an example.
Possible Hardware Setup
We don’t have the hardware yet but we can configure the possible setup in Visual Studio. An embedded PC has a coupler connected to an ethernet port. Two cards EL2008 (Output card) and EL1808 (Input card) are connected to the coupler. The variable solenoid output is linked to 1st channel. The variables upperProximitySensor and lowerProximitySensor are linked to the 1st and 2nd channels of card EL1808. This is drawn as in the following image.

Figure 05: Hardware setup for controlling the valve (simplified version, electrical safety stuff omitted).
With this setup, we activate our tested program, which should start working when the hardware is available. Since we don’t have the hardware yet we shall try to complete the test using our test tool ADSTestDriver.
Valve control Code in ST
In this section, we shall focus on the implementation of valve control in the structured text programming language.
Please download the source code from the download section. This is basically a valve function block that can be used to control the actual device. We have 3 other variables which are not related to the valve itself, those are terminalState of type WORD, pressureRawValue of type DINT, and temperatureRawValue of type DINT. We shall show how we can generate pressure or temperature data while we don’t have actual hardware. The terminal state is another important variable that indicates the communication status with hardware. We can set that status by using our test software.
How the test system works
In the current version of the test software, we connect to the PLC program and load a test case. The test case is generated by using or configuring an output. Basically we define what kind of input or process values we expect when an output goes active. Then we can observe the PLC program and fix the found issues. The following figure explains the configuration process for each variable in the system when we are testing a generic function block.

Figure 06: Test configurations, this can be used to test any PLC program with ST
Test configurations
Here we describe the functions of each button, check boxes, list boxes, etc.
1 => AMS NetID of the PLC where the PLC program is running
2 => PLC name
3 => Port number of the PLC program
4 => Button for connecting to the PLC (it will read only those variables that have comments as mentioned in 20, 32, and 48)
5 => Connection status to the PLC (Checked when connected and unchecked when not connected). Uncheck can disconnect from the PLC
6 => Current test case name
7 => Relation of variables in the current test case
8 => Test case file name where the test cases can be saved
9 => Update intermediate test cases, we configure 1 output at a time and press the update test case button before pressing “Save Test Cases”. Every time we configure 1 output and press the Update Test Cases button
10 => When we have configured all outputs then we save to the file name mentioned in step 8 (“Valve Test”). When we have saved the test case that file name will be visible in the list of 12
11 => Delete the current test case file from the list
12 => List of all test case files we have configured (we can have valve test all OK, input sensors malfunctioning, etc). If we select a file that will be visible in Tree View 7
13 => We need to tell the system that we are starting a new test case, if we don’t select this option, we can’t save data.
14 => Output variable (tag name), when we select another variable its property will be visible in the fields 15, 16, 17
15 => If this is checked then the system will change the configured input or analog variables
16 => Comment related to this output if needed
17 => If checked this output will be ignored
18 => If we change any properties (in 15, 16, and 17) that will be updated for the current output
19 => Update the list (21) by reading the variables from the system
20 => When we connect to PLC, this text is used to filter variables. If the system finds an output comment in any variable that will be added to the list 21, for example
(* output *)
solenoidOutput AT %Q* : BOOL;
21 => Variable names found in the system which has a comment that matches in the field 20
22 => We need to check so this variable will be configured. Only 1 output can be configured at a time.
23 => Currently selected input which we are going to configure
24 => If checked the input will be ON (after the delay in 25)
25 => Delay in seconds (the input will be changed as configured in 24). Delay can’t be -ve
26 => Ignore the case, no action will be taken if checked
27 => If we set Error active then we can configure the input Always ON or Always OFF
28 => If checked then the input will be ON all the time (27 and 28 should be selected)
29 => If checked then the input will be OFF all the time (27 and 29 should be selected)
30 => If we press this button then currently selected properties will be updated for the selected tag
31 => Refresh the input list which is found in the system based on the comment in field 32
32 => When we press on the connect then it will read the text and produce a list (in list 33) as shown below
(* input *)
upperProximitySensor AT%I*: BOOL;
33 => Display a list of variables which has a comment as found in field 32
34 => If selected this variable will be added to the list when we press “Update Test Cases” 9
35 => Currently selected variable from the list 49
36 => Max value for the analog variable
37 => Min value for the analog variable
38 => If selected, then the system will write to output variable average of min and max
39 => If selected, then the system will write to output variable from min value to max value during the time in 41
40 => If selected, then the system will write to output variable from min value to max and then back to min value during the time in 41
41 => The system will use this time to update the analog variable. The time is in seconds
42 => Delay in seconds (data will be written to the variable after the delay)
43 => If checked the case will be ignored (no data will be written)
44 => If checked, then we can simulate the error case
45 => If checked, then it will write the min value (44 and 45 must be checked)
46 => If checked, then it will write random data between min and max values (44 and 46 must be checked)
47 => The configured output will be updated internally
48 => This value will be used to find the variables from the program. In the PLC, the code is written like the following.
(* analog *)
terminalState AT %I* : WORD;
49 => Variables found which has a comment as mentioned in the field 48
50 => If checked this variable will be used for the test system
Steps for creating test case
Step 01: Configure all the needed outputs, inputs, and analog variables
=> Selecta variable, configure its properties and update
=> One output should be configured for many inputs and analog variables
Step 02: Select Start New TestCase, and select the output, input(s), and analog data(s)
Step 03: Update TestCases
Step 04: Select new output variables
=> If we want to reuse any input or analog variables that were used previously, we have to change their properties (if needed)
=> Select all the needed analog/input variables
=> Press Update Test Cases
Step 04: Finally give a name and press Save Test cases
Testing the valve

Figure 07: Testing the valve
When we are testing our software, we must select a test case file (from the configuration page) and the test sw should be connected to the PLC.
Testing Result
As we see the terminal state is 8, the output solenoid is ON (top circle), and 2 sensors are active. Also, pressure and temperature have some value as specified. This is done and tested in the ideal case. If we press open, the valve will be opened and when we press the valve will be closed. All are fine.
But now, let’s assume after a few days one of the sensors will be broken. When we run the same test the result will be like the following.

Figure 08: Testing the valve, one sensor is broken (configure a limit switch as OFF)
At this point, your user (operator) fixed the broken sensor and he wants to recover it himself. if he presses Open, Close nothing will help. The only way to make it working restarting the PLC. So the big question is, could we have done the test already beforehand so we could have better software? Yes, we have a solution for that. There are many ways to handle the case. The following is one of the ways to handle it. We introduce a reset button and change the PLC code to handle it so that if such a situation occurs then the operator can manage it without restarting the PLC or calling the developer.

Figure 09: Testing the valve, reset button and it’s functionality has been introduced in the PLC
The following code snippet has been introduced in the PLC. Note there are many different ways to handle the case, but this is one of those. You can download both versions from the download section.
IF state > VALVE_INIT THEN
IF valveResetCommand= TRUE THEN
valveResetCommand := FALSE;
valveOpenCommand := FALSE;
state :=VALVE_CLOSED;
solenoidOutput := FALSE;
valveCloseCommand:= FALSE;
upperProximitySensor := FALSE;
lowerProximitySensor := FALSE;
stateInit := FALSE;
pressureRawValue := 0;
temperatureRawValue := 0;
terminalState := 0;
pressureRealValue := 0.0;
temperatureRealValue := 0.0;
END_IF
IF state= VALVE_CLOSED AND valveOpenCommand= TRUE THEN
state :=VALVE_OPENING;
valveOpenCommand:= FALSE;
solenoidOutput := TRUE;
stateInit := FALSE;
END_IF
IF state= VALVE_OPENED AND valveCloseCommand= TRUE THEN
state :=VALVE_CLOSING;
solenoidOutput := FALSE;
valveCloseCommand:= FALSE;
stateInit := FALSE;
END_IF
END_IF
Architecture of the Test System
In the following figure, we can see the architecture of the test system. The system use the ADS library provided by Beckhoff.

Figure 10: Architecture of the test system
ADSTestDriver is a DLL that we wrap with the extension module. Since the source code is unavailable to you if you find any issue please get in touch with us and we shall update it and deliver it to you for free.
YouTube Video
Coming soon…
Download Source Code
The code contains the server extension DLL and ADSTestDriver.dll. You need to activate the ServerExtension.dll in the Visual Studio project.
The download link for the first version is ValvePLCProject_V01.zip
The download link for the second version (fixed with reset) is ValvePLCProject_V02.zip
Feel free to discuss the test system in our Google group https://groups.google.com/g/hemelix
After unzipping the project you get the following files in the folder ValvePLCProject\ServerExtension\bin\Debug

Figure 11: List of binaries provided in the zip files
To run the project directly please follow the following steps:
=> Load the solution in visual studio ValvePLCProject.sln and build the solution
=> First run the PLC program (local or on the remote PLC)
=> Right-click on the ServerExtension (under HMI Configuration Project) and activate the extension
=> Open Desktop.view and load in live view, press on “Configure Test Cases”
=> Press on the connect button, if all are fine we should get the connected check box checked
=> If we press on refresh list, we get the list of filtered variables
=> Now we can configure each output and define what the input variables and analog variables should do
Known Issues
=> Once we have created test cases (configured properties) then we can’t load the test case file and edit it (we need to recreate it again, we shall fix it in the next version)
=> ADSTestDriver, the binary is available in the downloadable project, if you need source code you can contact us!
New approaches!
We got some good feedback, and based on that feedback, we are taking completely new approaches. Here is the GUI