First bigger step to automation

- Aligned X and Y NC Axis with aligner camera coordination system
- Added robot plc jobs and feedback
- Began Meca500 robot interface
- Changed hotplate control to slow PWM
- PackML statemachine now starts in aborted state
- Fixed StateML start method
This commit is contained in:
2026-02-04 19:31:13 +01:00
parent 677c03d51d
commit c1850f780b
29 changed files with 1249 additions and 374 deletions

View File

@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<POU Name="FB_Aligner" Id="{5be6cab7-2294-48e5-869c-33773329143e}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_Aligner EXTENDS FB_PackMLGeneric
VAR_INPUT
xEnableVacuum : BOOL;
xAlign : BOOL;
xConfirmAlarms : BOOL;
END_VAR
VAR_OUTPUT
xVacuumEnabled : BOOL;
END_VAR
VAR
_fbXAxis : FB_AxisPTP;
_fbYAxis : FB_AxisPTP;
_xEnableVacuum AT %Q* : BOOL := FALSE;
_xDisableVacuum AT %Q* : BOOL := TRUE;
_xVacuumOk AT %I* : BOOL;
_udiXOffset AT %I* : UDINT;
_udiYOffset AT %I* : UDINT;
_rXPosToGo : REAL;
_rYPosToGo : REAL;
_iState : INT := 0;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[_fbXAxis(
xEnable:= TRUE,
xInvertCalibrationCam:= FALSE,
xEnablePositive:= TRUE,
xEnableNegative:= TRUE,
rOverride:= 100.0,
lrVelocity:= 2.5,
lrAcceleration:= 0,
lrDecelleration:= 0,
lrJerk:= 0,
xConfirmAlarms:= xConfirmAlarms,
xEnabled=> ,
xHomed=> ,
lrActPosition=> ,
xIsStopped=> ,
xBusy=> ,
xError=> );
_fbYAxis(
xEnable:= TRUE,
xInvertCalibrationCam:= FALSE,
xEnablePositive:= TRUE,
xEnableNegative:= TRUE,
rOverride:= 100.0,
lrVelocity:= 2.5,
lrAcceleration:= 0,
lrDecelleration:= 0,
lrJerk:= 0,
xConfirmAlarms:= xConfirmAlarms,
xEnabled=> ,
xHomed=> ,
lrActPosition=> ,
xIsStopped=> ,
xBusy=> ,
xError=> );
// Drei mal ausführen damit die Position genau ist
IF xAlign THEN
xAlign := FALSE;
_rXPosToGo := UDINT_TO_REAL(_udiXOffset) * -0.001;
_rYPosToGo := ((UDINT_TO_REAL(_udiYOffset) * 0.001) - 37.5) * -1;
IF (ABS(_rXPosToGo) < 10.0) AND (ABS(_rYPosToGo) < 10.0) AND (NOT _fbXAxis.xError) AND (NOT _fbYAxis.xError) THEN
_fbXAxis.M_MoveRel(lrRelDist := _rXPosToGo);
_fbYAxis.M_MoveRel(lrRelDist := _rYPosToGo);
END_IF
END_IF
// Handle enable disable vacuum command
_xEnableVacuum := xEnableVacuum;
_xDisableVacuum := (NOT xEnableVacuum);
xVacuumEnabled := _xVacuumOk;]]></ST>
</Implementation>
</POU>
</TcPlcObject>

View File

@@ -4,12 +4,17 @@
<Declaration><![CDATA[FUNCTION_BLOCK FB_Etcher EXTENDS FB_PackMLGeneric
VAR_INPUT
xOpenDoor : BOOL;
xEnableVacuum : BOOL;
xOpenChuckClamp : BOOL;
xEjectChuck : BOOL;
xReleaseManualMode : BOOL;
xConfirmAlarms : BOOL;
stHMIInterface : ST_Etcher_HMIInterface;
END_VAR
VAR_OUTPUT
xDoorOpen : BOOL;
xChuckClampOpen : BOOL;
xVacuumEnabled : BOOL;
END_VAR
VAR
_fbValveDoor : FB_Valve('Door');
@@ -18,39 +23,39 @@ VAR
xHasOpenFeedback := TRUE,
timTimeoutOpen := T#5S,
timTimeoutClose := T#5S);
_stDoorHMIInterface : ST_HMI_VALVE_DATA;
_fbClampingLeft : FB_Valve('Clamping left');
_stValveClampingLeftCfg : ST_ValveConfig := (
_fbUnlockLeft : FB_Valve('Clamping left');
_stValveUnlockLeftCfg : 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 := (
_fbUnlockRight : FB_Valve('Clamping right');
_stValveUnlockRightCfg : ST_ValveConfig := (
xHasClosedFeedback := TRUE,
xHasOpenFeedback := TRUE,
timTimeoutOpen := T#5S,
timTimeoutClose := T#5S);
_stClampingRightHMIInterface : ST_HMI_VALVE_DATA;
_fbClampingFront : FB_Valve('Clamping front');
_fbEjectFront : 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 := (
_fbEjectBack : FB_Valve('Clamping back');
_stValveEjectBackCfg : ST_ValveConfig := (
xHasClosedFeedback := TRUE,
xHasOpenFeedback := TRUE,
timTimeoutOpen := T#5S,
timTimeoutClose := T#5S);
_stClampingBackHMIInterface : ST_HMI_VALVE_DATA;
_rtEjectChuckCmd : R_TRIG;
_tpEjectChuck : TP;
@@ -59,6 +64,8 @@ VAR
// Sensors
// =======
_xVacuumOk AT %I* : BOOL;
// Spinner vibration sensor
_xVibrationSensor AT %I* : BOOL;
@@ -66,7 +73,7 @@ VAR
// Actuators
// =========
_xDisableVacuum AT %Q* : BOOL;
END_VAR
]]></Declaration>
<Implementation>
@@ -77,7 +84,9 @@ _fbValveDoor(
stValveConfig:= _stValveDoorCfg,
xReleaseManualMode:= FALSE,
xConfirmAlarms:= xConfirmAlarms,
stHMIInterface:= _stDoorHMIInterface);
stHMIInterface:= stHMIInterface.stDoorHMIInterface);
xDoorOpen := _fbValveDoor.IsOpen;
// Chuck
_rtEjectChuckCmd(CLK := xEjectChuck);
@@ -87,40 +96,45 @@ ELSE
_tpEjectChuck(IN := FALSE);
END_IF
_fbClampingLeft(
_fbUnlockLeft(
xAutomaticOpen:= xOpenChuckClamp,
xReleaseErrors:= TRUE,
stValveConfig:= _stValveClampingLeftCfg,
xReleaseManualMode:= FALSE,
stValveConfig:= _stValveUnlockLeftCfg,
xReleaseManualMode:= xReleaseManualMode,
xConfirmAlarms:= xConfirmAlarms,
stHMIInterface:= _stClampingLeftHMIInterface);
stHMIInterface:= stHMIInterface.stUnlockLeftHMIInterface);
_fbClampingRight(
_fbUnlockRight(
xAutomaticOpen:= xOpenChuckClamp,
xReleaseErrors:= TRUE,
stValveConfig:= _stValveClampingRightCfg,
xReleaseManualMode:= FALSE,
stValveConfig:= _stValveUnlockRightCfg,
xReleaseManualMode:= xReleaseManualMode,
xConfirmAlarms:= xConfirmAlarms,
stHMIInterface:= _stClampingRightHMIInterface);
stHMIInterface:= stHMIInterface.stUnlockRightHMIInterface);
_fbClampingFront(
_fbEjectFront(
xAutomaticOpen:= _tpEjectChuck.Q,
xReleaseErrors:= TRUE,
stValveConfig:= _stValveClampingFrontCfg,
xReleaseManualMode:= FALSE,
xReleaseManualMode:= xReleaseManualMode,
xConfirmAlarms:= xConfirmAlarms,
stHMIInterface:= _stClampingFrontHMIInterface);
stHMIInterface:= stHMIInterface.stEjectFrontHMIInterface);
_fbClampingBack(
_fbEjectBack(
xAutomaticOpen:= _tpEjectChuck.Q,
xReleaseErrors:= TRUE,
stValveConfig:= _stValveClampingBackCfg,
xReleaseManualMode:= FALSE,
stValveConfig:= _stValveEjectBackCfg,
xReleaseManualMode:= xReleaseManualMode,
xConfirmAlarms:= xConfirmAlarms,
stHMIInterface:= _stClampingBackHMIInterface);
stHMIInterface:= stHMIInterface.stEjectBackHMIInterface);
_xDisableVacuum := (NOT xEnableVacuum);
// Call base sm
SUPER^();]]></ST>
SUPER^();
// Copy internal signals to output
xVacuumEnabled := _xVacuumOk;]]></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.

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<DUT Name="ST_Etcher_HMIInterface" Id="{b42cab98-5a22-4703-a464-a4d1f5cdc177}">
<Declaration><![CDATA[TYPE ST_Etcher_HMIInterface :
STRUCT
stDoorHMIInterface : ST_HMI_VALVE_DATA;
stUnlockLeftHMIInterface : ST_HMI_VALVE_DATA;
stUnlockRightHMIInterface : ST_HMI_VALVE_DATA;
stEjectFrontHMIInterface : ST_HMI_VALVE_DATA;
stEjectBackHMIInterface : ST_HMI_VALVE_DATA;
END_STRUCT
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<DUT Name="ST_Meca_JointSet" Id="{11c9caa0-793d-42a4-a6d6-9b5ea59d2923}">
<Declaration><![CDATA[{attribute 'pack_mode' := '1'}
TYPE ST_Meca_JointSet :
STRUCT
rSubIndex001 : REAL;
rSubIndex002 : REAL;
rSubIndex003 : REAL;
rSubIndex004 : REAL;
rSubIndex005 : REAL;
rSubIndex006 : REAL;
END_STRUCT
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<DUT Name="ST_Meca_MotionStatus" Id="{5e335d40-97f1-424a-b3e3-1b2de304decf}">
<Declaration><![CDATA[{attribute 'pack_mode' := '1'}
TYPE ST_Meca_MotionStatus :
STRUCT
uiReachedCheckPointId : UINT;
uiDiscardedCheckpointId : UINT;
uiMoveID : UINT;
uiFIFOSpace : UINT;
bPaused : BIT;
bEOB : BIT;
bEOM : BIT;
bFIFOCleared : BIT;
PStop2 : BIT;
bExcessiveTorque : BIT;
uiOfflineProgramID : UINT;
END_STRUCT
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<DUT Name="ST_Meca_RobotStatus" Id="{2543bfc1-49aa-4184-94d9-b32f02498fcc}">
<Declaration><![CDATA[{attribute 'pack_mode' := '1'}
TYPE ST_Meca_RobotStatus :
STRUCT
bBusy : BIT;
bActivated : BIT;
bHomed : BIT;
bSimActivated : BIT;
bBrakesEngaged : BIT;
bRecoveryMode : BIT;
bEStop : BIT;
bCollisionStatus : BIT;
bWorkZoneStatus : BIT;
uiError : UINT;
END_STRUCT
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<POU Name="FB_Mecademics" Id="{c81cf0ae-3f01-4427-918b-0d3e1c93ae01}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_Mecademics
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</POU>
</TcPlcObject>

View File

@@ -35,6 +35,12 @@ VAR
timWarningLowOn := T#1S,
timHardwareSignalLevelOff := T#1S));
_fbPITempControl : FB_PI;
_xSaturatedUpper : BOOL;
_xSaturatedLower : BOOL;
_rMV : REAL;
_fbPulsOut : TP;
_fbPWMOut : FB_PWM;
END_VAR
]]></Declaration>
<Implementation>
@@ -48,15 +54,43 @@ _fbTempSensor(
xConfirmAlarms:= xConfirmAlarms,
stHMIInterface=> );
_fbPITempControl(
rSP:= rTargetTemp,
rPV:= _fbTempSensor.rScaledValue,
rKp:= 2,
rTn:= 0,
xEnable:= xEnable,
xSaturatedUpper:= _xSaturatedUpper,
xSaturatedLower:= _xSaturatedLower,
rMV=> _rMV);
IF _rMV >= 100.0 THEN
_rMV := 100.0;
_xSaturatedUpper := TRUE;
ELSE
_xSaturatedUpper := FALSE;
END_IF
IF _rMV <=0 THEN
_rMV := 0.0;
_xSaturatedLower := TRUE;
ELSE
_xSaturatedLower := FALSE;
END_IF
_fbPWMOut(
rPWM:= _rMV,
timPeriod:= T#10S,
xOutput=> _xEnableHotplate);
// 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
// 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}">

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<POU Name="FB_PWM" Id="{39ea0d97-8eb7-44fa-b55f-8461b6c6c8ae}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_PWM
VAR_INPUT
rPWM : REAL;
timPeriod : TIME;
END_VAR
VAR_OUTPUT
xOutput : BOOL;
END_VAR
VAR
_tonTimer : TON;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[_tonTimer(IN := TRUE, PT := timPeriod);
IF _tonTimer.Q THEN
_tonTimer(IN := FALSE);
END_IF
IF rPWM = 0.0 THEN
xOutput := FALSE;
ELSIF rPWM >= 100.0 THEN
xOutput := TRUE;
ELSE
IF (1.0 - (TIME_TO_REAL(_tonTimer.ET) / TIME_TO_REAL(timPeriod))) <= (rPWM * 0.01) THEN
xOutput := TRUE;
ELSE
xOutput := FALSE;
END_IF
END_IF]]></ST>
</Implementation>
</POU>
</TcPlcObject>

View File

@@ -15,15 +15,17 @@ TYPE E_KukaRobot_JobNumerPLC :
// Etcher 1 station
ENABLE_VACUUM_ETCHER1 := 20,
DISABLE_VACUUM_ETHER1 := 22,
DISABLE_VACUUM_ETCHER1 := 22,
UNLOCK_CHUCK_ETCHER1 := 60,
LOCK_CHUCK_ETCHER1 := 62,
// Ether 2 station
ENABLE_VACUUM_ETCHER2 := 21,
DISABLE_VACUUM_ETCHER2 := 23,
UNLOCK_CHUCK_ETHCER2 := 61,
LOCK_CHUCK_ETCHER2 := 63
UNLOCK_CHUCK_ETCHER2 := 61,
LOCK_CHUCK_ETCHER2 := 63,
JOB_FAILED := 99
) WORD := NO_JOB;
END_TYPE
]]></Declaration>

View File

@@ -9,11 +9,17 @@ VAR_INPUT
// Feedbacks from other units
// like if a door is open and such things
stUnitFeedbacks : ST_KukaRobot_UnitFeedbacks;
xAckPLCCmd : BOOL;
xPLCJobFailed : BOOL;
xReleaseAlarms : BOOL;
xConfirmAlarms : BOOL;
END_VAR
VAR_OUTPUT
eCmdFromRobot : E_KukaRobot_JobNumerPLC;
xNewCmdRequested : BOOL;
xReady : BOOL;
xError : BOOL;
END_VAR
@@ -43,7 +49,7 @@ VAR
_uState AT %I* : U_KukaRobot_State;
_dwErrorBits AT %I* : DWORD;
_awJobStatesFromRobot AT %I* : ARRAY[0..1] OF WORD;
_dwJobForPLC AT %I* : DWORD;
_eJobForPLC AT %I* : E_KukaRobot_JobNumerPLC;
_abMirrorToolsAndPositions AT %I* : ARRAY[0..3] OF BYTE;
@@ -58,6 +64,8 @@ VAR
_ePlcJob :E_KukaRobot_JobNumerPLC;
_iState : INT;
_xRobotReady : BOOL;
_xError : BOOL;
@@ -97,7 +105,7 @@ _fbAlarmEStopActive(
timOffDelay:= T#0S);
_fbAlarmOperatorSafetyNotOk(
xActive:= (NOT _uState.stState.bUserSAF),
xActive:= (NOT _uState.stState.bUserSAF) AND (_uState.stState.bExt),
xRelease:= TRUE,
xAcknowledge:= xConfirmAlarms,
timOnDelay:= T#0S,
@@ -149,7 +157,12 @@ _uCtrl.stCtrl.bNotDisableAxes := 1;
// Write unit feedbacks outputs
// ============================
_uCtrl.stCtrl.bDoorEtcher1Open := stUnitFeedbacks.xDoorEtcher1Open;
_uCtrl.stCtrl.bDoorEtcher2Open := stUnitFeedbacks.xDoorEtcher2Open;
_uCtrl.stCtrl.bDoorHVTestHotOpen := stUnitFeedbacks.xDoorHVTestHotOpen;
_uCtrl.stCtrl.bDoorHVTestColdOpen := stUnitFeedbacks.xDoorHVTestColdOpen;
M_HandlePLCJobs();
// =================
@@ -217,9 +230,69 @@ END_IF
<Declaration><![CDATA[METHOD PROTECTED M_Execute
]]></Declaration>
<Implementation>
<ST><![CDATA[// Wait for robot to be done
IF _awJobStatesFromRobot[0] = 0 THEN
_eCmd := E_PackMLCmd.COMPLETE;
<ST><![CDATA[CASE stJobParams.eJob OF
E_KukaRobot_JobNumberRobot.WARMUP:
CASE _iSSM OF
0: // Wait for program to end
IF _awJobStatesFromRobot[0] = 0 THEN
IF _asiMotorTemps1To4[3] < 40 THEN
_iSSM := 10;
ELSE
_eCmd := E_PackMLCmd.COMPLETE;
END_IF
END_IF
10: // Write robot number 0
_uJobs.stJobs.wJobNrForRobot := stJobParams.eJob;
IF _awJobStatesFromRobot[0] = _uJobs.stJobs.wJobNrForRobot THEN
_uJobs.stJobs.wJobNrForRobot := E_KukaRobot_JobNumberRobot.NO_JOB;
_iSSM := 0;
END_IF
END_CASE
ELSE
// Wait for robot to be done
IF _awJobStatesFromRobot[0] = 0 THEN
_uJobs.stJobs.wJobNrForRobot := E_KukaRobot_JobNumberRobot.NO_JOB;
_eCmd := E_PackMLCmd.COMPLETE;
END_IF
END_CASE
]]></ST>
</Implementation>
</Method>
<Method Name="M_HandlePLCJobs" Id="{4e3710b4-697b-42e8-86b1-31b19b3023db}">
<Declaration><![CDATA[METHOD M_HandlePLCJobs
VAR_INST
_rtrigNewJob : R_TRIG;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[_rtrigNewJob(CLK := (_eJobForPLC <> E_KukaRobot_JobNumberRobot.NO_JOB));
IF _rtrigNewJob.Q THEN
eCmdFromRobot := _eJobForPLC;
xNewCmdRequested := TRUE;
END_IF
IF xNewCmdRequested AND xAckPLCCmd THEN
xNewCmdRequested := FALSE;
IF (NOT xPLCJobFailed) THEN
_uJobs.stJobs.wFinishedJobNrFromPlc := _eJobForPLC;
ELSE
_uJobs.stJobs.wFinishedJobNrFromPlc := E_KukaRobot_JobNumerPLC.JOB_FAILED;
END_IF
eCmdFromRobot := E_KukaRobot_JobNumberRobot.NO_JOB;
END_IF
// Reset plc job done
IF (_eJobForPLC = E_KukaRobot_JobNumberRobot.NO_JOB)
AND (_uJobs.stJobs.wFinishedJobNrFromPlc <> E_KukaRobot_JobNumberRobot.NO_JOB)
AND (NOT xPLCJobFailed)
THEN
_uJobs.stJobs.wFinishedJobNrFromPlc := E_KukaRobot_JobNumberRobot.NO_JOB;
END_IF]]></ST>
</Implementation>
</Method>
@@ -343,15 +416,20 @@ END_VAR]]></Declaration>
<ST><![CDATA[CASE _iSSM OF
// Check job parameters
0:
IF (_stJobParams.byGripperNumber < 0) OR (_stJobParams.byGripperNumber > 3) // Wrong gripper number
OR (_stJobParams.byChuckNumber < 1) OR (_stJobParams.byChuckNumber > 6) // Wrong chuck number
OR (_stJobParams.byGripperSide < 1) OR (_stJobParams.byGripperSide > 2) // Wrong gripper side
IF (_stJobParams.byGripperNumber < 0) OR (_stJobParams.byGripperNumber > 4) // Wrong gripper number
//OR (_stJobParams.byChuckNumber < 1) OR (_stJobParams.byChuckNumber > 6) // Wrong chuck number
OR (_stJobParams.byGripperSide < 1) OR (_stJobParams.byGripperSide > 6) // Wrong gripper side
THEN
_eCmd := E_PackMLCmd.ABORT;
ELSE
_iSSM := 10;
END_IF
// BLOCKIERE GREIFER TAUSCH, DA AKTUELL KABEL DEFEKT !!!!!
IF _stJobParams.eJob = E_KukaRobot_JobNumberRobot.CHANGE_GRIPPER THEN
_eCmd := E_PackMLCmd.ABORT;;
END_IF
// Transfer job data to robot
10:
// Pos x in um
@@ -364,16 +442,7 @@ END_VAR]]></Declaration>
_diThickness := REAL_TO_DINT(_stJobParams.rThickness * 1000);
// Gripper side
IF _stJobParams.byGripperSide = 1 THEN
_uCtrl.stCtrl.bGripperSide1 := 1;
_uCtrl.stCtrl.bGripperSide2 := 0;
ELSIF _stJobParams.byGripperSide = 2 THEN
_uCtrl.stCtrl.bGripperSide1 := 0;
_uCtrl.stCtrl.bGripperSide2 := 1;
ELSE
_uCtrl.stCtrl.bGripperSide1 := 0;
_uCtrl.stCtrl.bGripperSide2 := 0;
END_IF
_uCtrl.stCtrl.byGripperSide := _stJobParams.byGripperSide;
// Scan QR code
IF stJobParams.xScanQRCode THEN

View File

@@ -38,15 +38,18 @@ STRUCT
bDummy8 : BIT;
bDummy9 : BIT;
bGripperSide1 : BIT;
bGripperSide2 : BIT;
bDummy10 : BIT;
bDummy11 : BIT;
bDummy12 : BIT;
bDoorEtcher1Open : BIT;
bDoorEtcher2Open : BIT;
bDoorHVTestHotOpen : BIT;
bDoorHVTestColdOpen : BIT;
bDummy13: BIT;
byGripperSide : BYTE;
END_STRUCT
END_TYPE
]]></Declaration>

View File

@@ -7,31 +7,31 @@ STRUCT
eJob : E_KukaRobot_JobNumberRobot;
// Position in x in mm
rPosX : REAL;
rPosX : REAL := 78;
// Position in y in mm
rPosY : REAL;
rPosY : REAL := 88;
// Substrate thickness in mm
rThickness : REAL;
rThickness : REAL := 2.7;
// Gripper side (1 or 2)
byGripperSide : BYTE;
byGripperSide : BYTE := 3;
// Scan QR Code during pickup from loading station
xScanQRCode : BOOL;
// Position on hotplate (1-9)
byPlaceOnHotplate : BYTE;
byPlaceOnHotplate : BYTE := 1;
// Position on coolplate (1-9)
byPlaceOnCoolPlate : BYTE;
byPlaceOnCoolPlate : BYTE := 1;
// Gripper tool number (0-3)
byGripperNumber : BYTE;
byGripperNumber : BYTE := 2;
// Chuck for etcher to load (1-6)
byChuckNumber : BYTE;
byChuckNumber : BYTE := 1;
END_STRUCT
END_TYPE
]]></Declaration>

View File

@@ -3,8 +3,8 @@
<DUT Name="ST_KukaRobot_UnitFeedbacks" Id="{d247890a-fdb7-498e-85a5-2423833e65fc}">
<Declaration><![CDATA[TYPE ST_KukaRobot_UnitFeedbacks :
STRUCT
xDoorEthcher1Open : BOOL;
xDoorEther2Open : BOOL;
xDoorEtcher1Open : BOOL;
xDoorEtcher2Open : BOOL;
xDoorHVTestHotOpen : BOOL;
xDoorHVTestColdOpen : BOOL;
END_STRUCT

View File

@@ -32,13 +32,14 @@ VAR
_fbSocketReceive : FB_SocketReceive;
_timReceiveTimeout : TIME := T#5S;
_abReceivedBuffer : ARRAY[0..100] OF BYTE;
_sReceivedResponse : STRING;
_asReceivedResponse : ARRAY[0..9] OF STRING;
_uiBufferPos : UINT;
_udiCounterReceive : UDINT;
_udiReceivedBytes : UDINT;
_timPollingTime : TIME := T#50MS;
_timPollingTime : TIME := T#1S;
_tonPollTimer : TON;
_xEnableReceiveTimeout : BOOL;
_timReceiveTimeoutTime : TIME := T#500MS;
_timReceiveTimeoutTime : TIME := T#5S;
_tonReceiveTimeout : TON;
_uiLastReceivedResponseId : UINT := 0;
@@ -141,194 +142,369 @@ CASE _iStateReceive OF
// Check if we are still connected
IF (NOT _xConnected) THEN
_tonPollTimer(IN := FALSE);
_sReceivedResponse := '';
//_asReceivedResponse[] := '';
_iStateReceive := 0;
END_IF
// Check received data
20:
// Check if received command is complete
MEMCPY(destAddr := ADR(_sReceivedResponse), srcAddr := ADR(_abReceivedBuffer), n := _udiReceivedBytes);
MEMCPY(destAddr := ADR(_asReceivedResponse[_uiBufferPos]), srcAddr := ADR(_abReceivedBuffer), n := _udiReceivedBytes);
_uiBufferPos := _uiBufferPos + 1;
IF _uiBufferPos > 9 THEN
_uiBufferPos := 0;
END_IF
_udiReceivedBytes := 0;
//_xCmdReceived := TRUE;
_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
// 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
// _xCmdReceived := FALSE;
// _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
//
// // 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 := 900;
// END_IF
//
// // For for response indicator
// IF _sReceivedResponse[1] <> F_ToASC('<') THEN
// // Wrong response indicator
// _iState := 901;
// END_IF
//
// // Check for correct cmd
// _xReceivedResponseOk := TRUE;
// FOR _diCounter := 2 TO 10 DO
// IF _sReceivedResponse[_diCounter] <> _sCmd[_diCounter] THEN
// _xReceivedResponseOk := FALSE;
// EXIT;
// END_IF
// END_FOR
//
// IF _xReceivedResponseOk THEN
// _xBusy := FALSE;
// _iState := 10;
// ELSE
// _iState := 902;
// END_IF
//
// 50:
// // Get command id
// _uiReceivedCommandId := _sReceivedResponse[0] - 16#30;
//
// // Check if it is a new command
// IF (_uiReceivedCommandId <> _uiLastReceivedResponseId) OR (_uiReceivedCommandId = 0) THEN
// _uiLastReceivedResponseId := _uiReceivedCommandId;
// xNewResponseReady := FALSE;
//
// // Send acknowledgement
// _iState := 60;
// END_IF
//
// // Prepare ack response
// 60:
// FOR _diCounter := 0 TO 10 DO
// _sAck[_diCounter] := _sReceivedResponse[_diCounter];
// END_FOR
// _sAck[11] := 0;
//
// IF _sReceivedResponse[1] = F_ToAsc('>') THEN
// _iState := 70;
// ELSE
// _iState := 10;
// END_IF
//
//
// // 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;
// _xBusy := FALSE;
// _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;
// _uiRetries := 0;
// _iState := 0;
// END_IF
// END_CASE
// Copy output buffers to outputs
xConnected := _xConnected;
xBusy := _xBusy;
xError := _xError;]]></ST>
</Implementation>
<Method Name="M_Debug" Id="{24e700f8-310e-46c8-98c0-8a10312afeda}">
<Declaration><![CDATA[METHOD M_Debug
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// 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
//
// // 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(_asReceivedResponse[0]) <> UINT_TO_STRING(_uiCmdId)) THEN
// // Wrong command id received
// _iState := 900;
// END_IF
//
// // For for response indicator
// IF _asReceivedResponse[1] <> F_ToASC('<') THEN
// // Wrong response indicator
// _iState := 901;
// END_IF
//
// // Check for correct cmd
// _xReceivedResponseOk := TRUE;
// FOR _diCounter := 2 TO 10 DO
// IF _asReceivedResponse[_diCounter] <> _sCmd[_diCounter] THEN
// _xReceivedResponseOk := FALSE;
// EXIT;
// END_IF
// END_FOR
//
// IF _xReceivedResponseOk THEN
// _xBusy := FALSE;
// _iState := 10;
// ELSE
// _iState := 902;
// END_IF
//
// 50:
// // Get command id
// _uiReceivedCommandId := _asReceivedResponse[0] - 16#30;
//
// // Check if it is a new command
// IF (_uiReceivedCommandId <> _uiLastReceivedResponseId) OR (_uiReceivedCommandId = 0) THEN
// _uiLastReceivedResponseId := _uiReceivedCommandId;
// xNewResponseReady := FALSE;
//
// // Send acknowledgement
// _iState := 60;
// END_IF
//
// // Prepare ack response
// 60:
// FOR _diCounter := 0 TO 10 DO
// _sAck[_diCounter] := _asReceivedResponse[_diCounter];
// END_FOR
// _sAck[11] := 0;
//
// IF _asReceivedResponse[1] = F_ToAsc('>') THEN
// _iState := 70;
// ELSE
// _iState := 10;
// END_IF
//
//
// // 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;
// _xBusy := FALSE;
// _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;
// _uiRetries := 0;
// _iState := 0;
// END_IF
// END_CASE]]></ST>
</Implementation>
</Method>
<Method Name="M_GetResponse" Id="{48f8719d-7ed0-4fb1-824a-0bf475fcfc2c}">
<Declaration><![CDATA[METHOD M_GetResponse : STRING
VAR
@@ -337,7 +513,7 @@ END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[xNewResponseReady := FALSE;
MEMCPY(destAddr := ADR(_sTmp), ADR(_sReceivedResponse) + 2, n := INT_TO_UDINT(LEN(_sReceivedResponse) - 2));
//MEMCPY(destAddr := ADR(_sTmp), ADR(_asReceivedResponse) + 2, n := INT_TO_UDINT(LEN(_asReceivedResponse) - 2));
M_GetResponse := _sTmp;]]></ST>
</Implementation>
</Method>

View File

@@ -15,7 +15,7 @@ VAR
_xTest : BOOL;
_xSendResult : BOOL;
_sCmd : STRING := 'STAT-FEED:';
_sCmd : STRING := 'STAT-FEED';
END_VAR
]]></Declaration>
<Implementation>