Files
infineon_legacy_plc/PLC/5 Relax/POUs/RETRY_MAIN_FB.TcPOU
2026-01-08 11:08:17 +01:00

394 lines
12 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4026.13">
<POU Name="RETRY_MAIN_FB" Id="{deb316fa-00f1-498b-8982-796ab9b4b8f3}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK RETRY_MAIN_FB EXTENDS Station_GENERAL_MAIN_FB
VAR_INPUT
RetryFlowName : T_MaxString;
END_VAR
VAR_OUTPUT
END_VAR
VAR
Recipe : sCassetteRecipe;
RecipeLoad : sCassetteRecipe;
RecipeRead : sCassetteRecipe;
ProcessCounter : USINT;
Processes : ARRAY [1..MaxNumberOfProcesses] OF sProcess;
CurrentTime : DT;
CassetteNumber : INT;
WaferNumber : INT;
SavedScheduler : sFullScheduler;
END_VAR
VAR CONSTANT
MaxNumberOfProcesses : INT := 100;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
<Folder Name="Scheduler" Id="{5f836bb7-6d1d-47d6-983e-32b9efe1e071}" />
<Method Name="CheckAlternative" Id="{847d1c23-a152-443d-82f0-cba1c1fc607b}" FolderPath="Scheduler\">
<Declaration><![CDATA[METHOD CheckAlternative : BOOL
VAR_OUTPUT
NoAlternative : BOOL;
END_VAR
VAR
i,j,k : INT;
TargetStation : INT;
END_VAR
VAR_INST
Step : INT;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[CASE Step OF
0: //Check ready Station
FOR i := 1 TO ProcessCounter DO
FOR j := 1 TO Processes[i].NumberOfAlternative DO
TargetStation := Processes[i].Alternative[j];
CASE StationsStatus[TargetStation].StationType OF
TypeRobot:
;
ELSE
IF OperationMode[TargetStation] = AutomaticMode AND StationsStatus[TargetStation].Ist.InitDone THEN
StationsStatus[TargetStation].Soll.CheckFlowName := Processes[i].Recipe;
StationsStatus[TargetStation].Soll.CheckFlow := TRUE;
StationsStatus[TargetStation].StandbyNotAllowed := TRUE;
//CheckFlowGripperSize[TargetStation] := TrayFeeder.SubstrateGripperSize;
END_IF
END_CASE
END_FOR
END_FOR
Step := 10;
10: //Wait till all Station are Checked
FOR k := FirstStation TO LastStation DO
IF StationsStatus[k].Soll.CheckFlow THEN
RETURN;
END_IF
END_FOR
Step := 20;
20: //Remove unready Station
FOR i := 1 TO ProcessCounter DO
FOR j := 1 TO Processes[i].NumberOfAlternative DO
TargetStation := Processes[i].Alternative[j];
CASE StationsStatus[TargetStation].StationType OF
TypeRobot:
;
ELSE
IF NOT StationsStatus[TargetStation].Ist.ReadyForFlow THEN
Processes[i].Alternative[j] := 0;
END_IF
END_CASE
END_FOR
END_FOR
Step := 30;
30: //Sort Alternative
FOR k := 1 TO ProcessCounter DO
Processes[k] := SortAlternative(Processes[k]);
IF Processes[k].NumberOfAlternative = 0 THEN
NoAlternative := TRUE;
CheckAlternative := TRUE;
Step := 0;
RETURN;
END_IF
END_FOR
Step := 40;
40:
CheckAlternative := TRUE;
Step := 0;
END_CASE
]]></ST>
</Implementation>
</Method>
<Method Name="CloseInOut" Id="{9a2c1df1-32c8-4c19-9779-06f2021fcd3a}">
<Declaration><![CDATA[METHOD CloseInOut : BOOL
]]></Declaration>
<Implementation>
<ST><![CDATA[CASE _Step OF
0:
CASE iCMD OF
CloseInCMD:
IF CMD[FirstStation] = StartCMD THEN
_Step := 10;
ELSE
iStationStatus.Soll.AutoStart := FALSE;
_Step := 100;
END_IF
CloseOutCMD:
_Step := 100;
END_CASE
10:
CassetteNumber := iStationStatus.WaferInfo[0].CassetteNumber;
WaferNumber := iStationStatus.WaferInfo[0].Number;
_Step := _Step +1;
11:
IF DeleteWaferFromScheduler(CassetteNumber, WaferNumber) THEN
_Step := 20;
END_IF
20:
iStationStatus.RecipeName := RetryFlowName;
IF noCMD = RecipeManagement.CMD THEN
RecipeManagement.ProcessRecipeName := iStationStatus.RecipeName;
RecipeManagement.ReadRecipeType := eRecipeType.TypeProcess;
RecipeManagement.CMD := CMDLoadRcpToStation;
_Step := _Step +1;
END_IF
21:
IF noCMD = RecipeManagement.CMD THEN
_Step := 100;
END_IF
100:
_Step := 0;
CloseInOut := TRUE;
END_CASE]]></ST>
</Implementation>
</Method>
<Method Name="FB_Init" Id="{6285961a-ace9-421b-a13a-bc3c048df021}">
<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[_NoConfigFile := TRUE;
_PersistentProductCheck := TRUE;
_VisuName := 'RETRY';
_NoService := TRUE;]]></ST>
</Implementation>
</Method>
<Method Name="Initialization" Id="{ea43bc97-4ca3-4d50-829b-2e399ae3ef7f}">
<Declaration><![CDATA[METHOD Initialization : BOOL
VAR_INPUT
iStation : INT;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[InitializationExt(iStation);
iStationStatus.NoRecipe := TRUE;
iStationStatus.NoOperationMode := TRUE;
iStationStatus.NoProductCheck := TRUE;
iStationStatus.StationName := CONCAT('Retry ', StationIndex);
RecipeStationName[iStation] := 'Flow';
RecipeManagement.Initialization(
iStation,
ADR(RecipeLoad),
ADR(CASSETTE_RECIPE_EDITE),
ADR(CASSETTE_RECIPE_EMPTY),
ADR(RecipeRead),
ADR(Recipe),
SIZEOF(sCassetteRecipe),
'sCassetteRecipe',
SIZEOF(sCassetteStepData)
);]]></ST>
</Implementation>
</Method>
<Method Name="ProcessesBlock" Id="{f9ed0a0a-99f0-4d86-9132-6c68d5626f73}" FolderPath="Scheduler\">
<Declaration><![CDATA[METHOD ProcessesBlock : BOOL;
VAR_INPUT
END_VAR
VAR
i,j : USINT;
DummyTime : TIME;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[ProcessCounter := 0;
FOR i := 1 TO Recipe.STEP_COUNT DO
//Robot Block
ProcessCounter := ProcessCounter +1;
Processes[ProcessCounter].StartTime := CurrentTime;
IF StationsStatus[RecipeGetStationType(Recipe.DATA[i].StationType)].OnlyMoveToStation THEN
CurrentTime := CurrentTime + LINT_TO_TIME(TimeBetweenProcesses*500);
ELSE
CurrentTime := CurrentTime + LINT_TO_TIME(TimeBetweenProcesses*1000);
END_IF
Processes[ProcessCounter].EndTime := CurrentTime;
Processes[ProcessCounter].StationType := TypeRobot;
Processes[ProcessCounter].Alternative[1] := RobotStation;
Processes[ProcessCounter].NumberOfAlternative := 1;
ProcessCounter := ProcessCounter +1;
//
//Process Block
Processes[ProcessCounter].StartTime := CurrentTime;
DummyTime := GetSchedulerStationTime(RecipeGetStationType(Recipe.DATA[i].StationType), Recipe.DATA[i].RecipeName, FALSE);
// IF AND DummyTime = T#60M THEN
// ProcessesBlock := FALSE;
// RETURN;
// END_IF
CurrentTime := CurrentTime + DummyTime;
Processes[ProcessCounter].EndTime := CurrentTime;
Processes[ProcessCounter].Recipe := Recipe.DATA[i].RecipeName;
Processes[ProcessCounter].StationType := RecipeGetStationType(Recipe.DATA[i].StationType);
Processes[ProcessCounter].Alternative := FindAlternativeList(RecipeGetStationType(Recipe.DATA[i].StationType), Recipe.DATA[i].Alternative);
Processes[ProcessCounter].Retry := Recipe.DATA[i].Retry;
// Processes[ProcessCounter].Defect := NOT Recipe.DATA[i].Retry;
Processes[ProcessCounter].RetryFlowName := Recipe.DATA[i].RetryFlowName;
FOR j := 1 TO MaxNumberOfAlternative DO
IF Processes[ProcessCounter].Alternative[j] > 0 THEN
Processes[ProcessCounter].NumberOfAlternative := j;
END_IF
END_FOR
//
END_FOR
//Final Robot Block
ProcessCounter := ProcessCounter +1;
Processes[ProcessCounter].StartTime := CurrentTime;
CurrentTime := CurrentTime + LINT_TO_TIME(TimeBetweenProcesses*1000);
Processes[ProcessCounter].EndTime := CurrentTime;
Processes[ProcessCounter].StationType := TypeRobot;
Processes[ProcessCounter].Alternative[1] := RobotStation;
Processes[ProcessCounter].NumberOfAlternative := 1;
ProcessesBlock := TRUE;]]></ST>
</Implementation>
</Method>
<Method Name="Start" Id="{bfa08185-d4a7-43d8-b8d6-51e46e7e25f8}">
<Declaration><![CDATA[METHOD Start : BOOL
VAR_INST
i : INT;
j : UINT;
FlowStepNumber : UINT;
OldTimeAsDT : DT;
FirstLevelScheduler : sFullScheduler;
SecondLevelScheduler : sFullScheduler;
StepCounter : INT;
NoAlternative : BOOL;
AlternativeCounter : INT;
TargetStation : INT;
NumberOfJob : INT;
RobotHasSubstrate : BOOL;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[RobotHasSubstrate := StationsStatus[RobotStation].WaferInfo[0].Number > 0 OR StationsStatus[RobotStation].WaferInfo[1].Number > 0;
IF StationsStatus[RobotStation].Ist.Busy OR RobotHasSubstrate THEN
IF _Step >= 0 AND _Step < 40 THEN
_Step := 0;
RETURN;
END_IF
END_IF
CASE _Step OF
0:
FOR i := FirstLelaxStation TO LastRelaxStation DO
IF i <> iStation THEN
IF iStationStatus.WaferInfo[0].Number > StationsStatus[i].WaferInfo[0].Number and StationsStatus[i].WaferInfo[0].Number <> 0 THEN
RETURN;
END_IF
END_IF
END_FOR
CurrentTime := timeAsDT;
IF OldtimeAsDT <> timeAsDT THEN
OldtimeAsDT := CurrentTime;
_Step := _Step +1;
END_IF
1:
IF ProcessesBlock() THEN
_Step := 10;
ELSE
_Step := 0;
END_IF
10:
IF CheckAlternative(NoAlternative => NoAlternative) THEN
IF NoAlternative THEN
_Step := 0;
ELSE
SavedScheduler := Scheduler;
SecondLevelScheduler := Scheduler;
StepCounter := 0;
_Step := 20;
END_IF
END_IF
20:
StepCounter := StepCounter +1;
IF StepCounter > ProcessCounter THEN
_Step := 40;
ELSE
FirstLevelScheduler := SecondLevelScheduler;
_Step := 30;
END_IF
30:
AlternativeCounter := 0;
_Step := _Step +1;
31:
AlternativeCounter := AlternativeCounter +1;
IF AlternativeCounter > Processes[StepCounter].NumberOfAlternative THEN
_Step := 0;
RETURN;
END_IF
TargetStation := Processes[StepCounter].Alternative[AlternativeCounter];
NumberOfJob := SecondLevelScheduler[TargetStation].NumberOfjob;
SecondLevelScheduler[TargetStation].Job[NumberOfJob].StartTime := Processes[StepCounter].StartTime;
SecondLevelScheduler[TargetStation].Job[NumberOfJob].EndTime := Processes[StepCounter].EndTime;
SecondLevelScheduler[TargetStation].Job[NumberOfJob].CassetteNumber := CassetteNumber;
SecondLevelScheduler[TargetStation].Job[NumberOfJob].WaferNumber := WaferNumber;
SecondLevelScheduler[TargetStation].NumberOfjob := NumberOfJob +1;
IF CheckReservation(SecondLevelScheduler, TargetStation) THEN
Processes[StepCounter].TargetStation := TargetStation;
FirstLevelScheduler := SecondLevelScheduler;
_Step := 20;
ELSE
SecondLevelScheduler := FirstLevelScheduler;
END_IF
40:
FOR i := FirstStation TO LastStation DO
IF NOT StationsStatus[i].OnlyMoveToStation THEN
IF NOT CheckReservation(FirstLevelScheduler, i) THEN
_Step := 0;
RETURN;
END_IF
END_IF
END_FOR
IF SchedulerChangeOk(SavedScheduler) THEN
Scheduler := FirstLevelScheduler;
ELSE
_Step := 0;
RETURN;
END_IF
FlowStepNumber := iStationStatus.WaferInfo[0].FlowStepNumber;
FOR j := 2 TO ProcessCounter BY 2 DO
CASSETTE_PROCESS[CassetteNumber][WaferNumber][FlowStepNumber+j/2].TargetStation := Processes[j].TargetStation;
CASSETTE_PROCESS[CassetteNumber][WaferNumber][FlowStepNumber+j/2].Recipe := Processes[j].Recipe;
CASSETTE_PROCESS[CassetteNumber][WaferNumber][FlowStepNumber+j/2].Retry := Processes[j].Retry;
CASSETTE_PROCESS[CassetteNumber][WaferNumber][FlowStepNumber+j/2].RetryFlowName := Processes[j].RetryFlowName;
END_FOR
_Step := 90;
90:
Start := TRUE;
_Step := 0;
END_CASE]]></ST>
</Implementation>
</Method>
</POU>
</TcPlcObject>