Files
infineon_legacy_plc/PLC/1 Cassette/POUs/CASSETTE_MAIN_FB.TcPOU
2026-01-08 11:08:17 +01:00

1118 lines
29 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4026.13">
<POU Name="CASSETTE_MAIN_FB" Id="{f460b72b-ceae-4e52-9063-58e9c5ed7ce4}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK CASSETTE_MAIN_FB EXTENDS Station_GENERAL_MAIN_FB IMPLEMENTS I_STATION_CMD_CALL
VAR_OUTPUT
NIO_InProduction : BOOL;
NIO_InUnload : BOOL;
END_VAR
VAR
Config : sCassetteConfig;
ConfigOld : sCassetteConfig;
Recipe : sCassetteRecipe;
RecipeLoad : sCassetteRecipe;
RecipeDummy : sCassetteRecipe;
RecipeRead : sCassetteRecipe;
Processes : ARRAY [1..MaxNumberOfProcesses] OF sProcess;
NoAlternative : BOOL;
CurrentTime : DT;
ProcessCounter : USINT;
IO : CASSETTE_IO_FB;
TrayFeeder : TrayFeeder_FB;
JobID : T_MaxString;
NIO_ToProduction : BOOL;
NIO_ToUnload : BOOL;
EMPTY_CASSETTE_PROCESS : sCassetteProcess;
END_VAR
VAR_INPUT
Signal : sCassetteSignal;
END_VAR
VAR CONSTANT
DoorLockTimeOut : TIME := T#5S;
END_VAR
VAR CONSTANT
MaxNumberOfProcesses : INT := 100;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
<Folder Name="Scheduler" Id="{6247b6bc-9a55-441d-8159-fc99116ed23d}" />
<Method Name="CheckAlternative" Id="{ba576b9c-57b3-4bc9-8717-98058b01424b}" 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="{ad800f96-aace-49ba-ae03-2ed100a43b0a}">
<Declaration><![CDATA[METHOD CloseInOut : BOOL
VAR_INST
i,j,k : INT;
CreateDir : FB_CreateDir;
MAPArray : ARRAY [1..MaxNumberOfSubstratesPerTray] OF BYTE;
StringWithLotID : T_MaxString;
END_VAR
VAR
START_TIME : STRING;
format : STRING := '%0004.0f.%02.0f.%02.0f_%02.0f%02.0f';//%02.0f';
fbFormat : FB_FormatString;
faTime : ARRAY[0..4] OF REAL;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[CASE _Step OF
0:
CASE iCMD OF
CloseInCMD:
CASSETTE_PROCESS[iStation] := EMPTY_CASSETTE_PROCESS;
_Step := 10;
CloseOutCMD:
CloseInOut := TRUE;
END_CASE
10:
IF iStationStatus.Soll.AutoStart THEN
_Step := 30;
ELSE
_Step := 20;
END_IF
20:
IF TrayFeeder.SCAN() THEN
_Step := 100;
END_IF
30:
iStationStatus.RecipeName := RecipeManagement.RecipeList[eRecipeType.TypeProcess].RecipeList[iStationStatus.SellectedRecipeAutomatic];
IF noCMD = RecipeManagement.CMD THEN
RecipeManagement.ProcessRecipeName := iStationStatus.RecipeName;
RecipeManagement.ReadRecipeType := eRecipeType.TypeProcess;
RecipeManagement.CMD := CMDLoadRcpToStation;
_Step := _Step +1;
END_IF
31:
IF noCMD = RecipeManagement.CMD THEN
_Step := _Step +1;
END_IF
32:
FOR i := 1 TO Recipe.STEP_COUNT DO
IF NOT CheckRecipeForFlow(Recipe.DATA[i]) THEN
AlarmSend(iStation:=iStation,MsgId := Cassette_ErrorNr.eRecipeMissing,TRUE, eReportType.Error, sAvailableResponse.Ok, FALSE);
iStationStatus.Soll.Stop := TRUE;
RETURN;
END_IF
END_FOR
_Step := 40;
40:
format := '%0004.0f.%02.0f.%02.0f_%02.0f%02.0f';
faTime[0] := LocalTime.wYear;
faTime[1] := LocalTime.wMonth;
faTime[2] := LocalTime.wDay;
faTime[3] := LocalTime.wHour;
faTime[4] := LocalTime.wMinute;
fbFormat(
sFormat:=format,
arg1:= F_REAL (faTime[0]),
arg2:= F_REAL (faTime[1]),
arg3:= F_REAL (faTime[2]),
arg4:= F_REAL (faTime[3]),
arg5:= F_REAL (faTime[4]),
sOut=> START_TIME
);
Signal.START_TIME := START_TIME;
START_TIME := CONCAT(LOG_MAIN_PATH, START_TIME);
CreateDir(sPathName := START_TIME, bExecute := TRUE);
_Step := _Step +1;
41:
IF CreateDir.bError THEN
_Step := 50;
ELSIF NOT CreateDir.bBusy THEN
_Step := 50;
END_IF
CreateDir(bExecute := FALSE);
50:
IF LEN(Signal.LotID) > 0 THEN
;
ELSE
format := '%02.0f%02.0f';
faTime[0] := LocalTime.wHour;
faTime[1] := LocalTime.wMinute;
fbFormat(
sFormat:=format,
arg1:= F_REAL (faTime[0]),
arg2:= F_REAL (faTime[1]),
sOut=> Signal.LotID
);
END_IF
StringWithLotID := CONCAT(LOG_MAIN_PATH, Signal.START_TIME);
StringWithLotID := CONCAT(StringWithLotID, '/');
StringWithLotID := CONCAT(StringWithLotID, Signal.LotID);
_Step := 60;
60:
CreateDir(sPathName := StringWithLotID, bExecute := TRUE);
_Step := _Step +1;
61:
IF CreateDir.bError THEN
_Step := 100;
ELSIF NOT CreateDir.bBusy THEN
_Step := 100;
END_IF
CreateDir(bExecute := FALSE);
100:
CloseInOut := TRUE;
_Step := 0;
END_CASE
]]></ST>
</Implementation>
</Method>
<Method Name="ExternalControl" Id="{5288186c-6a54-4705-a37c-0814ae0932ef}">
<Declaration><![CDATA[METHOD ExternalControl : BOOL;
VAR_INPUT
JobID : REFERENCE TO T_MaxString;
END_VAR
VAR_OUTPUT
END_VAR
VAR
i : UDINT;
EmptyList : ARRAY[0..100] OF STRING;
END_VAR
VAR_INST
Step : INT;
fbFileOpen : FB_FileOpen;
fbFileClose : FB_FileClose;
fbFileGets : FB_FileGets;
Path : T_MaxString;
hFile : UINT;
JobList : ARRAY[0..100] OF STRING;
Counter : UINT;
Pos : INT;
END_VAR
VAR CONSTANT
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[CASE Step OF
0:
IF LEN(JobID) > 0 THEN
JobList := EmptyList;
Counter := 0;
Path := CONCAT(JOB_MAIN_PATH, JobID);
Path := CONCAT(Path, '.txt');
Step := 10;
END_IF
10:
fbFileOpen(
sPathName := Path,
nMode := FOPEN_MODEREAD,
bExecute := TRUE
);
IF fbFileOpen.bError THEN
Step := 110;
ELSIF fbFileOpen.bBusy THEN
Step := Step +1;
END_IF
11:
IF fbFileOpen.bError THEN
Step := 110;
ELSIF NOT fbFileOpen.bBusy THEN
hFile := fbFileOpen.hFile;
Step := 20;
END_IF
fbFileOpen(bExecute := FALSE);
20:
fbFileGets(
hFile := hFile,
bExecute := TRUE
);
IF fbFileGets.bError THEN
Step := 110;
ELSIF fbFileGets.bBusy THEN
Step := Step +1;
END_IF
21:
IF fbFileGets.bError THEN
Step := 110;
ELSIF fbFileGets.bEOF THEN
Step := 30;
ELSIF NOT fbFileGets.bBusy THEN
JobList[Counter] := fbFileGets.sLine;
Counter := Counter +1;
Step := 20;
END_IF
fbFileGets(bExecute := FALSE);
30:
fbFileClose(
hFile := hFile,
bExecute := TRUE
);
IF fbFileClose.bError THEN
Step := 110;
ELSIF fbFileClose.bBusy THEN
Step := Step +1;
END_IF
31:
IF fbFileClose.bError THEN
Step := 110;
ELSIF NOT fbFileClose.bBusy THEN
Step := 40;
END_IF
fbFileClose(bExecute := FALSE);
40:
FOR i := 0 TO Counter -1 DO
Pos := find(JobList[i], '$N');
IF Pos > 0 THEN
JobList[i] := LEFT(JobList[i], Pos-1);
END_IF
END_FOR
Step := 50;
100:
ExternalControl := TRUE;
Step := 0;
110:
JobID := '';
Step := 0;
END_CASE]]></ST>
</Implementation>
</Method>
<Method Name="GetNumberOfEmptySlotsInNIO" Id="{faaf461a-fe64-4b88-b587-78575080aa2b}">
<Declaration><![CDATA[METHOD GetNumberOfEmptySlotsInNIO : INT
VAR_INPUT
END_VAR
VAR_INST
MaxNumberOfSlots : SINT;
Counter : INT;
END_VAR
VAR
i : INT;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[IF LastSizeFound = 0 THEN
RETURN;
END_IF
MaxNumberOfSlots := ROBOT_MAIN.Config.SubstrateInformation[LastSizeFound].MaxNumber;
Counter := 0;
FOR i := 1 TO MaxNumberOfSlots DO
IF CASSETTE_MAIN[LastCassette].Signal.Wafer[i].WaferStatus = noWafer THEN
Counter := Counter +1;
END_IF
END_FOR
GetNumberOfEmptySlotsInNIO := Counter;]]></ST>
</Implementation>
</Method>
<Method Name="GetNumberOfSubstrateInSystem" Id="{f46af4ec-2528-4f16-9c56-490ab3abacdf}">
<Declaration><![CDATA[METHOD GetNumberOfSubstrateInSystem : INT
VAR_INPUT
END_VAR
VAR
i : INT;
END_VAR
VAR_INST
Counter : INT;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[Counter := 0;
FOR i := FirstSpinner TO RobotStation DO
IF StationsStatus[i].WaferInfo[0].Number > 0 THEN
Counter := Counter +1;
END_IF
IF StationsStatus[i].WaferInfo[1].Number > 0 THEN
Counter := Counter +1;
END_IF
END_FOR
GetNumberOfSubstrateInSystem := Counter;]]></ST>
</Implementation>
</Method>
<Method Name="INIT" Id="{d876a2cf-f771-455d-974a-ad5fbae86a84}">
<Declaration><![CDATA[METHOD INIT : BOOL]]></Declaration>
<Implementation>
<ST><![CDATA[CASE _Step OF
0:
CASE iStation OF
10,11:
_Step := 10;
12:
_Step := 50;
END_CASE
10:
IF TrayFeeder.Init() THEN
_Step := _Step +1;
END_IF
11:
IF TrayFeeder.bOutInitDone THEN
_Step := 100;
END_IF
50:
IF IO.TrayLock[1].Down() AND IO.TrayLock[2].Down() THEN
_Step := 60;
END_IF
60:
IO.DoorLock.UnLock();
_Step := 100;
100:
INIT := TRUE;
_Step := 0;
END_CASE]]></ST>
</Implementation>
</Method>
<Method Name="Initialization" Id="{3140a64e-88cd-42c2-983c-30fb4ca996de}">
<Declaration><![CDATA[METHOD Initialization : BOOL
VAR_INPUT
iStation : INT;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[_VisuName := 'CASSETTE';
InitializationExt(iStation);
RecipeStationName[iStation] := 'Flow';
iStationStatus.NoStopServiceExit := TRUE;
StationsStatus[iStation].ErrorList := 'CASSETTE_ErrorNr';
CASE iStation OF
10:
iStationStatus.StationName := 'Tray Feeder Input';
11:
iStationStatus.StationName := 'Tray Feeder Output';
12:
iStationStatus.StationName := 'Failed Output';
END_CASE
CASE iStation OF
10:
;//iStationStatus.NoPut := TRUE;
11,12:
iStationStatus.NoGet := TRUE;
END_CASE
iStationStatus.RecipeStatus.StepCount REF= CASSETTE_RECIPE_EDITE.STEP_COUNT;
ConfigManagement.Initialization(ADR(Config), ADR(ConfigOld), SIZEOF(Config), 'sCassetteConfig', CONCAT('CASSETTE', StationIndex));
ConfigPlausibility REF= Config.ConfigPlausibility;
RecipeManagement.Initialization(
iStation,
ADR(RecipeLoad),
ADR(CASSETTE_RECIPE_EDITE),
ADR(CASSETTE_RECIPE_EMPTY),
ADR(RecipeRead),
ADR(Recipe),
// ADR(RecipeDummy),
SIZEOF(sCassetteRecipe),
'sCassetteRecipe',
SIZEOF(sCassetteStepData)
);
IO.Initialization(iStation);
CASE iStation OF
FirstCassette:
TrayFeeder.Initialization(iStation, '192.168.1.10');
11:
TrayFeeder.Initialization(iStation, '192.168.1.11');
12:
TrayFeeder.PeripherieInitialization(iStation);
END_CASE
TrayFeeder.AllWafer REF= Signal.Wafer;
CASE iStation OF
12:
iMediaArray[eCassetteMedienNamen.NIO_ToProduction].bReferenceControl REF= NIO_ToProduction;
iMediaArray[eCassetteMedienNamen.NIO_ToProduction].ServiceName[0] := 'NIO$NTo Production';
iMediaArray[eCassetteMedienNamen.NIO_ToProduction].InputAvailable := TRUE;
iMediaArray[eCassetteMedienNamen.NIO_ToProduction].NoErrorInput := TRUE;
iMediaArray[eCassetteMedienNamen.NIO_ToUnload].bReferenceControl REF= NIO_ToUnload;
iMediaArray[eCassetteMedienNamen.NIO_ToUnload].ServiceName[0] := 'NIO$NTo Unload';
iMediaArray[eCassetteMedienNamen.NIO_ToUnload].InputAvailable := TRUE;
iMediaArray[eCassetteMedienNamen.NIO_ToUnload].NoErrorInput := TRUE;
END_CASE
]]></ST>
</Implementation>
</Method>
<Method Name="MAIN" Id="{5eca4b0d-19fd-4933-b94b-cb1891d8dbb9}">
<Declaration><![CDATA[METHOD MAIN : BOOL
VAR_INPUT
END_VAR
VAR_INST
i,j,k : INT;
// WaferAvailable : BOOL;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[CASE iStation OF
10:
TrayFeeder();
JOB();
IF bEmpty THEN
FOR i := 1 TO MaxNumberOfWafer DO
CASE Signal.Wafer[i].WaferStatus OF
WaferForProccess:
Signal.Wafer[i].WaferStatus := WaferNotForProccess;
END_CASE
END_FOR
END_IF
11:
TrayFeeder();
12:
NIO();
END_CASE
IO();]]></ST>
</Implementation>
</Method>
<Method Name="MainSlow" Id="{2a174f27-698b-45fb-a471-431e40e92b33}">
<Declaration><![CDATA[METHOD MainSlow : BOOL
VAR_INST
i : INT;
ForLoopFrom : INT;
ForLoopTo : INT;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[CASE iStation OF
10:
ForLoopFrom := 1+ TrayFeeder.TrayNumber*100;
ForLoopTo := 100+ TrayFeeder.TrayNumber*100;
IF bEmpty THEN
FOR i := 1 TO MaxNumberOfWafer DO
CASE Signal.Wafer[i].WaferStatus OF
WaferForProccess:
Signal.Wafer[i].WaferStatus := WaferNotForProccess;
END_CASE
END_FOR
END_IF
11:
ForLoopFrom := 1+ TrayFeeder.TrayNumber*100;
ForLoopTo := 100+ TrayFeeder.TrayNumber*100;
12:
ForLoopFrom := 1;
ForLoopTo := 100;
END_CASE
FOR i := ForLoopFrom TO ForLoopTo DO
CASE Signal.Wafer[i].WaferStatus OF
noWafer:
Signal.Wafer[i].Invisible := TRUE;
WaferNotForProccess:
Signal.Wafer[i].Invisible := FALSE;
Signal.Wafer[i].Color := Color.dGray;
WaferForProccess:
Signal.Wafer[i].Invisible := FALSE;
Signal.Wafer[i].Color := Color.Blue;
WaferInProccess:
Signal.Wafer[i].Invisible := TRUE;
WaferFinish:
Signal.Wafer[i].Invisible := FALSE;
Signal.Wafer[i].Color := Color.dGreen;
WaferDefect:
Signal.Wafer[i].Invisible := FALSE;
Signal.Wafer[i].Color := Color.Red;
END_CASE
END_FOR]]></ST>
</Implementation>
</Method>
<Method Name="NIO" Id="{c27feb50-5c5b-4895-9a19-231efec8dd4b}">
<Declaration><![CDATA[METHOD NIO : BOOL
VAR_INPUT
END_VAR
VAR_INST
Step : INT;
END_VAR
VAR
i : INT;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[IF NIO_ToProduction OR NIO_ToUnload THEN
iMediaArray[eCassetteMedienNamen.NIO_ToProduction].Disable := TRUE;
iMediaArray[eCassetteMedienNamen.NIO_ToUnload].Disable := TRUE;
ELSE
iMediaArray[eCassetteMedienNamen.NIO_ToProduction].Disable := FALSE;
iMediaArray[eCassetteMedienNamen.NIO_ToUnload].Disable := FALSE;
END_IF
IF NOT iStationStatus.Ist.InitDone THEN
iMediaArray[eCassetteMedienNamen.NIO_ToProduction].Disable := TRUE;
iMediaArray[eCassetteMedienNamen.NIO_ToUnload].Disable := TRUE;
NIO_InProduction := FALSE;
NIO_InUnload := FALSE;
END_IF
iMediaArray[eCassetteMedienNamen.NIO_ToProduction].Input := NIO_InProduction;
iMediaArray[eCassetteMedienNamen.NIO_ToUnload].Input := NIO_InUnload;
IF GetNumberOfEmptySlotsInNIO() = 0 AND NIO_InProduction AND LastSizeFound > 0 THEN
NIO_ToUnload := TRUE;
END_IF
CASE Step OF
0:
IF NIO_ToProduction THEN
NIO_InProduction := FALSE;
NIO_InUnload := FALSE;
Step := 10;
END_IF
IF NIO_ToUnload THEN
NIO_InProduction := FALSE;
NIO_InUnload := FALSE;
Step := 50;
END_IF
10:
IF IO.DoorLock.Lock() THEN
Step := 20;
END_IF
20:
IF IO.TrayLock[1].Up() AND IO.TrayLock[2].Up() THEN
NIO_ToProduction := FALSE;
NIO_InProduction := TRUE;
Step := 0;
END_IF
50:
IF IO.TrayLock[1].Down() AND IO.TrayLock[2].Down() THEN
Step := 60;
END_IF
60:
IO.DoorLock.UnLock();
FOR i := 1 TO 50 DO
CASSETTE_MAIN[LastCassette].Signal.Wafer[i].WaferStatus := noWafer;
END_FOR
NIO_ToUnload := FALSE;
NIO_InUnload := TRUE;
Step := 0;
END_CASE]]></ST>
</Implementation>
</Method>
<Method Name="PrepInOut" Id="{aa02ee8f-041a-479b-b7cb-6170838077bd}">
<Declaration><![CDATA[METHOD PrepInOut : BOOL
VAR_INST
i : INT;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[CASE iCMD OF
PrepInCMD:
FOR i := 1 TO MaxNumberOfWafer DO
Signal.Wafer[i].WaferStatus := noWafer;
END_FOR
END_CASE
PrepInOut := TRUE;
]]></ST>
</Implementation>
</Method>
<Method Name="ProcessesBlock" Id="{3a633d9e-7933-4aef-acf1-815399fca58e}" 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 WaferInSystem 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="RCPAddStep" Id="{f7e9d314-020b-4cdd-9fe4-4d67fef8dab5}">
<Declaration><![CDATA[METHOD RCPAddStep : BOOL
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[MEMMOVE(
ADR(CASSETTE_RECIPE_EDITE.DATA[RecipeCurrentStep+1]),
ADR(CASSETTE_RECIPE_EDITE.DATA[RecipeCurrentStep]),
SIZEOF(CASSETTE_RECIPE_EDITE.DATA[RecipeCurrentStep])*(CASSETTE_RECIPE_EDITE.STEP_COUNT-RecipeCurrentStep+1)
);
CASSETTE_RECIPE_EDITE.STEP_COUNT := CASSETTE_RECIPE_EDITE.STEP_COUNT+1;
RecipeCurrentStep := RecipeCurrentStep +1;
CASSETTE_RECIPE_EDITE.DATA[RecipeCurrentStep].StationType := RecipeStationName[TypeHotplate];
CASSETTE_RECIPE_EDITE.DATA[RecipeCurrentStep].RecipeName := '';
CASSETTE_RECIPE_EDITE.DATA[RecipeCurrentStep].Alternative := 16#FFFF;
]]></ST>
</Implementation>
</Method>
<Method Name="RCPStepRemove" Id="{f583dafd-51c1-44cb-bb5b-8aeb2de363e7}">
<Declaration><![CDATA[METHOD RCPStepRemove : BOOL
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[IF CASSETTE_RECIPE_EDITE.STEP_COUNT = (RecipeCurrentStep) THEN
RecipeCurrentStep := RecipeCurrentStep -1;
ELSE
MEMMOVE(
ADR(CASSETTE_RECIPE_EDITE.DATA[RecipeCurrentStep]),
ADR(CASSETTE_RECIPE_EDITE.DATA[RecipeCurrentStep+1]),
SIZEOF(CASSETTE_RECIPE_EDITE.DATA[RecipeCurrentStep])*(CASSETTE_RECIPE_EDITE.STEP_COUNT-RecipeCurrentStep)
);
END_IF
CASSETTE_RECIPE_EDITE.STEP_COUNT := CASSETTE_RECIPE_EDITE.STEP_COUNT-1;]]></ST>
</Implementation>
</Method>
<Method Name="RecipeVisu" Id="{94439e65-1be0-4052-a7cc-d1448d3fb9e1}">
<Declaration><![CDATA[METHOD RecipeVisu : BOOL
VAR_INST
i : INT;
j : INT;
Timer : TON;
Step : INT;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[CurrentStepStationType := RecipeGetStationType(CASSETTE_RECIPE_EDITE.DATA[RecipeCurrentStep].StationType);
CASE Step OF
0:
FOR i := FirstStation TO LastStation DO
CASE StationsStatus[i].StationType OF
noStationType, TypeGeneral,TypeRobot, TypeCassette:
;
ELSE
IF StationsStatus[i].IRecipe.iCMD <> noCMD THEN
RETURN;
END_IF
END_CASE
END_FOR
Step := 10;
10://Find Step Type
FOR i := 0 TO FlowRecipeTypeCounter DO
IF CurrentStepStationType = FlowRecipeTypeFound[i] THEN
CurrentStepRecipeList := StationsStatus[CurrentStepStationType].IRecipe.GetProcessList;
FlowRecipeSelectedTypeIndex := i;
Step := 30;
RETURN;
END_IF
END_FOR
30://Find Step Recipe
IF CASSETTE_RECIPE_EDITE.DATA[RecipeCurrentStep].RecipeName <> '' THEN
FOR j := 1 TO CurrentStepRecipeList.NumberOfRecipe DO
IF CASSETTE_RECIPE_EDITE.DATA[RecipeCurrentStep].RecipeName = CurrentStepRecipeList.RecipeList[j] THEN
FlowRecipeSellectedRecipe := j;
Step := 40;
RETURN;
END_IF
END_FOR
END_IF
FlowRecipeSellectedRecipe := 0;
Step := 40;
40://Find Step Alternative
CurrentStepOld := RecipeCurrentStep;
Timer(IN := TRUE, PT := T#100MS);
IF Timer.Q THEN
Timer(IN := FALSE);
Step := 100;
END_IF
100:
IF CurrentStepOld <> RecipeCurrentStep THEN
Step := 10;
VisuCassetteMaxNumberOfRecipe := 100;
RETURN;
END_IF
VisuCassetteMaxNumberOfRecipe := CurrentStepRecipeList.NumberOfRecipe;
IF CASSETTE_RECIPE_EDITE.DATA[RecipeCurrentStep].Alternative = 0 THEN
CASSETTE_RECIPE_EDITE.DATA[RecipeCurrentStep].Alternative := 2;
END_IF
IF iStationStatus.Soll.RecipeExit THEN
Step := 0;
iStationStatus.Ist.Recipe := FALSE;
iStationStatus.Soll.RecipeExit := FALSE;
RETURN;
END_IF
END_CASE]]></ST>
</Implementation>
</Method>
<Method Name="Start" Id="{7d8cf147-8a64-4113-a2bf-61792c5015dc}">
<Declaration><![CDATA[METHOD Start : BOOL
VAR
DummyTime : TIME;
END_VAR
VAR_INST
i : INT;
j : SINT;
// WaferForProccessTimer : TON;
SavedScheduler : sFullScheduler;
FirstLevelScheduler : sFullScheduler;
SecondLevelScheduler : sFullScheduler;
OldTimeAsDT : DT;
NumberOfJob : INT;
StepCounter : INT;
TargetStation : INT;
AlternativeCounter : INT;
TimeCounter : UDINT;
WaferCounter : INT;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[CASE _Step OF
0:
WaferCounter := 1;
_Step := 10;
10:
IF NOT Safety_PRG.MediaOk THEN
FOR i := 1 TO MaxNumberOfWafer DO
IF Signal.Wafer[i].WaferStatus = WaferInProccess THEN
FOR j := INT_TO_SINT(FirstStation) TO INT_TO_SINT(LastStation) DO
IF NOT StationsStatus[j].Ist.InitDone THEN
IF StationsStatus[j].WaferInfo[0].CassetteNumber = iStation AND StationsStatus[j].WaferInfo[0].Number = i THEN
Signal.Wafer[i].WaferStatus := eWaferStatus.noWafer;
END_IF
END_IF
END_FOR
END_IF
END_FOR
END_IF
IF StationsStatus[RobotStation].Ist.Busy OR SubstrateOnRetry THEN
RETURN;
END_IF
IF GetNumberOfEmptySlotsInNIO() < GetNumberOfSubstrateInSystem() THEN
RETURN;
END_IF
Signal.WaitingForNIO := FALSE;
IF NOT CASSETTE_MAIN[LastCassette].NIO_InProduction THEN
Signal.WaitingForNIO := TRUE;
RETURN;
END_IF
//IF GetNumberOfSubstrateInSystem()
IF Signal.Wafer[WaferCounter].WaferStatus = WaferForProccess THEN
IF OldtimeAsDT <> timeAsDT THEN
_Step := 20;
END_IF
ELSE
WaferCounter := WaferCounter +1;
END_IF
IF WaferCounter > MaxNumberOfWafer OR WaferCounter = 0 OR iCMD <> StartCMD THEN
_Step := 90;
END_IF
20:
ProcessCounter := 0;
CurrentTime := timeAsDT + UDINT_TO_TIME(TimeCounter*1000);
IF TimeCounter > 10 THEN
TimeCounter := 0;
OldtimeAsDT := timeAsDT;
END_IF
TimeCounter := TimeCounter +1;
IF NOT ProcessesBlock() THEN
_Step := 10;
RETURN;
END_IF
_Step := _Step +1;
21:
IF CheckAlternative(NoAlternative => NoAlternative) THEN
IF NoAlternative THEN
_Step := 10;
ELSE
SavedScheduler := Scheduler;
SecondLevelScheduler := Scheduler;
StepCounter := 0;
_Step := 30;
END_IF
END_IF
30:
StepCounter := StepCounter +1;
IF StepCounter > ProcessCounter THEN
_Step := 40;
ELSE
FirstLevelScheduler := SecondLevelScheduler;
_Step := 35;
END_IF
35:
AlternativeCounter := 0;
_Step := _Step +1;
36:
AlternativeCounter := AlternativeCounter +1;
IF AlternativeCounter > Processes[StepCounter].NumberOfAlternative THEN
_Step := 10;
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 := iStation;
SecondLevelScheduler[TargetStation].Job[NumberOfJob].WaferNumber := WaferCounter;
SecondLevelScheduler[TargetStation].NumberOfjob := NumberOfJob +1;
IF CheckReservation(SecondLevelScheduler, TargetStation) THEN
Processes[StepCounter].TargetStation := TargetStation;
FirstLevelScheduler := SecondLevelScheduler;
_Step := 30;
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 := 10;
RETURN;
END_IF
END_IF
END_FOR
IF SchedulerChangeOk(SavedScheduler) THEN
Scheduler := FirstLevelScheduler;
ELSE
_Step := 10;
RETURN;
END_IF
FOR i := 2 TO ProcessCounter BY 2 DO
CASSETTE_PROCESS[iStation][WaferCounter][i/2].TargetStation := Processes[i].TargetStation;
CASSETTE_PROCESS[iStation][WaferCounter][i/2].Recipe := Processes[i].Recipe;
//CASSETTE_PROCESS[iStation].Cassette[WaferCounter].WaferProcess[i/2].Defect := Processes[i].Defect;
CASSETTE_PROCESS[iStation][WaferCounter][i/2].Retry := Processes[i].Retry;
CASSETTE_PROCESS[iStation][WaferCounter][i/2].RetryFlowName := Processes[i].RetryFlowName;
CASSETTE_PROCESS[iStation][WaferCounter][i/2].MaxLaytime := Processes[i].MaxLaytime;
CASSETTE_PROCESS[iStation][WaferCounter][i/2].NumberOfAlternative := Processes[i].NumberOfAlternative;
CASSETTE_PROCESS[iStation][WaferCounter][i/2].Alternative := Processes[i].Alternative;
END_FOR
_Step := _Step +1;
41:
IF StationsStatus[RobotStation].Ist.Busy AND (ROBOT_MAIN.TargetStation <> iStation OR ROBOT_MAIN.TargetSlot <> WaferCounter) THEN
_Step := 45;
RETURN;
END_IF
IF bEmpty THEN
_Step := 45;
RETURN;
END_IF
IF StationsStatus[RobotStation].Ist.Busy AND
ROBOT_MAIN.TargetStation = iStation AND
ROBOT_MAIN.TargetSlot = WaferCounter THEN
_Step := 42;
RETURN;
END_IF
CASE Signal.Wafer[WaferCounter].WaferStatus OF
WaferForProccess:
;
WaferInProccess:
_Step := 0;
WaferNotForProccess, noWafer:
_Step := 45;
END_CASE
42:
CASE Signal.Wafer[WaferCounter].WaferStatus OF
WaferInProccess:
_Step := 0;
noWafer:
_Step := 45;
END_CASE
45:
IF DeleteWaferFromScheduler(iStation, WaferCounter) THEN
_Step := 0;
END_IF
90:
FOR i := 1 TO MaxNumberOfWafer DO
IF Signal.Wafer[i].WaferStatus = WaferInProccess THEN
_Step := 0;
RETURN;
END_IF
END_FOR
_Step := 100;
100:
Signal.LotID := '';
Start := TRUE;
_Step := 0;
END_CASE
]]></ST>
</Implementation>
</Method>
<Method Name="ToVisu" Id="{7e4e924d-1d2a-4558-af9b-801664a49506}">
<Declaration><![CDATA[METHOD ToVisu : BOOL
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[VisuCassetteSignal REF= Signal;
//VISU_AXIS REF= CASSETTE_Axis[iStation];
iStationStatus REF= StationsStatus[iStation];
VisuCMD REF= CMD[iStation];
VisuCassetteConfig REF= Config;
VisuCassetteMain REF= THIS^;
CASE iStation OF
FirstCassette:
CurrentCameraPosition := KeyenceCamera.GetCurrentCameraPosition();
END_CASE
]]></ST>
</Implementation>
</Method>
</POU>
</TcPlcObject>