1118 lines
29 KiB
XML
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> |