public void MoveFmRobot(FMStage stage, int nSlot, ARM _Arm, FMStatus status, bool bHandFold = false) { //int nSlot = 1; if (bHandFold == true) { FmRobot.MoveWaitFold((int)stage, nSlot, _Arm); } else { switch (stage) { case FMStage.CP1: case FMStage.CP2: case FMStage.CP3: FmRobot.MovePickup((int)stage, nSlot, _Arm); break; case FMStage.AL: FmRobot.MovePlace((int)stage, nSlot, _Arm); break; case FMStage.LPMA: case FMStage.LPMB: case FMStage.LPMC: case FMStage.LPMD: if (status == FMStatus.LPM_LOAD) { FmRobot.MovePickup((int)stage, nSlot, _Arm); } else if (status == FMStatus.LPM_UNLOAD) { FmRobot.MovePlace((int)stage, nSlot, _Arm); } break; } } }
public fn FmRobot_Place_Buffer() { if (!isAcceptRun()) { return(fn.busy); } nPreSeqNo = nSeqNo; FMStage stage = GlobalVariable.manualInfo.mnlStageFM; //매뉴얼에서 선택한 Stage 연결 int nSlot = GlobalVariable.manualInfo.nSelectSource; FmRobot_Arm = (CJ_Controls.Communication.CybogRobot_HTR.ARM)GlobalVariable.manualInfo.SelArmFM; FMStatus fmStatus = FMStatus.BUFFER_UNLOAD; switch (nSeqNo) { case 0: break; case 10: break; case 15: //Door Open Check break; case 20: GlobalSeq.autoRun.prcFM.MoveFmRobot(stage, nSlot, FmRobot_Arm, fmStatus); break; case 30: if (GlobalSeq.autoRun.prcFM.CheckCompl_FM() != fn.success) { return(fn.busy); } break; case 35: GlobalSeq.autoRun.prcFM.MoveFmRobot(stage, nSlot, FmRobot_Arm, fmStatus, true); break; case 40: if (GlobalSeq.autoRun.prcFM.CheckCompl_FM() != fn.success) { return(fn.busy); } break; case 50: nSeqNo = 0; return(fn.success); } //wrong seq check if (nSeqNo > 10000) { //error occur return(fn.err); } nSeqNo++; return(fn.busy); }
public fn FmRobot_Place_LPM() { if (!isAcceptRun()) { return(fn.busy); } nPreSeqNo = nSeqNo; FMStage stage = GlobalVariable.manualInfo.mnlStageFM; //매뉴얼에서 선택한 Stage 연결 int nSlot = GlobalVariable.manualInfo.nSelectSource; FmRobot_Arm = (CJ_Controls.Communication.CybogRobot_HTR.ARM)GlobalVariable.manualInfo.SelArmFM; EFEM Lpm = EFEM.LPMA; FMStatus fmStatus = FMStatus.LPM_UNLOAD; //LPM 구분 switch (stage) { case FMStage.LPMA: Lpm = EFEM.LPMA; break; case FMStage.LPMB: Lpm = EFEM.LPMB; break; case FMStage.LPMC: Lpm = EFEM.LPMC; break; case FMStage.LPMD: Lpm = EFEM.LPMD; break; default: //LPM Index Error return(fn.err); } switch (nSeqNo) { case 0: break; case 10: if (GlobalSeq.autoRun.prcFM.CheckUnload_LPM(Lpm) != fn.success) { return(fn.busy); } break; case 15: //Door Open Check break; case 20: GlobalSeq.autoRun.prcFM.MoveFmRobot(stage, nSlot, FmRobot_Arm, fmStatus); break; case 30: if (GlobalSeq.autoRun.prcFM.CheckCompl_FM() != fn.success) { return(fn.busy); } break; case 35: GlobalSeq.autoRun.prcFM.MoveFmRobot(stage, nSlot, FmRobot_Arm, fmStatus, true); break; case 40: if (GlobalSeq.autoRun.prcFM.CheckCompl_FM() != fn.success) { return(fn.busy); } break; case 50: nSeqNo = 0; return(fn.success); } //wrong seq check if (nSeqNo > 10000) { //error occur return(fn.err); } nSeqNo++; return(fn.busy); }
public void Run() { if (!isAcceptRun()) { return; } if (nSeqNo != nPreSeqNo) { resetCmd(); } nPreSeqNo = nSeqNo; CaseFM seqCase = (CaseFM)nSeqNo; //test int nRetV = 0; alwaysCheck(); switch (seqCase) { case CaseFM.Initialze: break; case CaseFM.Check_Interlock: //임시 테스트, 웨이퍼 2장만 진행하기 위함 //if (nWaferCount >= 2) return; //strLog = seqCase.ToString(); //AddMessage(strLog); break; case CaseFM.Start_LPM_Load: if (bLPM_Load[(int)EFEM.LPMA] && bLPM_Load[(int)EFEM.LPMC]) { //이미 LPM 로드 상태면 진행하지 않는다 nextSeq((int)CaseFM.Check_Status); return; } break; case CaseFM.Move_LPM_Load: if (bLPM_Load[(int)EFEM.LPMA] == false) { //로드 전 Flag 초기화 LpmRoot.InitMappingFlag(EFEM.LPMA); LoadLPM(EFEM.LPMA); } if (bLPM_Load[(int)EFEM.LPMC] == false) { LpmRoot.InitMappingFlag(EFEM.LPMC); LoadLPM(EFEM.LPMC); } Thread.Sleep(500); //Load Delay break; case CaseFM.Compl_LPM_Load: if (CheckLoad_LPM(EFEM.LPMA) != fn.success) { return; } break; case CaseFM.End_LPM_Load: if (CheckLoad_LPM(EFEM.LPMC) != fn.success) { return; } break; case CaseFM.LPM_Mapping_Data: //로드 시 Scan한 Map Data 연결 break; case CaseFM.Check_Status_Load_A: //Status를 체크 할 경우 LPM Alarm이 발생함, //테스트 시 제거 후 진행 함 //LpmRoot.GetStatus(EFEM.LPMA); break; case CaseFM.Compl_Status_Load_A: //if (CheckLoad_LPM(EFEM.LPMA) != fn.success) return; break; case CaseFM.End_Status_Load_A: #if _REAL_MC //LPM Load 후 Mapping Flag가 변경되면 완료 if (LpmRoot.GetMappingComplete(EFEM.LPMA) == false) { return; } if (LpmRoot.GetMappingComplete(EFEM.LPMC) == false) { return; } #endif bLPM_Load[(int)EFEM.LPMA] = true; bLPM_Load[(int)EFEM.LPMC] = true; break; case CaseFM.Check_Status: RUN_MODE RunMode = RecipeMgr.Inst.TempRcp.eRunMode; //현재 레시피 if (RunMode == RUN_MODE.FULL || RunMode == RUN_MODE.ONLY_BOND) { //FULL Mode if (nWaferCount % 2 == 0) { Working_LPM = EFEM.LPMA; efemType = EFEM_TYPE.A_CARRIER; } else { Working_LPM = EFEM.LPMC; efemType = EFEM_TYPE.C_DEVICE; } } else if (RunMode == RUN_MODE.ONLY_LAMI) { //Only Lami 일경우 Carrier 고정 사용 Working_LPM = EFEM.LPMA; efemType = EFEM_TYPE.A_CARRIER; } else { return; } //Next Wafer Slot 유/무 확인 GlobalVariable.WaferInfo.nWaferLoadSlot[(int)Working_LPM] = LpmRoot.GetNextWaferSlot(Working_LPM, LPMStatus.Load, COUNT.MAX_PORT_SLOT); if (GlobalVariable.WaferInfo.nWaferLoadSlot[(int)Working_LPM] < 0) { //Wafer Empty //더이상 투입할 웨이퍼가 없을경우 언로딩 시퀀스로 보낸다 nextSeq((int)CaseFM.Check_Unload_Wafer); return; } break; case CaseFM.Start_FM_Pickup_LPM: //FM 로봇 상태 확인 //FM 로봇 웨이퍼 상태 확인 //웨이퍼 택타임 측정 시작 시간 if (Working_LPM == EFEM.LPMA) { GlobalVariable.seqShared.carrierArray1[GlobalVariable.WaferInfo.nWaferLoadSlot[(int)Working_LPM]].strTotalSt = DateTime.Now.ToString("hh:mm:ss.fff"); } else if (Working_LPM == EFEM.LPMB) { GlobalVariable.seqShared.carrierArray2[GlobalVariable.WaferInfo.nWaferLoadSlot[(int)Working_LPM]].strTotalSt = DateTime.Now.ToString("hh:mm:ss.fff"); } else if (Working_LPM == EFEM.LPMC) { GlobalVariable.seqShared.deviceArray1[GlobalVariable.WaferInfo.nWaferLoadSlot[(int)Working_LPM]].strTotalSt = DateTime.Now.ToString("hh:mm:ss.fff"); } else if (Working_LPM == EFEM.LPMD) { GlobalVariable.seqShared.deviceArray2[GlobalVariable.WaferInfo.nWaferLoadSlot[(int)Working_LPM]].strTotalSt = DateTime.Now.ToString("hh:mm:ss.fff"); } break; case CaseFM.Move_FM_Pickup_LPM: fmStatus = FMStatus.LPM_LOAD; Working_Stage = (FMStage)Working_LPM + 1; //현재 LPM을 작업 할 Stage로 변경 nWorking_Slot = GlobalVariable.WaferInfo.nWaferLoadSlot[(int)Working_LPM] + 1; //현재 작업할 Wafer Slot Working_Arm = ARM.UPPER; MoveFmRobot(Working_Stage, nWorking_Slot, Working_Arm, fmStatus); strLog = string.Format("FmRobot Pickup Move Start -> {0}, {1}, {2}", Working_Stage.ToString(), nWorking_Slot, Working_Arm.ToString()); AddMessage(strLog); break; case CaseFM.Compl_FM_Pickup_LPM: if (CheckCompl_FM() != fn.success) { return; } //nRetV = CheckCompl_FM(); //f(nRetV == err ) strLog = string.Format("FmRobot Pickup Move End -> {0}, {1}, {2}", Working_Stage.ToString(), nWorking_Slot, Working_Arm.ToString()); AddMessage(strLog); break; case CaseFM.End_FM_Pickup_LPM: GlobalSeq.autoRun.prcFM.LpmRoot.SetWaferInfo(Working_LPM, nWorking_Slot - 1, false); //웨이퍼 맵핑 데이터 갱신 GlobalVariable.seqShared.LoadingEfemToFm(efemType, nWorking_Slot - 1, (HAND)Working_Arm); nWaferCount++; break; case CaseFM.Waiting_AL: if (GlobalVariable.seqShared.IsInAligner() || GlobalVariable.interlock.bAlignMoving == true) { //Alinger에 Wafer가 아직 있으면 대기 하도록 하자 return; } break; case CaseFM.Start_FM_Place_AL: break; case CaseFM.Move_FM_Place_AL: fmStatus = FMStatus.BUFFER_LOAD; Working_Stage = FMStage.AL; nWorking_Slot = 1; Working_Arm = ARM.UPPER; MoveFmRobot(Working_Stage, nWorking_Slot, Working_Arm, fmStatus); strLog = string.Format("FmRobot Place Move Start -> {0}, {1}, {2}", Working_Stage.ToString(), nWorking_Slot, Working_Arm.ToString()); AddMessage(strLog); break; case CaseFM.Compl_FM_Place_AL: if (CheckCompl_FM() != fn.success) { return; } strLog = string.Format("FmRobot Place Move End -> {0}, {1}, {2}", Working_Stage.ToString(), nWorking_Slot, Working_Arm.ToString()); AddMessage(strLog); break; case CaseFM.End_FM_Place_AL: GlobalVariable.seqShared.LoadingFmToAligner((HAND)Working_Arm); GlobalVariable.interlock.bAlignMoving = true; //얼라인 동작 break; case CaseFM.Check_Unload_Wafer: //CP에 언로드 할 웨이퍼가 있는지 확인 if (GlobalVariable.seqShared.IsInCP(0) == false) { nextSeq((int)CaseFM.Initialze); return; } break; ////////////////////////////////////// //Wafer Unload ///////////////////////////////////// case CaseFM.Start_FM_Pickup_CP: //CP 웨이퍼 감지 센서 확인 필요! break; case CaseFM.Move_FM_Pickup_CP: fmStatus = FMStatus.BUFFER_UNLOAD; Working_Stage = FMStage.CP1; nWorking_Slot = 1; Working_Arm = ARM.LOWER; //CP에서 언로딩 시에는 LOW ARM 사용하자 MoveFmRobot(Working_Stage, nWorking_Slot, Working_Arm, fmStatus); strLog = string.Format("FmRobot Pickup Move Start -> {0}, {1}, {2}", Working_Stage.ToString(), nWorking_Slot, Working_Arm.ToString()); AddMessage(strLog); break; case CaseFM.Compl_FM_Pickup_CP: if (CheckCompl_FM() != fn.success) { return; } strLog = string.Format("FmRobot Pickup Move End -> {0}, {1}, {2}", Working_Stage.ToString(), nWorking_Slot, Working_Arm.ToString()); AddMessage(strLog); break; case CaseFM.End_FM_Pickup_cp: GlobalVariable.seqShared.LoadingCpToFm(0, (HAND)Working_Arm); break; case CaseFM.Start_FM_Place_LPM: //완료 웨이퍼 언로딩 시 LPM A부터 채워넣자 Working_LPM = EFEM.LPMA; //LPM 상태를 확인하자 if (CheckLoad_LPM(Working_LPM) != fn.success) { //로드 상태가 아니면 에러 return; } //Unload Slot Check //Next Wafer Slot 유/무 확인 GlobalVariable.WaferInfo.nWaferUnloadSlot[(int)Working_LPM] = LpmRoot.GetNextWaferSlot(Working_LPM, LPMStatus.Unload, COUNT.MAX_PORT_SLOT); if (GlobalVariable.WaferInfo.nWaferUnloadSlot[(int)Working_LPM] < 0) { //Wafer Empty return; } break; case CaseFM.Move_FM_Place_LPM: fmStatus = FMStatus.LPM_UNLOAD; Working_Stage = (FMStage)Working_LPM + 1; nWorking_Slot = GlobalVariable.WaferInfo.nWaferUnloadSlot[(int)Working_LPM] + 1; //현재 작업할 Wafer Slot Working_Arm = ARM.LOWER; //CP에서 언로딩 시에는 LOW ARM 사용하자 MoveFmRobot(Working_Stage, nWorking_Slot, Working_Arm, fmStatus); strLog = string.Format("FmRobot Place Move Start -> {0}, {1}, {2}", Working_Stage.ToString(), nWorking_Slot, Working_Arm.ToString()); AddMessage(strLog); break; case CaseFM.Compl_FM_Place_LPM: if (CheckCompl_FM() != fn.success) { return; } strLog = string.Format("FmRobot Place Move End -> {0}, {1}, {2}", Working_Stage.ToString(), nWorking_Slot, Working_Arm.ToString()); AddMessage(strLog); break; case CaseFM.End_FM_Place_LPM: GlobalVariable.seqShared.LoadingFmToEfem(EFEM_TYPE.A_CARRIER, nWorking_Slot - 1, (HAND)Working_Arm); //Wafer Unload 후 Data 변경 GlobalSeq.autoRun.prcFM.LpmRoot.SetUnloadSlot(Working_LPM, nWorking_Slot - 1, true); if (Working_LPM == EFEM.LPMA) { GlobalVariable.seqShared.carrierArray1[GlobalVariable.WaferInfo.nWaferUnloadSlot[(int)Working_LPM]].strTotalEnd = DateTime.Now.ToString("hh:mm:ss.fff"); } else if (Working_LPM == EFEM.LPMB) { GlobalVariable.seqShared.carrierArray2[GlobalVariable.WaferInfo.nWaferUnloadSlot[(int)Working_LPM]].strTotalEnd = DateTime.Now.ToString("hh:mm:ss.fff"); } else if (Working_LPM == EFEM.LPMC) { GlobalVariable.seqShared.deviceArray1[GlobalVariable.WaferInfo.nWaferUnloadSlot[(int)Working_LPM]].strTotalEnd = DateTime.Now.ToString("hh:mm:ss.fff"); } else if (Working_LPM == EFEM.LPMD) { GlobalVariable.seqShared.deviceArray2[GlobalVariable.WaferInfo.nWaferUnloadSlot[(int)Working_LPM]].strTotalEnd = DateTime.Now.ToString("hh:mm:ss.fff"); } nextSeq((int)CaseFM.Initialze); return; /////////////////////////////////// //LPM Unload ////////////////////////////////// case CaseFM.Start_LPM_Unload: break; case CaseFM.Move_LPM_Unload: UnloadLPM(Working_LPM); break; case CaseFM.Check_Status_Unload: LpmRoot.GetStatus(Working_LPM); break; case CaseFM.Compl_LPM_Unload: if (CheckUnload_LPM(Working_LPM) != fn.success) { return; } break; case CaseFM.End_LPM_Unload: //처음 case로 nextSeq((int)CaseFM.Initialze); return; } nSeqNo++; }