394 lines
12 KiB
XML
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> |