Merge branch 'master' into mbp-100-read-write-axis-parameters

This commit is contained in:
[Luke Nisbet]
2020-03-06 13:39:40 +00:00
15 changed files with 581 additions and 2147 deletions

2
.gitignore vendored
View File

@@ -17,3 +17,5 @@ logs.0*
solution/TrialLicense.tclrs
tools/linux/ADS/
tools/linux/getADSState/getADSState.bin
_Config/NC/Axes
_Config/IO

3
.gitmodules vendored
View File

@@ -1,6 +1,3 @@
[submodule "solution/tc_epicscommodule"]
path = solution/tc_epicscommodule
url = https://bitbucket.org/europeanspallationsource/tc_epicscommodule.git
[submodule "solution/tc_project_app/tc_mca_std_lib"]
path = solution/tc_project_app/tc_mca_std_lib
url = https://bitbucket.org/europeanspallationsource/tc_mca_std_lib.git

View File

@@ -1,11 +1,10 @@
image: python:3.7.3
options:
max-time: 1
pipelines:
default:
- step:
script:
- git submodule update --init
- git submodule
- python twincat_version_manager.py
- python check_fix_white_space.py
image: python:3.7.3
options:
max-time: 1
pipelines:
default:
- step:
script:
- git submodule update --init
- python twincat_version_manager.py
- python check_fix_white_space.py

View File

@@ -26,6 +26,8 @@ def fix_white_space(debug, fix_files):
for pathname in found_files:
dirty = False
had_TAB = False
had_trailing_WS = False
new_lines = []
if debug >= 1:
print("tab_with=%d pathname=%s" % (tab_width, pathname))
@@ -41,8 +43,16 @@ def fix_white_space(debug, fix_files):
had_crlf = 1 # LF
# Convert all TAB into SPACE
new_line = old_line.expandtabs(tabsize=tab_width)
# Strip of all trailing white space, including the CRLF
new_line = new_line.rstrip("\r\n ")
if new_line != old_line:
had_TAB = True
# Strip the CRLF
new_line = new_line.rstrip("\r\n")
# Strip trailing WS
tmp_line = new_line.rstrip(" ")
if tmp_line != new_line:
had_trailing_WS = True
new_line = tmp_line
if had_crlf == 2:
new_line = new_line + '\r\n'
elif had_crlf == 1:
@@ -61,7 +71,12 @@ def fix_white_space(debug, fix_files):
if debug >= 1:
print("pathname=%s dirty=%d" % (pathname, dirty))
if dirty:
incorrect_files[pathname] = True
if had_TAB and had_trailing_WS:
incorrect_files[pathname] = 'has white space damage'
elif had_TAB:
incorrect_files[pathname] = 'has TAB'
elif had_trailing_WS:
incorrect_files[pathname] = 'has trailing whitespace'
if fix_files:
file = open(pathname, 'w', newline='', encoding="iso-8859-1")
file.writelines(new_lines)
@@ -88,8 +103,10 @@ if __name__ == "__main__":
incorrect_files = fix_white_space(debug, fix_files)
if not fix_files:
for file in incorrect_files:
print("ERROR: '{}' has white space damage".format(file))
message = incorrect_files[file]
print("ERROR: '{}' {}".format(file,message))
if incorrect_files:
print('run %s --fix' % sys.argv[0])
exit(1)
except IOError as e:
print(e) # Likely no files found

View File

@@ -0,0 +1,20 @@
<?xml version="1.0"?>
<TcSmItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.beckhoff.com/schemas/2012/07/TcSmProject" TcSmVersion="1.0" TcVersion="3.1.4023.119" ClassName="CNcSafTaskDef" SubType="0">
<NC>
<SafTask Priority="4" CycleTime="20000" AmsPort="501" IoAtBegin="true">
<Name>NC-Task 1 SAF</Name>
<Vars VarGrpType="1" InsertType="1">
<Name>Inputs</Name>
</Vars>
<Vars VarGrpType="2" InsertType="1">
<Name>Outputs</Name>
</Vars>
<Image Id="1" AddrType="1" ImageType="1">
<Name>Image</Name>
</Image>
</SafTask>
<SvbTask Priority="8" CycleTime="100000" AmsPort="511">
<Name>NC-Task 1 SVB</Name>
</SvbTask>
</NC>
</TcSmItem>

File diff suppressed because it is too large Load Diff

View File

@@ -7,8 +7,7 @@ VAR_GLOBAL
END_VAR
VAR_GLOBAL CONSTANT
axisNum : UINT:=2;
//axisCoupleMax : UINT:=4;
axisNum : UINT:=0;
END_VAR]]></Declaration>
</GVL>
</TcPlcObject>

View File

@@ -6,6 +6,7 @@ VAR
sVersion: STRING:='1.0.0';
i : UINT; //index variable for AXES()
aFbAxes: ARRAY [1..gvl_app.axisNum] OF FB_Axis;
hmiAxisSelection : INT:=1; //Not possible to use local hmi variables for array indexes
(******Outputs: Power for Limit switches and Home Sensors (every 4th output)********)
@@ -25,19 +26,6 @@ VAR
//bOutput24 AT %Q*: BOOL:= TRUE;
//bOutput28 AT %Q*: BOOL:= TRUE;
(******Error Handling********)
fbErrorSystem: FB_ErrorSystem;
aFbAxesError: ARRAY [1..gvl_app.axisNum] OF FB_NC_Error;
//fbEL1018 : EL1018;
//fbEL2808 : EL2808;
//fbEL5101 : EL5101;
//fbEL9505 : EL9505;
//fbEL1252 : EL1252;
//fbEL9410 : EL9410;
//fbEL7037 : EL7037;
//fbEK1110 : EK1110;
(******Startup, Shutdown and UPS********)
fbUPS : FB_S_UPS_CX51x0;
eUpsMode : E_S_UPS_Mode := eSUPS_WrPersistData_Shutdown;
@@ -48,6 +36,7 @@ VAR
iRetry : INT;
fbReadEncRefSys : ARRAY [1..gvl_app.axisNum] OF MC_ReadParameter;
fbRestorePosition : ARRAY [1..GVL_app.axisNum] OF MC_SetPosition;
fbGetDeviceIdentification : FB_GetDeviceIdentification;
END_VAR
@@ -55,25 +44,11 @@ VAR PERSISTENT
bRestoreOnStartup : BOOL;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[(*fbUPS(eUpsMode := eUpsMode); (* call UPS-FB instance in first lines of the fastest PLC Task *)
IF eGlobalSUpsState = eSUPS_PowerFailure THEN
(* first cycle of powerfailure *)
(* execute code that should only be done once with each powerfailure, i.e. increase powerfailure counter *)
bRestoreOnStartup:=TRUE;
STORE_PERSISTENT();
RETURN;
ELSIF eGlobalSUpsState > eSUPS_PowerFailure THEN
(* next cycles of powerfailure *)
(* skip regular code execution for the remaining cycles of the powerfailure/writing of persistent data/quick shutdown ... *)
RETURN;
END_IF*)
RESTORE_POSITIONS();
<ST><![CDATA[POSITION_RECOVERY();
PROG();
AXES();
ERROR();]]></ST>
AXES();]]></ST>
</Implementation>
<Folder Name="POSITION_RECOVERY" Id="{3561f6ef-e145-4ed3-9839-f17334bd2d97}" />
<Action Name="AXES" Id="{7eb32732-9b53-4934-8cd9-20ba971dd8ff}">
<Implementation>
<ST><![CDATA[FOR GVL.iAxis:=1 TO gvl_app.axisNum DO
@@ -81,55 +56,40 @@ ERROR();]]></ST>
END_FOR]]></ST>
</Implementation>
</Action>
<Action Name="ERROR" Id="{35f2cf38-f81e-4aa3-9534-be5fb417817d}">
<Action Name="CHECK_UPS" Id="{f0f28f50-53b8-4f73-b0f5-6d7ce4c1636f}" FolderPath="POSITION_RECOVERY\">
<Implementation>
<ST><![CDATA[//
(****FB containting the log of the errors****)
//
fbErrorSystem(
En:= TRUE,
bReset:= ,
nErrorNum:= ,
bACK:= ,
bValidSelection:= ,
nTableRowIndex:= ,
EnO=> ,
nSelectedError=> ,
pErrorSystem=> );
<ST><![CDATA[fbUPS(eUpsMode := eUpsMode); (* call UPS-FB instance in first lines of the fastest PLC Task *)
FOR GVL.iAxis:=1 TO gvl_app.axisNum DO
aFbAxesError[gvl.iAxis](EN:=TRUE,
nNC_ErrorID:= gvl.axes[gvl.iAxis].status.nErrorID,
nNC_AxisID:=gvl.axes[gvl.iAxis].Axis.NcToPlc.AxisId,
ErrorSystem:= fbErrorSystem.pErrorSystem);
END_FOR
(*call all the necessary instance (input assistance F2 or right click) according to the terminals that you have in your hardware and
add "TRUE" in the input En, the corresponding number of termianl to the iTerminal_ID and
the variable "fbErrorSystem.pErrorSystem" to the input ErrorSystem in each FB E. g. :
fbEL1808(
En:= TRUE,
iTerminal_ID:= 01,
ErrorSystem:= fbErorSystem.pErrorSystem,
EnO=> ,
bError=> );
*)
]]></ST>
IF eGlobalSUpsState = eSUPS_PowerFailure THEN
(* first cycle of powerfailure *)
(* execute code that should only be done once with each powerfailure, i.e. increase powerfailure counter *)
bRestoreOnStartup:=TRUE;
STORE_PERSISTENT();
RETURN;
ELSIF eGlobalSUpsState <> eSUPS_PowerOK THEN
(* next cycles of powerfailure *)
(* skip regular code execution for the remaining cycles of the powerfailure/writing of persistent data/quick shutdown ... *)
RETURN;
END_IF]]></ST>
</Implementation>
</Action>
<Action Name="POSITION_RECOVERY" Id="{28e203b7-aea5-42d0-980d-12a6841f9d22}" FolderPath="POSITION_RECOVERY\">
<Implementation>
<ST><![CDATA[fbGetDeviceIdentification(bExecute:=TRUE);
IF (fbGetDeviceIdentification.stDevIdent.strHardwareSerialNo <> '0') THEN
CHECK_UPS();
RESTORE_POSITIONS();
END_IF]]></ST>
</Implementation>
</Action>
<Action Name="PROG" Id="{5d03ebbb-2a47-4890-ad6d-e82daf72dc51}">
<Implementation>
<ST><![CDATA[//
(* Program any sequence, safety or feature (if necessary) application specific in thsi section*)
//]]></ST>
</Implementation>
</Action>
<Action Name="RESTORE_POSITIONS" Id="{0c7ee537-7bd9-4833-b428-c17cbb57e893}">
<Action Name="RESTORE_POSITIONS" Id="{0c7ee537-7bd9-4833-b428-c17cbb57e893}" FolderPath="POSITION_RECOVERY\">
<Implementation>
<ST><![CDATA[///#########################################################
// This ACT will restore the position of an incremental axis on startup with the act position it read before losing power.
@@ -144,7 +104,7 @@ fbEL1808(
// Note from Beckhoff: "A maximum of 1 MB persistent data can be reliably saved over the entire service life."
///#########################################################
IF bRestoreOnStartup THEN
IF bRestoreOnStartup AND eGlobalSUpsState = eSUPS_PowerOK THEN
bRestoreOnStartup:=FALSE;
bRestoreExecute:=TRUE;
END_IF
@@ -176,14 +136,14 @@ IF bRestoreExecute AND NOT bPositionRestoreDone THEN
ColdStart:
// First cycle of the PLC, do nothing just give one cycle for variables to initialise
IF NOT bPositionRestoreDone THEN
eStartUp:=eStartUp+1;
eStartUp:= ReadAxisFeedbackType;
iRetry:=0;
END_IF
ReadAxisFeedbackType:
// Exectute the function blocks to read the encoder reference system (0=inc OR 1=ABS)
bExecuteReadEncRefSys:=TRUE;
eStartUp:=eStartUp+1;
eStartUp:=CheckReadDone;
CheckReadDone:
// Check the encoder reference system has been read for all axis -> if busy then continue with PLC cycle and check again next time.
@@ -199,14 +159,14 @@ IF bRestoreExecute AND NOT bPositionRestoreDone THEN
// .valid=FALSE and .busy=FALSE which indicateds the FB probably hasn't started and thus needs to see a rising edge.
// Set execute to low, Exit MAIN.STARTUP and go back a step in the CASE statement.
bExecuteReadEncRefSys:=FALSE;
eStartUp:=eStartUp-1;
eStartUp:=ReadAxisFeedbackType;
iRetry:=iRetry+1; // counter used for troubleshooting to see how many cycles it takes before fbReadEncRefSys function blocks are read correctly
RETURN;
END_IF
END_IF
END_FOR
// If the code gets here all axes either have .valid=TRUE for all axes
eStartUp:=eStartUp+1;
eStartUp:= ExecuteRestore;
ExecuteRestore:
// Execute position restore by setting fbRestorePosition.execute = TRUE
@@ -217,7 +177,7 @@ IF bRestoreExecute AND NOT bPositionRestoreDone THEN
END_IF
END_IF
END_FOR
eStartUp:=eStartUp+1;
eStartUp:= CheckRestore;
CheckRestore:
// Check the set position fbs are finished
@@ -232,7 +192,7 @@ IF bRestoreExecute AND NOT bPositionRestoreDone THEN
END_IF
END_IF
END_FOR
eStartUp:=eStartUp+1;
eStartUp:= FinishRestore;
FinishRestore:
// Remove execute = TRUE for fbRestorePosition
@@ -245,7 +205,7 @@ IF bRestoreExecute AND NOT bPositionRestoreDone THEN
END_IF]]></ST>
</Implementation>
</Action>
<Action Name="STORE_PERSISTENT" Id="{cb5c9254-2e5f-47b1-9baa-10e728a961b0}">
<Action Name="STORE_PERSISTENT" Id="{cb5c9254-2e5f-47b1-9baa-10e728a961b0}" FolderPath="POSITION_RECOVERY\">
<Implementation>
<ST><![CDATA[FOR i:=1 TO gvl_app.axisNum DO
axesPersistent[i].iPositionAtShutdown:=gvl.axes[i].Axis.NcToPlc.ActPos;
@@ -259,38 +219,26 @@ END_FOR]]></ST>
</Implementation>
</Action>
<LineIds Name="MAIN">
<LineId Id="376" Count="11" />
<LineId Id="2" Count="0" />
<LineId Id="189" Count="0" />
<LineId Id="135" Count="0" />
<LineId Id="505" Count="0" />
<LineId Id="134" Count="0" />
<LineId Id="81" Count="1" />
<LineId Id="81" Count="0" />
</LineIds>
<LineIds Name="MAIN.AXES">
<LineId Id="1" Count="0" />
<LineId Id="4" Count="0" />
<LineId Id="10" Count="0" />
</LineIds>
<LineIds Name="MAIN.ERROR">
<LineId Id="31" Count="0" />
<LineId Id="10" Count="1" />
<LineId Id="34" Count="8" />
<LineIds Name="MAIN.CHECK_UPS">
<LineId Id="2" Count="11" />
<LineId Id="1" Count="0" />
</LineIds>
<LineIds Name="MAIN.POSITION_RECOVERY">
<LineId Id="2" Count="3" />
<LineId Id="1" Count="0" />
<LineId Id="90" Count="1" />
<LineId Id="88" Count="1" />
<LineId Id="92" Count="2" />
<LineId Id="87" Count="0" />
<LineId Id="79" Count="1" />
<LineId Id="12" Count="0" />
<LineId Id="44" Count="8" />
<LineId Id="62" Count="0" />
<LineId Id="14" Count="0" />
<LineId Id="33" Count="0" />
</LineIds>
<LineIds Name="MAIN.PROG">
<LineId Id="2" Count="0" />
<LineId Id="1" Count="0" />
<LineId Id="5" Count="0" />
<LineId Id="3" Count="0" />
</LineIds>
<LineIds Name="MAIN.RESTORE_POSITIONS">

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.0">
<POU Name="tcUNIT_APP_RUN" Id="{677fcae4-9d84-425e-8fcd-8e3d3a1985e8}" SpecialFunc="None">
<Declaration><![CDATA[(* tcUNIT Tests: Add this program to PLC task in order to run tcUNIT tests against the declared POU test suites.
see https://tcunit.org/ for documentation.*)
PROGRAM tcUNIT_APP_RUN
VAR
(* Declare standard library POU tests to be run
E.g. fbMoveNonLinearSlits: FB_MoveNonLinearSlits_Test;*)
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[TcUnit.RUN();]]></ST>
</Implementation>
<LineIds Name="tcUNIT_APP_RUN">
<LineId Id="45" Count="0" />
</LineIds>
</POU>
</TcPlcObject>

View File

@@ -0,0 +1,149 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.0">
<POU Name="FB_tcUNIT_common" Id="{0f757d3d-99b7-46eb-bdc6-03aa126689f4}" SpecialFunc="None">
<Declaration><![CDATA[// tcUNIT Common function block: Contains helper methods for tcUNIT.
FUNCTION_BLOCK FB_tcUNIT_common
VAR
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
<Method Name="mEnableAxis" Id="{12e91532-7139-4c17-998e-4c670b584b9d}">
<Declaration><![CDATA[METHOD mEnableAxis : BOOL
VAR_INPUT
iAxisIndex: INT; // The idex of the axis to action the method on.
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[GVL.axes[iAxisIndex].control.bEnable := TRUE;]]></ST>
</Implementation>
</Method>
<Method Name="mExecute" Id="{010bd927-5568-40db-a7c5-fcfe995a5cb1}">
<Declaration><![CDATA[METHOD mExecute : BOOL
VAR_INPUT
iAxisIndex: INT; // The idex of the axis to action the method on.
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[GVL.axes[iAxisIndex].control.bExecute := TRUE;]]></ST>
</Implementation>
</Method>
<Method Name="mPrepareDefaultMove" Id="{c23244d5-896c-49ad-8d8a-19390856e4dc}">
<Declaration><![CDATA[METHOD mPrepareDefaultMove
VAR_INPUT
iAxisIndex: INT; // The idex of the axis to action the method on.
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[// Prepare an axis so it is ready to action a move using target defaults when executed.
GVL.axes[iAxisIndex].control.bEnable := TRUE;
GVL.axes[iAxisIndex].control.eCommand := MotionFunctions.MoveAbsolute;
GVL.axes[iAxisIndex].inputs.bLimitBwd := TRUE;
GVL.axes[iAxisIndex].inputs.bLimitFwd := TRUE;
GVL.axes[iAxisIndex].config.fVelocity := tcUNIT_GVL.fDEFAULT_TARGET_VELOCITY;
GVL.axes[iAxisIndex].config.fAcceleration := tcUNIT_GVL.fDEFAULT_TARGET_ACCELERATION;
GVL.axes[iAxisIndex].config.fDeceleration := tcUNIT_GVL.fDEFAULT_TARGET_DECCELERATION;
GVL.axes[iAxisIndex].config.fOverride := tcUNIT_GVL.fDEFAULT_TARGET_OVERRIDE;
GVL.axes[iAxisIndex].config.fPosition := tcUNIT_GVL.fDEFAULT_POSITION;]]></ST>
</Implementation>
</Method>
<Method Name="mPrepareMove" Id="{97bd5417-d0a1-4d32-8732-16310a863fcc}">
<Declaration><![CDATA[METHOD mPrepareMove
VAR_INPUT
iAxisIndex: INT; // The idex of the axis to action the method on.
fTargetVelocity: LREAL;
fTargetAcceleration: LREAL;
fTargetDeceleration: LREAL;
fTargetPosition: LREAL;
eMotionStrategy: MotionFunctions; // The desired MotionFunctions motion strategy.
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[// Prepare the axis so it is ready to action a move when executed for a given motion strategy.
GVL.axes[iAxisIndex].control.bEnable := FALSE;
GVL.axes[iAxisIndex].control.eCommand := eMotionStrategy;
GVL.axes[iAxisIndex].inputs.bLimitBwd := TRUE;
GVL.axes[iAxisIndex].inputs.bLimitFwd := TRUE;
GVL.axes[iAxisIndex].config.fVelocity := fTargetVelocity;
GVL.axes[iAxisIndex].config.fAcceleration := fTargetAcceleration;
GVL.axes[iAxisIndex].config.fDeceleration := fTargetDeceleration;
GVL.axes[iAxisIndex].config.fPosition := fTargetPosition;]]></ST>
</Implementation>
</Method>
<Method Name="mSetAxisDefaults" Id="{5b9336be-4414-4858-a614-0fdb2847e171}">
<Declaration><![CDATA[METHOD mSetAxisDefaults
VAR_INPUT
iAxisIndex: INT; // The idex of the axis to action the method on.
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[// Set PLC default values for the axis. Note: Status values can take multiple cycles to updated. This is not an instant reset.
IF GVL.axes[iAxisIndex].status.bBusy THEN
GVL.axes[iAxisIndex].control.bStop := TRUE;
END_IF
IF GVL.axes[iAxisIndex].status.bError THEN
GVL.axes[iAxisIndex].control.bReset := TRUE;
END_IF
IF NOT GVL.axes[iAxisIndex].control.bEnable AND GVL.axes[iAxisIndex].control.bStop THEN
GVL.axes[iAxisIndex].control.bStop := FALSE;
END_IF
GVL.axes[iAxisIndex].control.bEnable := FALSE;
GVL.axes[iAxisIndex].control.bExecute := FALSE;
GVL.axes[iAxisIndex].control.bReset := FALSE;
GVL.axes[iAxisIndex].control.bJogFwd := FALSE;
GVL.axes[iAxisIndex].control.bJogBwd := FALSE;
GVL.axes[iAxisIndex].control.bStop := FALSE;
GVL.axes[iAxisIndex].control.eCommand := MotionFunctions.MoveAbsolute;
GVL.axes[iAxisIndex].config.fVelocity := 0.0;
GVL.axes[iAxisIndex].config.fAcceleration := 0.0;
GVL.axes[iAxisIndex].config.fDeceleration := 0.0;
GVL.axes[iAxisIndex].config.fPosition := 0;
GVL.axes[iAxisIndex].config.fOverride := 0.0;
GVL.axes[iAxisIndex].config.nHomeSeq := 0;
GVL.axes[iAxisIndex].inputs.bLimitBwd := FALSE;
GVL.axes[iAxisIndex].inputs.bLimitFwd := FALSE;
GVL.axes[iAxisIndex].inputs.bEncLAtch := FALSE;
GVL.axes[iAxisIndex].inputs.bHomeSensor := FALSE;]]></ST>
</Implementation>
</Method>
<LineIds Name="FB_tcUNIT_common">
<LineId Id="9" Count="0" />
</LineIds>
<LineIds Name="FB_tcUNIT_common.mEnableAxis">
<LineId Id="5" Count="0" />
</LineIds>
<LineIds Name="FB_tcUNIT_common.mExecute">
<LineId Id="5" Count="0" />
</LineIds>
<LineIds Name="FB_tcUNIT_common.mPrepareDefaultMove">
<LineId Id="6" Count="0" />
<LineId Id="38" Count="0" />
<LineId Id="8" Count="1" />
<LineId Id="39" Count="0" />
<LineId Id="11" Count="6" />
<LineId Id="19" Count="0" />
</LineIds>
<LineIds Name="FB_tcUNIT_common.mPrepareMove">
<LineId Id="17" Count="11" />
</LineIds>
<LineIds Name="FB_tcUNIT_common.mSetAxisDefaults">
<LineId Id="6" Count="0" />
<LineId Id="41" Count="0" />
<LineId Id="34" Count="1" />
<LineId Id="31" Count="0" />
<LineId Id="44" Count="1" />
<LineId Id="43" Count="0" />
<LineId Id="36" Count="2" />
<LineId Id="7" Count="19" />
</LineIds>
</POU>
</TcPlcObject>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.0">
<GVL Name="tcUNIT_GVL" Id="{4b23d6c9-6a88-40b7-9bf4-d55c4dfd4246}">
<Declaration><![CDATA[// tcUNIT_GVL: Global variables used in tcUNIT tests.
{attribute 'qualified_only'}
VAR_GLOBAL CONSTANT
// Constants for axis defaults.
fDEFAULT_VELOCITY: LREAL := 0.0;
fDEFAULT_ACCELERATION: LREAL := 0.0;
fDEFAULT_DECCELERATION: LREAL := 0.0;
fDEFAULT_POSITION: LREAL := 0.0;
fDEFAULT_TARGET_VELOCITY: LREAL := 1.0;
fDEFAULT_TARGET_ACCELERATION: LREAL := 0.5;
fDEFAULT_TARGET_DECCELERATION: LREAL := 0.5;
fDEFAULT_TARGET_POSITION: LREAL := 10.0;
fDEFAULT_TARGET_OVERRIDE: LREAL := 100;
END_VAR
VAR_GLOBAL
END_VAR]]></Declaration>
</GVL>
</TcPlcObject>

View File

@@ -0,0 +1,248 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.0">
<POU Name="FB_Axis_TEST" Id="{3bfca2b4-3b3f-48f2-9900-9d4cd3404e9e}" SpecialFunc="None">
<Declaration><![CDATA[// Test suite for the FB_Axis POU
{attribute 'call_after_init'}
FUNCTION_BLOCK FB_Axis_TEST EXTENDS tcUnit.FB_TestSuite
VAR
fbCommon: FB_tcUNIT_common;
iTargetAxis: INT := 1; // The <index> of the axis within GVL.axes[<index>] to test against.
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[// Declare methods defined in the FB_Axis_TEST POU to be included (executed) in the test suite
SetAxisControl_Enabled();
CheckAxisStatus_Moving();
SetAxisConfig_Acceleration();
CheckAxisStatus_NewPosition();
SetAxisControl_Velocity();
SetAxisInputs_bLimitFwd();]]></ST>
</Implementation>
<Method Name="CheckAxisStatus_Moving" Id="{f7dcf822-91ec-4555-918f-e2487353578a}">
<Declaration><![CDATA[METHOD CheckAxisStatus_Moving
VAR
Result: BOOL;
ExpectedResult: BOOL;
nCycle: UINT;
nMaxCycles: UINT := 30;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('test_GIVEN_new_axis_position_WHEN_execute_move_THEN_axis_moves');
ExpectedResult := TRUE;
fbCommon.mPrepareDefaultMove(iTargetAxis);
fbCommon.mExecute(iTargetAxis);
Result := GVL.axes[iTargetAxis].status.bBusy;
IF nCycle > nMaxCycles OR ExpectedResult = Result THEN
AssertEquals(Expected := ExpectedResult,
Actual := Result,
Message := 'Axis is not moving.');
TEST_FINISHED();
ELSE
nCycle := nCycle + 1;
END_IF]]></ST>
</Implementation>
</Method>
<Method Name="CheckAxisStatus_NewPosition" Id="{604b9446-af57-41db-afac-f53f5b12cc2c}">
<Declaration><![CDATA[METHOD CheckAxisStatus_NewPosition
VAR
InitialValue: LREAL;
Result: LREAL;
ExpectedResult: LREAL;
nCycle: UINT;
nCycleMax: UINT := 100;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('test_GIVEN_new_axis_position_set_WHEN_executed_THEN_axis_moves_to_new_position');
// Since the axis has state; a test might begin the position at some location set by
// a previous test. Therefore if we execute a move we should just check it's moved
// from the initial location not some initial default.
InitialValue := GVL.axes[iTargetAxis].config.fPosition;
ExpectedResult := InitialValue + 10;
GVL.axes[iTargetAxis].config.fPosition := ExpectedResult;
GVL.axes[iTargetAxis].control.eCommand := MotionFunctions.MoveAbsolute;
GVL.axes[iTargetAxis].control.bExecute := TRUE;
Result := GVL.axes[iTargetAxis].status.fActPosition;
IF nCycle > nCycleMax OR ExpectedResult = Result THEN
AssertEquals(Expected := ExpectedResult,
Actual := Result,
Message := 'fPosition of the axis is different.');
TEST_FINISHED();
ELSE
nCycle := nCycle + 1;
END_IF]]></ST>
</Implementation>
</Method>
<Method Name="SetAxisConfig_Acceleration" Id="{2efd2402-6ad3-455d-a703-347847c98522}">
<Declaration><![CDATA[METHOD SetAxisConfig_Acceleration
VAR
InitialValue: LREAL;
Result: LREAL;
ExpectedResult: LREAL;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('test_GIVEN_new_axis_acceleration_set_WHEN_executed_THEN_new_axis_acceleration_set');
// example of direct GVL axis reference for assert.
ExpectedResult := tcUNIT_gvl.fDEFAULT_TARGET_ACCELERATION;
fbCommon.mPrepareDefaultMove(iTargetAxis);
Result := GVL.axes[1].config.fAcceleration;
AssertEquals(Expected := ExpectedResult,
Actual := Result,
Message := 'fAcceleration of the axis is different.');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="SetAxisControl_Enabled" Id="{749049e6-6152-4a23-ac76-75883bd089b7}">
<Declaration><![CDATA[METHOD SetAxisControl_Enabled
VAR
Result: BOOL;
ExpectedResult: BOOL;
nCycle: UINT;
nMaxCycles: UINT := 30;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('test_GIVEN_prepare_default_move_WHEN_move_prepared_THEN_axis_enabled');
// example of test that requires multiple cycles to complete. Due to stateful behaviour of the axis structure.
ExpectedResult := TRUE;
GVL.axes[1].control.bEnable := ExpectedResult;
Result := GVL.axes[iTargetAxis].status.bEnabled;
IF nCycle > nMaxCycles OR ExpectedResult = Result THEN
AssertEquals(Expected := ExpectedResult,
Actual := Result,
Message := 'Axis is not enabled.');
TEST_FINISHED();
ELSE
nCycle := nCycle + 1;
END_IF
]]></ST>
</Implementation>
</Method>
<Method Name="SetAxisControl_Velocity" Id="{f87270b6-fb94-4214-bb13-17f22f6ab8f5}">
<Declaration><![CDATA[METHOD SetAxisControl_Velocity
VAR
InitialValue: LREAL;
Result: LREAL;
ExpectedResult: LREAL;
fDelta: REAL := 0.01;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('test_GIVEN_new_axis_velocity_set_WHEN_executed_THEN_new_axis_velocity_set');
// Example of using a tcUNIT assert for a specific type (in this case LREAL).
InitialValue := GVL.axes[iTargetAxis].config.fVelocity;
ExpectedResult := InitialValue + 0.5;
GVL.Axes[iTargetAxis].config.fVelocity := ExpectedResult;
Result := GVL.axes[iTargetAxis].config.fVelocity;
AssertEquals_LREAL(Expected := ExpectedResult,
Actual := Result,
Delta := fDelta,
Message := 'fVelocity of the axis is different.');
TEST_FINISHED();
]]></ST>
</Implementation>
</Method>
<Method Name="SetAxisInputs_bLimitFwd" Id="{6304c3b1-9e72-403e-9ae2-a5609b1efe92}">
<Declaration><![CDATA[METHOD SetAxisInputs_bLimitFwd
VAR
Result: BOOL;
ExpectedResult: BOOL;
nCycle: UINT;
nMaxCycles: UINT := 30;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('test_GIVEN_prepare_default_move_WHEN_bFwEnabled_prepared_enabled_THEN_bFwEnable_enabled');
ExpectedResult := TRUE;
GVL.axes[iTargetAxis].inputs.bLimitFwd := TRUE;
Result := GVL.axes[iTargetAxis].status.bFwEnabled;
IF nCycle > nMaxCycles OR ExpectedResult = Result THEN
AssertEquals(Expected := ExpectedResult,
Actual := Result,
Message := 'Axis bLimitFwd is not enabled.');
TEST_FINISHED();
ELSE
nCycle := nCycle + 1;
END_IF]]></ST>
</Implementation>
</Method>
<LineIds Name="FB_Axis_TEST">
<LineId Id="37" Count="0" />
<LineId Id="34" Count="0" />
<LineId Id="38" Count="1" />
<LineId Id="12" Count="0" />
<LineId Id="40" Count="0" />
<LineId Id="48" Count="0" />
</LineIds>
<LineIds Name="FB_Axis_TEST.CheckAxisStatus_Moving">
<LineId Id="127" Count="16" />
</LineIds>
<LineIds Name="FB_Axis_TEST.CheckAxisStatus_NewPosition">
<LineId Id="121" Count="21" />
<LineId Id="56" Count="0" />
</LineIds>
<LineIds Name="FB_Axis_TEST.SetAxisConfig_Acceleration">
<LineId Id="5" Count="0" />
<LineId Id="50" Count="1" />
<LineId Id="9" Count="0" />
<LineId Id="13" Count="0" />
<LineId Id="57" Count="0" />
<LineId Id="23" Count="0" />
<LineId Id="22" Count="0" />
<LineId Id="25" Count="4" />
<LineId Id="24" Count="0" />
</LineIds>
<LineIds Name="FB_Axis_TEST.SetAxisControl_Enabled">
<LineId Id="144" Count="16" />
<LineId Id="107" Count="0" />
</LineIds>
<LineIds Name="FB_Axis_TEST.SetAxisControl_Velocity">
<LineId Id="5" Count="0" />
<LineId Id="92" Count="1" />
<LineId Id="10" Count="0" />
<LineId Id="61" Count="2" />
<LineId Id="67" Count="0" />
<LineId Id="69" Count="0" />
<LineId Id="91" Count="0" />
<LineId Id="70" Count="1" />
<LineId Id="80" Count="0" />
<LineId Id="72" Count="0" />
<LineId Id="24" Count="0" />
<LineId Id="86" Count="0" />
</LineIds>
<LineIds Name="FB_Axis_TEST.SetAxisInputs_bLimitFwd">
<LineId Id="24" Count="0" />
<LineId Id="26" Count="0" />
<LineId Id="25" Count="0" />
<LineId Id="48" Count="2" />
<LineId Id="67" Count="0" />
<LineId Id="19" Count="0" />
<LineId Id="58" Count="6" />
<LineId Id="57" Count="0" />
</LineIds>
</POU>
</TcPlcObject>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.0">
<POU Name="tcUNIT_STD_LIB_RUN" Id="{5e8cc903-e536-40be-a096-d6b305fbb618}" SpecialFunc="None">
<Declaration><![CDATA[// tcUNIT Standard Library tests: Add program to PLC task in order to run tcUNIT tests against the declared POU test suites
PROGRAM tcUNIT_STD_LIB_RUN
VAR
// Declare standard library POU tests to be run
fbFB_Axis: FB_Axis_TEST;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[TcUnit.RUN();]]></ST>
</Implementation>
<LineIds Name="tcUNIT_STD_LIB_RUN">
<LineId Id="45" Count="0" />
</LineIds>
</POU>
</TcPlcObject>

View File

@@ -6,7 +6,7 @@
<ProjectGuid>{fb261665-fd20-4bf2-97f8-2854c82b752d}</ProjectGuid>
<SubObjectsSortedByName>True</SubObjectsSortedByName>
<Name>tc_project_app</Name>
<ProgramVersion>3.1.4023.0</ProgramVersion>
<ProgramVersion>3.1.4022.6</ProgramVersion>
<Application>{047dee04-c246-47b2-8ccc-a15e36987c43}</Application>
<TypeSystem>{ae4eb5ee-6030-47a6-bf35-5a6afd9efeeb}</TypeSystem>
<Implicit_Task_Info>{5ef19bd0-aca2-493f-b2a1-89e363647697}</Implicit_Task_Info>
@@ -14,6 +14,7 @@
<Implicit_Jitter_Distribution>{26d08e27-a705-49a9-95de-a3a0b6ea049c}</Implicit_Jitter_Distribution>
<LibraryReferences>{577f21c4-8eb2-4f2c-a24e-4c3f62ca96d2}</LibraryReferences>
<AutoUpdateVisuProfile>true</AutoUpdateVisuProfile>
<Released>false</Released>
</PropertyGroup>
<ItemGroup>
<Compile Include="GlobalTextList.TcGTLO">
@@ -74,117 +75,6 @@
<Compile Include="tc_mca_std_lib\POUs\ChangeConfig\FB_WriteParameterInNc_v1_00.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\ErrorHandling\DUT_ErrorState.TcDUT">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\ErrorHandling\FB_ErrorSystem.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\ErrorHandling\FB_GenericError.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\ErrorHandling\FB_NC_Error.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\ErrorHandling\FB_TerminalError.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\ErrorHandling\ST_ErrorEntry.TcDUT">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\ErrorHandling\ST_ErrorSystem.TcDUT">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Analog_Inputs\EL3174_0002.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Analog_Inputs\EL3214.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Analog_Inputs\EL3255.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Digital_Inputs\EL1008.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Digital_Inputs\EL1018.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Digital_Inputs\EL1252.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Digital_Inputs\EL1808.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Digital_Inputs\EL1809.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Digital_Inputs\EL1819.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Digital_Outputs\EL2014.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Digital_Outputs\EL2252.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Digital_Outputs\EL2808.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Digital_Outputs\EL2819.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Digital_Outputs\External_Types\dutEL2521_Ctrl.TcDUT">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Digital_Outputs\External_Types\dutEL2521_Status.TcDUT">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Drives\EL2522.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Drives\EL4134.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Drives\EL7037.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Drives\EL7041_0052.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Drives\EL7047.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Drives\EL7211.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Feedback_Terminals\EL5002.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Feedback_Terminals\EL5021.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Feedback_Terminals\EL5042.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Feedback_Terminals\EL5101.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Feedback_Terminals\EL7201.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\System\EK1100.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\System\EK1110.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\System\EL9410.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\System\EL9505.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="tc_mca_std_lib\POUs\Motion\FB_Axis.TcPOU">
<SubType>Code</SubType>
</Compile>
@@ -232,6 +122,21 @@
<Compile Include="tc_mca_std_lib\POUs\VISUs\visuTextLinks.TcTLO">
<SubType>Code</SubType>
</Compile>
<Compile Include="Test\app_tests\tcUNIT_APP_RUN.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="Test\common\FB_tcUNIT_common.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="Test\common\tcUNIT_GVL.TcGVL">
<SubType>Code</SubType>
</Compile>
<Compile Include="Test\standard_library_tests\FB_Axis_TEST.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="Test\standard_library_tests\tcUNIT_STD_LIB_RUN.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="Visualization Manager.TcVMO">
<SubType>Code</SubType>
</Compile>
@@ -239,26 +144,18 @@
<ItemGroup>
<Folder Include="DUTs" />
<Folder Include="GVLs" />
<Folder Include="Test" />
<Folder Include="tc_mca_std_lib" />
<Folder Include="tc_mca_std_lib\DUTs" />
<Folder Include="tc_mca_std_lib\GVLs" />
<Folder Include="tc_mca_std_lib\POUs" />
<Folder Include="tc_mca_std_lib\POUs\ChangeConfig" />
<Folder Include="tc_mca_std_lib\POUs\Hardware" />
<Folder Include="tc_mca_std_lib\POUs\Hardware" />
<Folder Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals" />
<Folder Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Analog_Inputs" />
<Folder Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Digital_Inputs" />
<Folder Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Digital_Outputs" />
<Folder Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Digital_Outputs\External_Types" />
<Folder Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Drives" />
<Folder Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\Feedback_Terminals" />
<Folder Include="tc_mca_std_lib\POUs\Hardware\EtherCAT_Terminals\System" />
<Folder Include="tc_mca_std_lib\POUs\Motion" />
<Folder Include="tc_mca_std_lib\POUs\Hardware" />
<Folder Include="tc_mca_std_lib\POUs\ErrorHandling" />
<Folder Include="tc_mca_std_lib\POUs\Motion\Homing" />
<Folder Include="tc_mca_std_lib\POUs\VISUs" />
<Folder Include="Test\app_tests" />
<Folder Include="Test\common" />
<Folder Include="Test\standard_library_tests" />
<Folder Include="VISUs" />
<Folder Include="POUs" />
</ItemGroup>
@@ -337,6 +234,10 @@
<DefaultResolution>Tc3_Module, * (Beckhoff Automation GmbH)</DefaultResolution>
<Namespace>Tc3_Module</Namespace>
</PlaceholderReference>
<PlaceholderReference Include="TcUnit">
<DefaultResolution>TcUnit, * (www.tcunit.org)</DefaultResolution>
<Namespace>TcUnit</Namespace>
</PlaceholderReference>
<PlaceholderReference Include="VisuDialogs">
<DefaultResolution>VisuDialogs, * (System)</DefaultResolution>
<Namespace>VisuDialogs</Namespace>