Ejemplo n.º 1
0
        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;
                }
            }
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
0
        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++;
        }