Added hot and cold plates

- Started spinner chuck io's
This commit is contained in:
2026-02-01 13:53:21 +01:00
parent 8c41ff9bad
commit 1ade81c1c5
30 changed files with 3626 additions and 5882 deletions

View File

@@ -1,25 +1,146 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<POU Name="FB_Etcher" Id="{e75b6d70-36db-4c78-b78d-a594609441d1}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_Etcher
<Declaration><![CDATA[FUNCTION_BLOCK FB_Etcher EXTENDS FB_PackMLGeneric
VAR_INPUT
xOpenDoor : BOOL;
xOpenChuckClamp : BOOL;
xEjectChuck : BOOL;
xConfirmAlarms : BOOL;
END_VAR
VAR_OUTPUT
xChuckClampOpen : BOOL;
END_VAR
VAR
_xOpenDoor AT %Q* : BOOL;
_xCloseDoor AT %Q* : BOOL;
_fbValveDoor : FB_Valve('Door');
_stValveDoorCfg : ST_ValveConfig := (
xHasClosedFeedback := TRUE,
xHasOpenFeedback := TRUE,
timTimeoutOpen := T#5S,
timTimeoutClose := T#5S);
_stDoorHMIInterface : ST_HMI_VALVE_DATA;
_fbClampingLeft : FB_Valve('Clamping left');
_stValveClampingLeftCfg : ST_ValveConfig := (
xHasClosedFeedback := TRUE,
xHasOpenFeedback := TRUE,
timTimeoutOpen := T#5S,
timTimeoutClose := T#5S);
_stClampingLeftHMIInterface : ST_HMI_VALVE_DATA;
_fbClampingRight : FB_Valve('Clamping right');
_stValveClampingRightCfg : ST_ValveConfig := (
xHasClosedFeedback := TRUE,
xHasOpenFeedback := TRUE,
timTimeoutOpen := T#5S,
timTimeoutClose := T#5S);
_stClampingRightHMIInterface : ST_HMI_VALVE_DATA;
_fbClampingFront : FB_Valve('Clamping front');
_stValveClampingFrontCfg : ST_ValveConfig := (
xHasClosedFeedback := TRUE,
xHasOpenFeedback := TRUE,
timTimeoutOpen := T#5S,
timTimeoutClose := T#5S);
_stClampingFrontHMIInterface : ST_HMI_VALVE_DATA;
_fbClampingBack : FB_Valve('Clamping back');
_stValveClampingBackCfg : ST_ValveConfig := (
xHasClosedFeedback := TRUE,
xHasOpenFeedback := TRUE,
timTimeoutOpen := T#5S,
timTimeoutClose := T#5S);
_stClampingBackHMIInterface : ST_HMI_VALVE_DATA;
_rtEjectChuckCmd : R_TRIG;
_tpEjectChuck : TP;
// =======
// Sensors
// =======
// Spinner vibration sensor
_xVibrationSensor AT %I* : BOOL;
// =========
// Actuators
// =========
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[IF xOpenDoor THEN
_xOpenDoor := TRUE;
_xCloseDoor := FALSE;
<ST><![CDATA[// Main door
_fbValveDoor(
xAutomaticOpen:= xOpenDoor,
xReleaseErrors:= TRUE,
stValveConfig:= _stValveDoorCfg,
xReleaseManualMode:= FALSE,
xConfirmAlarms:= xConfirmAlarms,
stHMIInterface:= _stDoorHMIInterface);
// Chuck
_rtEjectChuckCmd(CLK := xEjectChuck);
IF _rtEjectChuckCmd.Q THEN
_tpEjectChuck(IN := TRUE, PT := T#500MS);
ELSE
_xOpenDoor := FALSE;
_xCloseDoor := TRUE;
END_IF]]></ST>
_tpEjectChuck(IN := FALSE);
END_IF
_fbClampingLeft(
xAutomaticOpen:= xOpenChuckClamp,
xReleaseErrors:= TRUE,
stValveConfig:= _stValveClampingLeftCfg,
xReleaseManualMode:= FALSE,
xConfirmAlarms:= xConfirmAlarms,
stHMIInterface:= _stClampingLeftHMIInterface);
_fbClampingRight(
xAutomaticOpen:= xOpenChuckClamp,
xReleaseErrors:= TRUE,
stValveConfig:= _stValveClampingRightCfg,
xReleaseManualMode:= FALSE,
xConfirmAlarms:= xConfirmAlarms,
stHMIInterface:= _stClampingRightHMIInterface);
_fbClampingFront(
xAutomaticOpen:= _tpEjectChuck.Q,
xReleaseErrors:= TRUE,
stValveConfig:= _stValveClampingFrontCfg,
xReleaseManualMode:= FALSE,
xConfirmAlarms:= xConfirmAlarms,
stHMIInterface:= _stClampingFrontHMIInterface);
_fbClampingBack(
xAutomaticOpen:= _tpEjectChuck.Q,
xReleaseErrors:= TRUE,
stValveConfig:= _stValveClampingBackCfg,
xReleaseManualMode:= FALSE,
xConfirmAlarms:= xConfirmAlarms,
stHMIInterface:= _stClampingBackHMIInterface);
// Call base sm
SUPER^();]]></ST>
</Implementation>
<Method Name="FB_Init" Id="{afcda70c-3e52-4a32-9ca9-670a6b854f24}">
<Declaration><![CDATA[//FB_Init is always available implicitly and it is used primarily for initialization.
//The return value is not evaluated. For a specific influence, you can also declare the
//methods explicitly and provide additional code there with the standard initialization
//code. You can evaluate the return value.
METHOD FB_Init: BOOL
VAR_INPUT
bInitRetains: BOOL; // TRUE: the retain variables are initialized (reset warm / reset cold)
bInCopyCode: BOOL; // TRUE: the instance will be copied to the copy code afterward (online change)
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[_stSMConfig.xStoppingDisabled := TRUE;
_stSMConfig.xCompletingDisabled := TRUE;
_stSMConfig.xCompletedDisabled := TRUE;
_stSMConfig.xAbortingDisabled := TRUE;]]></ST>
</Implementation>
</Method>
</POU>
</TcPlcObject>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<POU Name="FB_HVTester" Id="{63fd7fbb-2896-492c-ad94-827a20571a58}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_HVTester
<Declaration><![CDATA[FUNCTION_BLOCK FB_HVTester EXTENDS FB_PackMLGeneric
VAR_INPUT
xOpenChambers : BOOL;
END_VAR
@@ -35,7 +35,10 @@ ELSE
_xCloseDoor1 := TRUE;
_xCloseDoor2 := TRUE;
END_IF]]></ST>
END_IF
// Call base sm
SUPER^();]]></ST>
</Implementation>
</POU>
</TcPlcObject>

View File

@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<POU Name="FB_CoolPlate" Id="{629e3316-5d72-4e23-a03a-af14d37e58d6}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_CoolPlate
VAR_INPUT
rTempSetpoint : REAL := 25.0;
END_VAR
VAR_OUTPUT
END_VAR
VAR
// Card inputs
_stStatus AT %I* : ST_SerialStatus;
_byDataIn AT %I* : ARRAY[0..21] OF BYTE;
// Card outputs
_stCtrl AT %Q* : ST_SerialCrl;
_byDataOut AT %Q* : ARRAY[0..21] OF BYTE;
// Internal temp setpoint
_rTempSetpoint : REAL;
// Send trigger
_xSend : BOOL;
// Send temp test
_xTempTest : BOOL;
// Init trigger
_xInit : BOOL;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// Clamp temperature settings
_rTempSetpoint := rTempSetpoint;
IF _rTempSetpoint > 60.0 THEN
_rTempSetpoint := 60.0;
END_IF
IF _rTempSetpoint < 10.0 THEN
_rTempSetpoint := 10.0;
END_IF
// Init card on first run
IF _xInit THEN
_xInit := FALSE;
_stCtrl.bInitRequest := 1;
END_IF
IF _stStatus.bInitAccepted THEN
_stCtrl.bInitRequest := 0;
END_IF
// Send
IF _xSend THEN
_xSend := FALSE;
_stCtrl.bTransmitRequest := 1;
END_IF
IF _stStatus.bTransmitAccepted THEN
_stCtrl.bTransmitRequest := 0;
END_IF
// Debug test
IF _xTempTest THEN
_xTempTest := FALSE;
M_SetTemp(rTemp := _rTempSetpoint);
_xSend := TRUE;
END_IF]]></ST>
</Implementation>
<Method Name="M_CalcChecksum" Id="{dc2c8dbc-8315-4281-befa-84b7f4e74dc9}">
<Declaration><![CDATA[METHOD M_CalcChecksum
VAR_INPUT
uiStartIndex : UINT;
uiEndIndex : UINT;
END_VAR
VAR_OUTPUT
byHigh : BYTE;
byLow : BYTE;
END_VAR
VAR
_dwChecksum : DWORD;
_uiCounter : UINT;
_byHigh : BYTE;
_byLow : BYTE;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// Calculate sum
FOR _uiCounter := uiStartIndex TO uiEndIndex DO
_dwChecksum := _dwChecksum + _byDataOut[_uiCounter];
END_FOR
// Use lower bytes
_byHigh := SHR(_dwChecksum.%B0 AND 16#F0, 4);
_byLow := _dwChecksum.%B0 AND 16#0F;
// Add offset
_byHigh := _byHigh + 16#30;
_byLow := _byLow + 16#30;
byHigh := _byHigh;
byLow := _byLow;]]></ST>
</Implementation>
</Method>
<Method Name="M_SetTemp" Id="{e9f6069c-f4a0-47e4-9ef0-4fbbec8764d9}">
<Declaration><![CDATA[METHOD M_SetTemp
VAR_INPUT
rTemp : REAL;
END_VAR
VAR
_dwTemp : DWORD;
_sTemp : STRING(4);
_byHigh : BYTE;
_byLow : BYTE;
_sHexString : STRING(4);
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// Convert temperature
_dwTemp := REAL_TO_DWORD(rTemp * 10)*10;
_sTemp := DWORD_TO_STRING(_dwTemp);
_byDataOut[0] := 16#02; // STX
_byDataOut[1] := 16#31; // Command code
_byDataOut[2] := _sTemp[0];
_byDataOut[3] := _sTemp[1];
_byDataOut[4] := _sTemp[2];
_byDataOut[5] := _sTemp[3];
_byDataOut[6] := 16#03; // ETX
M_CalcChecksum(
uiStartIndex:= 1,
uiEndIndex:= 5,
byHigh=> _byDataOut[7],
byLow=> _byDataOut[8]);
_byDataOut[9] := 16#0D; // <CR>
_stCtrl.byOutputLength := 10;]]></ST>
</Implementation>
</Method>
</POU>
</TcPlcObject>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<POU Name="FB_HeatCoolPlates" Id="{a2be063c-19d7-4ca2-8121-529d61cc7bc2}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_HeatCoolPlates
VAR_INPUT
xConfirmAlarms : BOOL;
END_VAR
VAR_OUTPUT
END_VAR
VAR
_fbHeatingPlate : FB_HotPlate;
_xEnableHotplate : BOOL;
_rTargetTemp : REAL := 30.0;
// Cool plate
_fbCoolPlate : FB_CoolPlate;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[_fbHeatingPlate(
xEnable:= _xEnableHotplate,
rTargetTemp:= _rTargetTemp,
xConfirmAlarms:= xConfirmAlarms,
uiNextFreeSlot=> ,
uiNextReadySlot=> );
_fbCoolPlate();]]></ST>
</Implementation>
</POU>
</TcPlcObject>

View File

@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<POU Name="FB_HotPlate" Id="{317a2373-f886-4e32-b683-81b726d00aac}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_HotPlate
VAR_INPUT
xEnable : BOOL;
rTargetTemp : REAL;
rDeadBand : REAL := 5.0;
xConfirmAlarms : BOOL;
END_VAR
VAR_OUTPUT
uiNextFreeSlot : UINT;
uiNextReadySlot : UINT;
END_VAR
VAR
_xEnableHotplate AT %Q* : BOOL;
_axSlotFree : ARRAY [0..(GVL_HeatCoolConfig.HEAT_COOL_PLATES_NUM_SLOTS - 1)] OF BOOL;
_tonSlotTimer : ARRAY[0..(GVL_HeatCoolConfig.HEAT_COOL_PLATES_NUM_SLOTS - 1)] OF TON;
// Temp sensor
_fbTempSensor : FB_AnalogInput('Temp sensor');
_stTempSensorConfig : ST_ANALOG_IO_CONFIG := (sUnit := '°C', rPVMin := -200, rPVMax := 850, iAIMin := -2000, iAIMax := 8500);
_stTempSEnsorEWConfig : ST_ANALOG_EW_CONFIG := (
stLevels := (
rErrorMin := -2000,
rErrorMax := 8500,
rWarningMin := -1000,
rWarningMax := 7500),
stDelays := (
timErrorHighOn := T#1S,
timErrorLowOn := T#1S,
timWarningHighOn := T#1S,
timWarningLowOn := T#1S,
timHardwareSignalLevelOff := T#1S));
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// Call sensor fbs
_fbTempSensor(
stAnalogIOConfig:= _stTempSensorConfig,
stAnalogEWConfig:= _stTempSEnsorEWConfig,
xReleaseErrors:= TRUE,
xReleaseLimitErrors:= FALSE,
xReleaseHardwareErrors:= TRUE,
xConfirmAlarms:= xConfirmAlarms,
stHMIInterface=> );
// Control temperature with two point controller
IF _fbTempSensor.rScaledValue < (rTargetTemp - rDeadBand) THEN
_xEnableHotplate := TRUE;
END_IF
IF _fbTempSensor.rScaledValue >= (rTargetTemp) THEN
_xEnableHotplate := FALSE;
END_IF
]]></ST>
</Implementation>
<Method Name="M_AddItem" Id="{9707459a-6558-487c-b730-c9dc92d598ed}">
<Declaration><![CDATA[METHOD M_AddItem
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
</POU>
</TcPlcObject>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<GVL Name="GVL_HeatCoolConfig" Id="{865917de-a2fa-49b0-b682-05395fd01971}">
<Declaration><![CDATA[{attribute 'qualified_only'}
VAR_GLOBAL CONSTANT
HEAT_COOL_PLATES_NUM_SLOTS : UINT := 9;
END_VAR]]></Declaration>
</GVL>
</TcPlcObject>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<DUT Name="ST_SerialCrl" Id="{02e99166-5c76-4fb3-84cc-719c63e20136}">
<Declaration><![CDATA[{attribute 'pack_mode' := '1'}
TYPE ST_SerialCrl :
STRUCT
bTransmitRequest : BIT;
bReceiveAccepted : BIT;
bInitRequest : BIT;
bSendContinues : BIT;
byOutputLength : BYTE;
END_STRUCT
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<DUT Name="ST_SerialStatus" Id="{e37399e0-7acb-4d91-826f-26258cabab1c}">
<Declaration><![CDATA[{attribute 'pack_mode' := '1'}
TYPE ST_SerialStatus :
STRUCT
bTransmitAccepted : BIT;
bReceiveRequested : BIT;
bInitAccepted : BIT;
bBufferFull : BIT;
bParityError : BIT;
bFramingError : BIT;
bOverrunError : BIT;
byInputLength : BYTE;
END_STRUCT
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

View File

@@ -140,9 +140,9 @@ SUPER^();
_uCtrl.stCtrl.bNotDisableAxes := 1;
// Disable move if in T2 for safety reasons
IF _uState.stState.bT2 THEN
_uCtrl.stCtrl.bEnableMove := 0;
END_IF
// IF _uState.stState.bT2 THEN
// _uCtrl.stCtrl.bEnableMove := 0;
// END_IF
// ============================
@@ -179,7 +179,7 @@ _stSMConfig.xAbortingDisabled := TRUE;]]></ST>
</Implementation>
</Method>
<Method Name="M_Aborted" Id="{0c0c17ce-5c1c-4640-9d39-f25b22309d5d}">
<Declaration><![CDATA[METHOD M_Aborted
<Declaration><![CDATA[METHOD PROTECTED M_Aborted
]]></Declaration>
<Implementation>
<ST><![CDATA[// Reset all relevant robot control signals
@@ -196,7 +196,7 @@ _uJobs.stJobs.wFinishedJobNrFromPlc := E_KukaRobot_JobNumerPLC.NO_JOB;]]></ST>
</Implementation>
</Method>
<Method Name="M_Clearing" Id="{e6152288-8c7d-4b38-bfbc-4f861d76ccc5}">
<Declaration><![CDATA[METHOD M_Clearing
<Declaration><![CDATA[METHOD PROTECTED M_Clearing
VAR_INST
_tonWait : TON;
END_VAR]]></Declaration>
@@ -214,7 +214,7 @@ END_IF
</Implementation>
</Method>
<Method Name="M_Execute" Id="{bc86876c-a8db-4285-b95c-7c6858a2ca66}">
<Declaration><![CDATA[METHOD M_Execute
<Declaration><![CDATA[METHOD PROTECTED M_Execute
]]></Declaration>
<Implementation>
<ST><![CDATA[// Wait for robot to be done
@@ -224,28 +224,33 @@ END_IF]]></ST>
</Implementation>
</Method>
<Method Name="M_Held" Id="{22ddbad0-0b66-427e-a2aa-f177f8adbc94}">
<Declaration><![CDATA[METHOD M_Held
<Declaration><![CDATA[METHOD PROTECTED M_Held
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_Holding" Id="{ff8c2c8e-1fe0-4c63-ad7b-790d72bd9217}">
<Declaration><![CDATA[METHOD M_Holding
<Declaration><![CDATA[METHOD PROTECTED M_Holding
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
<ST><![CDATA[_uCtrl.stCtrl.bEnableMove := 0;
IF _uState.stState.bRobStopped THEN
M_StateComplete();
END_IF
]]></ST>
</Implementation>
</Method>
<Method Name="M_Idle" Id="{025437ab-beb0-4ad6-bdc3-468dec599ff4}">
<Declaration><![CDATA[METHOD M_Idle
<Declaration><![CDATA[METHOD PROTECTED M_Idle
]]></Declaration>
<Implementation>
<ST><![CDATA[_stJobParams := stJobParams;]]></ST>
</Implementation>
</Method>
<Method Name="M_Resetting" Id="{dfe4d36a-80aa-4364-bfd8-6ddd41636d59}">
<Declaration><![CDATA[METHOD M_Resetting
<Declaration><![CDATA[METHOD PROTECTED M_Resetting
VAR_INST
_tonTimeout : TON;
END_VAR]]></Declaration>
@@ -253,7 +258,26 @@ END_VAR]]></Declaration>
<ST><![CDATA[_tonTimeout(PT := T#10S);
CASE _iSSM OF
// Check if com interface is ok
0:
_uCtrl.stCtrl.bEnableMove := 1;
_uCtrl.stCtrl.bConfMess := 1;
_tonTimeout.IN := TRUE;
IF _uState.stState.bIOActConf THEN
_uCtrl.stCtrl.bConfMess := 0;
_iSSM := 10;
END_IF
// Timeout io_Act_conf ready
IF _tonTimeout.Q THEN
_uCtrl.stCtrl.bConfMess := 0;
_tonTimeout(IN := FALSE);
_eCmd := E_PackMLCmd.ABORT;
END_IF
// Enable axes
10:
_uCtrl.stCtrl.bEnableAxes := 1;
_tonTimeout.IN := TRUE;
@@ -261,7 +285,7 @@ CASE _iSSM OF
IF _uState.stState.bPeriRdy THEN
_uCtrl.stCtrl.bEnableAxes := 0;
_tonTimeout(IN := FALSE);
_iSSM := 10;
_iSSM := 20;
END_IF
// Timeout drives ready
@@ -272,16 +296,16 @@ CASE _iSSM OF
_eCmd := E_PackMLCmd.ABORT;
END_IF
10:
// Reset move stop
20:
_uCtrl.stCtrl.bConfMess := 1;
_tonTimeout.IN := TRUE;
// Wait for errors to be reset
IF (NOT _uState.stState.bStopMess) THEN
_uCtrl.stCtrl.bConfMess := 0;
_tonTimeout(IN := FALSE);
_iSSM := 20;
_iSSM := 30;
END_IF
// Timeout reset errors
@@ -291,10 +315,9 @@ CASE _iSSM OF
_eCmd := E_PackMLCmd.ABORT;
END_IF
20:
// Start main program
// Start program
30:
_uCtrl.stCtrl.bExtStart := 1;
_tonTimeout.IN := TRUE;
IF _tonTimeout.Q THEN
@@ -312,7 +335,7 @@ END_CASE]]></ST>
</Implementation>
</Method>
<Method Name="M_Starting" Id="{011f85d8-1225-4288-876f-918df6e4f235}">
<Declaration><![CDATA[METHOD M_Starting
<Declaration><![CDATA[METHOD PROTECTED M_Starting
VAR_INST
_tonTimeout : TON;
END_VAR]]></Declaration>
@@ -413,10 +436,10 @@ END_CASE
</Implementation>
</Method>
<Method Name="M_Stopped" Id="{50813767-4bd7-4147-b5dc-1bbd18ae1555}">
<Declaration><![CDATA[METHOD M_Stopped
<Declaration><![CDATA[METHOD PROTECTED M_Stopped
]]></Declaration>
<Implementation>
<ST><![CDATA[_uCtrl.stCtrl.bConfMess := 0;
<ST><![CDATA[// _uCtrl.stCtrl.bConfMess := 0;
_uCtrl.stCtrl.bEnableAxes := 0;
_uCtrl.stCtrl.bNotDisableAxes := 1;
_uCtrl.stCtrl.bExtStart := 0;
@@ -426,28 +449,89 @@ _ePlcJob := E_KukaRobot_JobNumerPLC.NO_JOB;]]></ST>
</Implementation>
</Method>
<Method Name="M_Suspended" Id="{c2db015c-1cd0-491a-8ce6-6c0bffba7631}">
<Declaration><![CDATA[METHOD M_Suspended
<Declaration><![CDATA[METHOD PROTECTED M_Suspended
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_Suspending" Id="{5b0e5227-d5bb-40c6-a1b8-8e81b852b9b9}">
<Declaration><![CDATA[METHOD M_Suspending
<Declaration><![CDATA[METHOD PROTECTED M_Suspending
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_Unholding" Id="{786f4949-9630-4ace-9e30-65bea4e87cb2}">
<Declaration><![CDATA[METHOD M_Unholding
]]></Declaration>
<Declaration><![CDATA[METHOD PROTECTED M_Unholding
VAR_INST
_tonTimeout : TON;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
<ST><![CDATA[_tonTimeout(PT := T#10S);
CASE _iSSM OF
0:
_uCtrl.stCtrl.bEnableMove := 1;
_uCtrl.stCtrl.bEnableAxes := 1;
_tonTimeout.IN := TRUE;
// Wait for drives to be ready
IF _uState.stState.bPeriRdy THEN
_uCtrl.stCtrl.bEnableAxes := 0;
_tonTimeout(IN := FALSE);
_iSSM := 10;
END_IF
// Timeout drives ready
IF _tonTimeout.Q THEN
_uCtrl.stCtrl.bEnableAxes := 0;
_fbAlarmDrivesEnableTimeout.xRelease := TRUE;
_tonTimeout(IN := FALSE);
_eCmd := E_PackMLCmd.ABORT;
END_IF
10:
_uCtrl.stCtrl.bConfMess := 1;
_tonTimeout.IN := TRUE;
// Wait for errors to be reset
IF (NOT _uState.stState.bStopMess) THEN
_uCtrl.stCtrl.bConfMess := 0;
_tonTimeout(IN := FALSE);
_iSSM := 20;
END_IF
// Timeout reset errors
IF _tonTimeout.Q THEN
_fbAlarmRobotErrorResetTimeout.xRelease := TRUE;
_tonTimeout(IN := FALSE);
_eCmd := E_PackMLCmd.ABORT;
END_IF
20:
// Start main program
_uCtrl.stCtrl.bExtStart := 1;
_tonTimeout.IN := TRUE;
IF _tonTimeout.Q THEN
_tonTimeout(IN := FALSE);
_eCmd := E_PackMLCmd.ABORT;
END_IF
IF _uState.stState.bProAct THEN
_uCtrl.stCtrl.bExtStart := 0;
_tonTimeout(IN := FALSE);
M_StateComplete();
END_IF
END_CASE]]></ST>
</Implementation>
</Method>
<Method Name="M_Unsuspending" Id="{d7ce33fd-cd94-44f1-9289-25a3ab3829eb}">
<Declaration><![CDATA[METHOD M_Unsuspending
<Declaration><![CDATA[METHOD PROTECTED M_Unsuspending
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>

View File

@@ -0,0 +1,376 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<POU Name="FB_TFProtocol" Id="{f0c44f0b-70b8-45d0-8720-9bd7e08b6aa6}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_TFProtocol
VAR_INPUT
sIpAddr : STRING;
udiPort : UDINT;
xConfirmAlarms : BOOL;
END_VAR
VAR_OUTPUT
xConnected : BOOL;
xNewResponseReady : BOOL;
xBusy : BOOL;
xError : BOOL;
END_VAR
VAR
// Connection settings
_fbTcpConnection : FB_ClientServerConnection;
_sIpAddr : STRING;
_udiPort : UDINT;
_hSocket : T_HSOCKET;
_xConnect : BOOL := TRUE;
_xConnected : BOOL;
// Socket send
_fbSocketSend : FB_SocketSend;
_timSendTimeout : TIME := T#5S;
// Socket receive
_fbSocketReceive : FB_SocketReceive;
_timReceiveTimeout : TIME := T#5S;
_abReceivedBuffer : ARRAY[0..100] OF BYTE;
_sReceivedResponse : STRING;
_udiCounterReceive : UDINT;
_udiReceivedBytes : UDINT;
_timPollingTime : TIME := T#50MS;
_tonPollTimer : TON;
_xEnableReceiveTimeout : BOOL;
_timReceiveTimeoutTime : TIME := T#500MS;
_tonReceiveTimeout : TON;
_uiLastReceivedResponseId : UINT := 0;
// Receive state machine
_iStateReceive : INT;
// Command data
_uiCmdId : UINT := 1;
_sCmd : STRING(255);
_sAck : STRING(255);
// Main state machine
_iState : INT := 0;
_diCounter : DINT;
_xSendCmd : BOOL;
_uiRetries : UINT;
_xCmdReceived : BOOL;
_iPlaceCmdSeperator : INT;
_sTmp : STRING;
_xReceivedResponseOk : BOOL;
_uiReceivedCommandId : UINT;
// Buffer before output
_xBusy : BOOL;
_xError : BOOL;
END_VAR
VAR CONSTANT
MAX_RETRIES : UINT := 3;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// Call client server connection fb
_fbTcpConnection(
sSrvNetID:= '',
nMode:= ,
sRemoteHost:= sIpAddr,
nRemotePort:= udiPort,
bEnable:= _xConnect,
tReconnect:= T#2S,
bBusy=> ,
bError=> ,
nErrId=> ,
hSocket=> _hSocket,
eState=> );
// Get connected state
_xConnected := (_fbTcpConnection.eState = E_SocketConnectionState.eSOCKET_CONNECTED);
// Receive timeout after sending a command
_tonReceiveTimeout(IN := _xEnableReceiveTimeout, PT := _timReceiveTimeoutTime);
// Receive state machine
CASE _iStateReceive OF
// Main socket not connected
0:
IF _xConnected THEN
_iStateReceive := 10;
END_IF
// Call receive
10:
_fbSocketReceive(
sSrvNetId:= '',
hSocket:= _hSocket,
cbLen:= SIZEOF(_abReceivedBuffer) - _udiReceivedBytes,
pDest:= ADR(_abReceivedBuffer) + _udiReceivedBytes,
bExecute:= TRUE,
tTimeout:= _timReceiveTimeout,
bBusy=> ,
bError=> ,
nErrId=> ,
nRecBytes=> );
IF (NOT _fbSocketReceive.bBusy) AND (NOT _fbSocketReceive.bError) THEN
_fbSocketReceive(bExecute := FALSE);
IF _fbSocketReceive.nRecBytes > 0 THEN
_udiReceivedBytes := _udiReceivedBytes + _fbSocketReceive.nRecBytes;
_iStateReceive := 20;
ELSE
_iStateReceive := 15;
END_IF
END_IF
// If we have an error, check if we are connected
IF _fbSocketReceive.bError THEN
_fbSocketReceive(bExecute := FALSE);
_iStateReceive := 0;
END_IF
// Wait some time before rechecking
15:
_tonPollTimer(IN := TRUE, PT := _timPollingTime);
IF _tonPollTimer.Q THEN
_tonPollTimer(IN := FALSE);
_iStateReceive := 10;
END_IF
// Check if we are still connected
IF (NOT _xConnected) THEN
_tonPollTimer(IN := FALSE);
_sReceivedResponse := '';
_iStateReceive := 0;
END_IF
// Check received data
20:
// Check if received command is complete
MEMCPY(destAddr := ADR(_sReceivedResponse), srcAddr := ADR(_abReceivedBuffer), n := _udiReceivedBytes);
_udiReceivedBytes := 0;
//_xCmdReceived := TRUE;
// Go back to polling wait state
_iStateReceive := 15;
END_CASE
CASE _iState OF
// Wait for active connection to tray feeder
0:
IF _xConnected THEN
_iState := 10;
END_IF
// Connected and idle
10:
// Got to disconnected state if connection is lost
IF (NOT _xConnected) THEN
_iState := 0;
END_IF
IF _xSendCmd THEN
_xSendCmd := FALSE;
_xBusy := TRUE;
_iState := 20;
END_IF
// Check if we received a response without sending a command
// IF _xCmdReceived THEN
// _iState := 50;
// END_IF
// Send command
20:
_fbSocketSend(
sSrvNetId:= '',
hSocket:= _hSocket,
cbLen:= SIZEOF(_sCmd),
pSrc:= ADR(_sCmd),
bExecute:= TRUE,
tTimeout:= _timSendTimeout,
bBusy=> ,
bError=> ,
nErrId=> );
IF (NOT _fbSocketSend.bBusy) AND (NOT _fbSocketSend.bError) THEN
_fbSocketSend(bExecute := FALSE);
//_xEnableReceiveTimeout := TRUE;
//_iState := 30;
END_IF
IF _fbSocketSend.bError THEN
_fbSocketSend(bExecute := FALSE);
_iState := 90;
END_IF
// Wait for response
30:
// Received a response
IF _xCmdReceived THEN
_xCmdReceived := FALSE;
_xEnableReceiveTimeout := FALSE;
_uiRetries := 0;
_iState := 40;
END_IF
// Didnt receive command ack in time
// So resend the command if max retries are not reached
IF _tonReceiveTimeout.Q THEN
_xEnableReceiveTimeout := FALSE;
_uiRetries := _uiRetries + 1;
// Check if we reached the max number of retries
IF _uiRetries > MAX_RETRIES THEN
_iState := 90;
ELSE
// Retry by sendind command again
_iState := 20;
END_IF
END_IF
// Check response
40:
// Check for cmd id
IF (TO_STRING(_sReceivedResponse[0]) <> UINT_TO_STRING(_uiCmdId)) THEN
// Wrong command id received
_iState := 90;
END_IF
// For for response indicator
IF _sReceivedResponse[1] <> F_ToASC('<') THEN
// Wrong response indicator
_iState := 90;
END_IF
// Check for correct cmd
_xReceivedResponseOk := TRUE;
FOR _diCounter := 2 TO (LEN(_sReceivedResponse) - 1) DO
IF _sReceivedResponse[_diCounter] = F_ToASC(':') THEN
EXIT;
ELSIF _sReceivedResponse[_diCounter] <> _sCmd[_diCounter] THEN
_xReceivedResponseOk := FALSE;
EXIT;
END_IF
END_FOR
IF _xReceivedResponseOk THEN
_iState := 10;
ELSE
_iState := 90;
END_IF
50:
// Get command id
_uiReceivedCommandId := STRING_TO_UINT(TO_STRING(_sReceivedResponse[0]));
// Check if it is a new command
IF (_uiReceivedCommandId <> _uiLastReceivedResponseId) OR (_uiReceivedCommandId = 0) THEN
_uiLastReceivedResponseId := _uiReceivedCommandId;
xNewResponseReady := TRUE;
// Send acknowledgement
_iState := 60;
END_IF
// Prepare ack response
60:
_sAck := CONCAT(UINT_TO_STRING(_uiLastReceivedResponseId), '<');
FOR _diCounter := 2 TO (LEN(_sReceivedResponse) - 1) DO
IF _sReceivedResponse[_diCounter] <> F_ToASC(':') THEN
_sAck[_diCounter] := _sReceivedResponse[_diCounter];
ELSE
_sAck[_diCounter] := F_ToASC('\0');
EXIT;
END_IF
END_FOR
_iState := 70;
// Send ack response
70:
_fbSocketSend(
sSrvNetId:= '',
hSocket:= _hSocket,
cbLen:= SIZEOF(_sAck),
pSrc:= ADR(_sAck),
bExecute:= TRUE,
tTimeout:= _timSendTimeout,
bBusy=> ,
bError=> ,
nErrId=> );
IF (NOT _fbSocketSend.bBusy) AND (NOT _fbSocketSend.bError) THEN
_fbSocketSend(bExecute := FALSE);
_xEnableReceiveTimeout := TRUE;
_iState := 10;
END_IF
IF _fbSocketSend.bError THEN
_fbSocketSend(bExecute := FALSE);
_iState := 90;
END_IF
// Error
90:
_xError := TRUE;
_xBusy := FALSE;
IF xConfirmAlarms THEN
_xError := FALSE;
_iState := 0;
END_IF
END_CASE
// Copy output buffers to outputs
xConnected := _xConnected;
xBusy := _xBusy;
xError := _xError;]]></ST>
</Implementation>
<Method Name="M_GetResponse" Id="{48f8719d-7ed0-4fb1-824a-0bf475fcfc2c}">
<Declaration><![CDATA[METHOD M_GetResponse : STRING
VAR
_sTmp : STRING(255);
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[xNewResponseReady := FALSE;
MEMCPY(destAddr := ADR(_sTmp), ADR(_sReceivedResponse) + 2, n := INT_TO_UDINT(LEN(_sReceivedResponse) - 2));
M_GetResponse := _sTmp;]]></ST>
</Implementation>
</Method>
<Method Name="M_SendCmd" Id="{d00a8c1a-c183-4659-9c9e-be5b30566b7c}">
<Declaration><![CDATA[METHOD M_SendCmd : BOOL
VAR_INPUT
sCmd : STRING(80);
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// Check if we are already sending a command
IF _xBusy OR _xError THEN
M_SendCmd := FALSE;
RETURN;
END_IF
// Increment command id
_uiCmdId := _uiCmdId + 1;
// Overflows at 9 and is reset to 1
IF _uiCmdId > 9 THEN
_uiCmdId := 1;
END_IF
// Create command with id
_sCmd := CONCAT(UINT_TO_STRING(_uiCmdId), '>');
_sCmd := CONCAT(_sCmd, sCmd);
// start sendind command state machine
_xSendCmd := TRUE;
M_SendCmd := TRUE;]]></ST>
</Implementation>
</Method>
</POU>
</TcPlcObject>

View File

@@ -1,38 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<POU Name="FB_TrayFeeder" Id="{e2e3e993-37de-42b1-80e1-7dba99a66e94}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FINAL FB_TrayFeeder EXTENDS FB_Isa88_SM
<Declaration><![CDATA[FUNCTION_BLOCK FINAL FB_TrayFeeder EXTENDS FB_PackMLGeneric
VAR_INPUT
xConfirmAlarms : BOOL;
END_VAR
VAR_OUTPUT
END_VAR
VAR
_fbTcpConnection : FB_ClientServerConnection;
_sIpAddr : STRING;
_udiPort : UDINT;
_fbProtocolHandler : FB_TFProtocol;
_xTest : BOOL;
_xSendResult : BOOL;
_sCmd : STRING := 'STAT-FEED:';
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// Call client server connection fb
_fbTcpConnection(
sSrvNetID:= '',
nMode:= ,
sRemoteHost:= _sIpAddr,
nRemotePort:= ,
bEnable:= ,
tReconnect:= ,
bBusy=> ,
bError=> ,
nErrId=> ,
hSocket=> ,
eState=> );
<ST><![CDATA[// IPs
// 192.168.1.10
// 192.168.1.11
_fbProtocolHandler(
sIpAddr:= _sIpAddr,
udiPort:= _udiPort,
xConfirmAlarms:= xConfirmAlarms,
xConnected=> ,
xNewResponseReady=> ,
xBusy=> ,
xError=> );
IF _xTest THEN
_xTest := FALSE;
_xSendResult := _fbProtocolHandler.M_SendCmd(sCmd := _sCmd);
END_IF
// Call isa88 base state machine
SUPER^();
// IPs
// 192.168.1.10
// 192.168.1.11]]></ST>
SUPER^();]]></ST>
</Implementation>
<Method Name="FB_init" Id="{6c7048d9-3836-4289-b5f3-f8878267494f}">
<Declaration><![CDATA[//FB_Init ist immer implizit verfügbar und wird primär für die Initialisierung verwendet.
@@ -48,8 +54,17 @@ sIPAddr : STRING;
udiPort : UDINT;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[_sIpAddr := sIPAddr;
_udiPort := udiPort;]]></ST>
<ST><![CDATA[// Save connection settings
_sIpAddr := sIPAddr;
_udiPort := udiPort;
// Config state machine
_stSMConfig.xStoppingDisabled := TRUE;
_stSMConfig.xCompletingDisabled := TRUE;
_stSMConfig.xCompletedDisabled := TRUE;
_stSMConfig.xAbortingDisabled := TRUE;]]></ST>
</Implementation>
</Method>
</POU>