using SA_LTT.Info.AttenuatorCalInfo; using SA_LTT.Info.RecipeInfo; using SA_LTT.Info.WaferInfo; using SA_LTT.Module; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SA_LTT { public delegate void RecipeExcuteEvent(Recipe recipe); public delegate void ProcessInfoExcuteEvent(ProcessInfo _processInfo, int processInfoIndex); public class Sequence { /* Port Get Pre Aligner Flip Put Align Pre Align Get Chamber Put Melting Chamber Get Pre Aligner Flip Put Align Pre Aligner Flip Get Port Put */ public enum TmcSteps { Wait, StatusCheck, LoadPortMapping, CheckMappingData, ProcessDataCheck, GetLoadPort, CheckGetLoadPort, BeforePutPreAlignerFlip, CheckBeforePutPreAlignerFlip, BeforeGetWaitPreAligner, //GetWait 명령 날려 놓고 Align 진행. (TactTime 감소) BeforeAlign, BeforeAlignWait, BeforeGetPreAligner, CheckBeforeGetPreAligner, AlignHomeStart, ChamberStatusCheck, PutChamber, CheckPutChamber, MeltingWait, // 가공 완료 대기. GetChamber, CheckGetChamber, AlignHomeCheck, AfterPutPreAlignerFlip, CheckAfterPutPreAlignerFlip, AfterGetWaitPreAligner, //GetWait 명령 날려 놓고 Align 진행. (TactTime 감소) AfterAlign, AfterAlignWait, AfterGetPreAligner, CheckAfterGetPreAligner, PutLoadPort, CheckPutLoadPort, End, } public enum PmcSteps { Wait, //Wafer 받기 대기 StatusCheck, BeforeMoveLoadPosition, CheckBeforeLoadPosition, BeforeGateOpen, BeforePinUp, WaferPutWait, //Wafer 받은 후 이동 BeforeVacuumOn, BeforePinDown, BeforeGateClose, Melting, // Manual 가공 -> MoveCenterPosition, CheckCenterPosition, GetRecipeData, // ============================= //===Wafer Align 진행 MoveAlignPosition, CheckAlignPosition, VisionReady, VisionReadyCheck, WaferDetectionReady, WaferDetectionReadyCheck, WaferDetection, WaferDetectionCheck, MoveOffsetPosition, CheckOffsetPositon, //==================== //===전체 가공 영역 다 종료 될때 까지 반복 구간=== GetProcessInfoData, //레시피에 있는 가공 좌표 가져오기 CoordTransform, //가공 좌표를 Scanner, Stage에 맞게 변환 하는 작업. // Todo. Power 측정 기능 넣기.=== Attenuator Set 대신 CalDataAttenuatorSet, // 추후 명칭 변경 CalDataCheckAttenuator, // 추후 명칭 변경 MovePowerMeterPosition, CheckPowerMeterPosition, PowerMeterInitialize, PowerMeterInitializeCheck, LaserOn, MeasurementStart, Measurement, MeasurementEnd, MeasurrmentDataCheck, AttenuatorSet, CheckAttenuator, // ============================ MoveProcessStartPosition, CheckProcessStartPosition, ProcessStart, ProcessRunning, ProcessEnd, //======================================== //가공 종료 AfterMoveLoadPosition, CheckAfterLoadPosition, AfterGateOpen, AfterVacuumOff, AfterPinUp, WaferEmptyWait, PinDown, GateClose, End, //Energy drop check EnergyDropCheckStart, EdcPowerMeterInitialize, EdcPowerMeterInitializeCheck, EdcMoveCenterPosition, EdcCheckCenterPosition, EdcMovePowerMeterPosition, EdcCheckPowerMeterPosition, EdcAttenuatorSet, EdcCheckAttenuator, EdcLaserOn, EdcMeasurementStart, EdcMeasurement, EdcMeasurementLaserOff, EdcMeasurementLaserOffCheck, EdcMeasurementEnd, EdcMeasurementDataCheck, EdcLaserOff, EdcLaserOffCheck, EnergyDropCheckEnd, //Attenuator Cal AttenuatorCalStart, AcPowerMeterInitialize, AcPowerMeterInitializeCheck, AcMoveCenterPosition, AcCheckCenterPosition, AcMovePowerMeterPosition, AcCheckPowerMeterPosition, AcAttenuatorSet, AcCheckAttenuator, AcCoolingTimeWait, AcLaserOn, AcMeasurementStart, AcMeasurement, AcMeasurementLaserOff, AcMeasurementLaserOffCheck, AcMeasurementEnd, AcMeasurementDataCheck, AcLaserOff, AcLaserOffCheck, AttenuatorCalEnd, } private Equipment _equipment; private SequenceTimer _processTimer = new SequenceTimer(); private SequenceTimer _pmcSequenceTimer = new SequenceTimer(); private SequenceTimer _tmcSequenceTimer = new SequenceTimer(); private SequenceTimer _measurementTimer = new SequenceTimer(); private PmcSteps _pmcStep = PmcSteps.Wait; private PmcSteps _pmcStepOld = PmcSteps.Wait; private TmcSteps _tmcStep = TmcSteps.Wait; private TmcSteps _tmcStepOld = TmcSteps.Wait; private List _pauseDisableTmcSteps; private List _pauseDisablePmcSteps; private Recipe _currentRecipe; private ProcessInfo _oldProcessInfo; private ProcessInfo _processInfo; private int _processNum; private double _centerPositionX; private double _centerPositionY; private double _centerPositionT; private double _alignOffsetX; private double _alignOffsetY; private double _alignOffsetT; private double _processStartPositionX; // 가공 시작 X 축 위치 private double _processStartPositionY; // 가공 시작 Y 축 위치 private double _processEndPositionX; // 가공 종료 X축 위치 private double _stageVelocity; // Stage 가공 속도 private float _currentAttenuatorCalAngle; private Info.FoupInfo.Foup currentFoup; private float _setAttenuatorAngle; private int _processNumber; private bool _processStartBit; private bool _processEndBit; private bool _chamberWaferEmptyBit; private int _measurementCount; private int _waferProcessCountAfterMeasurement; private DateTime _lastMeasurementTime = DateTime.Now; private List _attenuatorCalData = new List(); public PmcSteps PmcStep { get { return _pmcStep; } private set { _pmcStep = value; } } public TmcSteps TmcStep { get { return _tmcStep; } private set { _tmcStep = value; } } //가공 시간 TactTime public double ProcessTactTimeSeconds { get { return _processTimer.Seconds; } } public bool IsTmcStepPauseEnable { get { return _pauseDisableTmcSteps.Contains(TmcStep) == false; } } public bool IsPmcStepPauseEnable { get { return _pauseDisablePmcSteps.Contains(PmcStep) == false; } } // Recipe 등록, 이벤트 하나만 등록해서 사용할 것. begin invoke 사용. public event RecipeExcuteEvent RecipeExcuted; // Recipe의 ProcessInfo 등록, 이벤트 하나만 등록해서 사용할 것. begin invoke 사용. public event ProcessInfoExcuteEvent ProcessInfoExcuted; public Sequence(Equipment equipment) { _equipment = equipment; _pauseDisableTmcSteps = new List(); _pauseDisablePmcSteps = new List(); _pauseDisableTmcSteps.Add(TmcSteps.CheckMappingData); _pauseDisableTmcSteps.Add(TmcSteps.CheckGetLoadPort); _pauseDisableTmcSteps.Add(TmcSteps.CheckBeforePutPreAlignerFlip); _pauseDisableTmcSteps.Add(TmcSteps.CheckBeforeGetPreAligner); _pauseDisableTmcSteps.Add(TmcSteps.CheckPutChamber); _pauseDisableTmcSteps.Add(TmcSteps.CheckAfterPutPreAlignerFlip); _pauseDisableTmcSteps.Add(TmcSteps.CheckAfterGetPreAligner); _pauseDisableTmcSteps.Add(TmcSteps.CheckPutLoadPort); _pauseDisableTmcSteps.Add(TmcSteps.End); _pauseDisablePmcSteps.Add(PmcSteps.CheckBeforeLoadPosition); _pauseDisablePmcSteps.Add(PmcSteps.CheckCenterPosition); _pauseDisablePmcSteps.Add(PmcSteps.CheckAttenuator); _pauseDisablePmcSteps.Add(PmcSteps.Measurement); _pauseDisablePmcSteps.Add(PmcSteps.MeasurementEnd); _pauseDisablePmcSteps.Add(PmcSteps.CheckProcessStartPosition); _pauseDisablePmcSteps.Add(PmcSteps.ProcessRunning); _pauseDisablePmcSteps.Add(PmcSteps.ProcessEnd); _pauseDisablePmcSteps.Add(PmcSteps.CheckAfterLoadPosition); _pauseDisablePmcSteps.Add(PmcSteps.AfterPinUp); _pauseDisablePmcSteps.Add(PmcSteps.End); //Energy drop check _pauseDisablePmcSteps.Add(PmcSteps.EdcCheckCenterPosition); _pauseDisablePmcSteps.Add(PmcSteps.EdcCheckPowerMeterPosition); _pauseDisablePmcSteps.Add(PmcSteps.EdcCheckAttenuator); _pauseDisablePmcSteps.Add(PmcSteps.EdcMeasurement); _pauseDisablePmcSteps.Add(PmcSteps.EdcMeasurementEnd); _pauseDisablePmcSteps.Add(PmcSteps.EdcMeasurementLaserOff); _pauseDisablePmcSteps.Add(PmcSteps.EdcMeasurementLaserOffCheck); _pauseDisablePmcSteps.Add(PmcSteps.EdcLaserOff); _pauseDisablePmcSteps.Add(PmcSteps.EdcLaserOffCheck); _pauseDisablePmcSteps.Add(PmcSteps.EnergyDropCheckEnd); //AttenuatorCal _pauseDisablePmcSteps.Add(PmcSteps.AcCheckCenterPosition); _pauseDisablePmcSteps.Add(PmcSteps.AcCheckPowerMeterPosition); _pauseDisablePmcSteps.Add(PmcSteps.AcCheckAttenuator); _pauseDisablePmcSteps.Add(PmcSteps.AcMeasurement); _pauseDisablePmcSteps.Add(PmcSteps.AcMeasurementEnd); _pauseDisablePmcSteps.Add(PmcSteps.AcLaserOff); _pauseDisablePmcSteps.Add(PmcSteps.AcLaserOffCheck); _pauseDisablePmcSteps.Add(PmcSteps.AttenuatorCalEnd); } public void TmcSequence() { if (TmcStep != _tmcStepOld) { EquipmentLogManager.Instance.WriteTmcSequenceLog(TmcStep.ToString()); _tmcStepOld = TmcStep; _tmcSequenceTimer.ReStart(); } switch (TmcStep) { case TmcSteps.Wait: { break; } case TmcSteps.StatusCheck: { if (_equipment.crevis.DigitalInputs[Crevis.DigitalInput.CST_DETECTOR_1] || _equipment.crevis.DigitalInputs[Crevis.DigitalInput.CST_DETECTOR_2]) { if (_equipment.port1Foup.status == Info.FoupInfo.FoupStatus.Ready || _equipment.port1Foup.status == Info.FoupInfo.FoupStatus.Ready) { if (_equipment.port1Foup.status == Info.FoupInfo.FoupStatus.Ready) { EquipmentLogManager.Instance.WriteProcessLog("Foup 1 Process start !!"); currentFoup = _equipment.port1Foup; } else { EquipmentLogManager.Instance.WriteProcessLog("Foup 2 Process start !!"); currentFoup = _equipment.port2Foup; } _processNumber = 0; currentFoup.status = Info.FoupInfo.FoupStatus.Process; TmcStep = TmcSteps.LoadPortMapping; } else { TmcStep = TmcSteps.End; } } else { TmcStep = TmcSteps.End; } break; } case TmcSteps.LoadPortMapping: { if (_equipment.robot.MappingSeq(currentFoup.portNumber)) { EquipmentLogManager.Instance.WriteProcessLog($"Port {currentFoup.portNumber} mapping"); TmcStep = TmcSteps.CheckMappingData; } else { //MappingSeq 내부에 alarm 발생 됨. } break; } case TmcSteps.CheckMappingData: { if (_equipment.robot.IsRunEnable) // Mapping 완료 확인. { if (_equipment.robot.IsMappingError) { EquipmentLogManager.Instance.WriteProcessLog($"Mapping {currentFoup.portNumber} Error Restart."); TmcStep = TmcSteps.LoadPortMapping; } else { TmcStep = TmcSteps.ProcessDataCheck; } } break; } case TmcSteps.ProcessDataCheck: { for (; _processNumber < 25; _processNumber++) { if (currentFoup.foupRecipe.RecipeNames[_processNumber] != null) { if (currentFoup.portNumber == 1) { if (_equipment.waferInfoManager.GetWaferInfo(Info.WaferInfo.WaferInfoManager.WaferNumbers.A1 + _processNumber).IsStatus == Info.WaferInfo.WaferInfo.WaferStatus.Exist) { break; } } else { if (_equipment.waferInfoManager.GetWaferInfo(Info.WaferInfo.WaferInfoManager.WaferNumbers.B1 + _processNumber).IsStatus == Info.WaferInfo.WaferInfo.WaferStatus.Exist) { break; } } } } if(_equipment.IsRunStop) // 마지막 웨이퍼 끝난 후 종료. { currentFoup.status = Info.FoupInfo.FoupStatus.Complete; TmcStep = TmcSteps.End; } else { if (_processNumber == 25) { currentFoup.status = Info.FoupInfo.FoupStatus.Complete; TmcStep = TmcSteps.StatusCheck; } else { if(PmcStep == PmcSteps.Wait) { PmcStep = PmcSteps.StatusCheck; } TmcStep = TmcSteps.GetLoadPort; } } break; } case TmcSteps.GetLoadPort: { if (currentFoup.portNumber == 1) { if (_equipment.robot.Get(Robot.StageList.Port1, _processNumber + 1)) { EquipmentLogManager.Instance.WriteProcessLog($"Get port : {currentFoup.portNumber} lot {_processNumber + 1}"); TmcStep = TmcSteps.CheckGetLoadPort; } else { //Get 내부에 alarm 발생 됨. } } else { if (_equipment.robot.Get(Robot.StageList.Port2, _processNumber + 1)) { EquipmentLogManager.Instance.WriteProcessLog($"Get port : {currentFoup.portNumber} lot {_processNumber + 1}"); TmcStep = TmcSteps.CheckGetLoadPort; } else { //Get 내부에 alarm 발생 됨. } } break; } case TmcSteps.CheckGetLoadPort: { if (_equipment.robot.IsRunEnable) { if (_equipment.robot.IsWaferExist) { TmcStep = TmcSteps.BeforePutPreAlignerFlip; } else { _equipment.alarmManager.Occur(AlarmCode.AL_0074_ROBOT_HAS_NOT_WAFER); TmcStep = TmcSteps.GetLoadPort; } } break; } case TmcSteps.BeforePutPreAlignerFlip: { if (_equipment.robot.Put(Robot.StageList.AlignFlip)) { EquipmentLogManager.Instance.WriteProcessLog($"Put align flip"); TmcStep = TmcSteps.CheckBeforePutPreAlignerFlip; } else { //Put 내부에 alarm 발생 됨. } break; } case TmcSteps.CheckBeforePutPreAlignerFlip: { if (_equipment.robot.IsRunEnable) { if (_equipment.robot.IsWaferExist == false) { TmcStep = TmcSteps.BeforeGetWaitPreAligner; } else { _equipment.alarmManager.Occur(AlarmCode.AL_0077_ROBOT_HAS_WAFER); } } break; } case TmcSteps.BeforeGetWaitPreAligner: { if (_equipment.robot.GetReady(Robot.StageList.Align)) { TmcStep = TmcSteps.BeforeAlign; } else { //Get Ready 내부에 alarm 발생 됨. } break; } case TmcSteps.BeforeAlign: { _equipment.preAligner.Align(180); EquipmentLogManager.Instance.WriteProcessLog($"Pre align start"); TmcStep = TmcSteps.BeforeAlignWait; break; } case TmcSteps.BeforeAlignWait: { if (_equipment.preAligner.IsRunEnable) { EquipmentLogManager.Instance.WriteProcessLog($"Pre align end"); TmcStep = TmcSteps.BeforeGetPreAligner; } break; } case TmcSteps.BeforeGetPreAligner: { if (_equipment.robot.Get(Robot.StageList.Align)) { EquipmentLogManager.Instance.WriteProcessLog($"Get align"); TmcStep = TmcSteps.CheckBeforeGetPreAligner; } else { //Get 내부에 alarm 발생 됨. } break; } case TmcSteps.CheckBeforeGetPreAligner: { if (_equipment.robot.IsRunEnable) { if (_equipment.robot.IsWaferExist) { TmcStep = TmcSteps.ChamberStatusCheck; //TmcStep = TmcSteps.AlignHomeStart; //23.05.11 Align 교체 후 테스트 } else { _equipment.alarmManager.Occur(AlarmCode.AL_0074_ROBOT_HAS_NOT_WAFER); } } break; } case TmcSteps.AlignHomeStart: { if(_equipment.preAligner.IsRunEnable) { _equipment.preAligner.Home(); TmcStep = TmcSteps.ChamberStatusCheck; } break; } case TmcSteps.ChamberStatusCheck: { if (_equipment.chamber.IsGateOpen && _equipment.chamber.IsLiftPinUp && _equipment.chamber.IsLoadPosition) { if(PmcStep == PmcSteps.WaferPutWait) { TmcStep = TmcSteps.PutChamber; } } else { if(_equipment.IsAttenuatorCalTime() == false && _equipment.IsAttenuatorCalRun == false && _equipment.IsEnergyDropCheckTime() == false&& _equipment.IsEnergyDropCheckRun == false) { if (PmcStep == PmcSteps.Wait) { PmcStep = PmcSteps.StatusCheck; } } } break; } case TmcSteps.PutChamber: { if (_equipment.chamber.IsGateOpen && _equipment.chamber.IsLiftPinUp && _equipment.chamber.IsLoadPosition) { if (PmcStep == PmcSteps.WaferPutWait) { if (_equipment.robot.Put(Robot.StageList.Chamber)) { EquipmentLogManager.Instance.WriteProcessLog($"Put chamber"); TmcStep = TmcSteps.CheckPutChamber; } else { //Put 내부에 alarm 발생 됨. } } } break; } case TmcSteps.CheckPutChamber: { if (_equipment.robot.IsRunEnable) { if (_equipment.robot.IsWaferExist == false) { _chamberWaferEmptyBit = false; _processStartBit = true; TmcStep = TmcSteps.MeltingWait; } else { _equipment.alarmManager.Occur(AlarmCode.AL_0077_ROBOT_HAS_WAFER); } } break; } case TmcSteps.MeltingWait: { if (_processEndBit == true) { if (_equipment.chamber.IsGateOpen && _equipment.chamber.IsLiftPinUp && _equipment.chamber.IsLoadPosition) { if (PmcStep == PmcSteps.WaferEmptyWait) { _processEndBit = false; TmcStep = TmcSteps.GetChamber; } } } break; } case TmcSteps.GetChamber: { if (_equipment.chamber.IsGateOpen && _equipment.chamber.IsLiftPinUp && _equipment.chamber.IsLoadPosition) { if (PmcStep == PmcSteps.WaferEmptyWait) { if (_equipment.robot.Get(Robot.StageList.Chamber)) { EquipmentLogManager.Instance.WriteProcessLog($"Get chamber"); TmcStep = TmcSteps.CheckGetChamber; } else { //Get 내부에 alarm 발생 됨. } } } break; } case TmcSteps.CheckGetChamber: { if (_equipment.robot.IsRunEnable) { if (_equipment.robot.IsWaferExist) { _chamberWaferEmptyBit = true; TmcStep = TmcSteps.AlignHomeCheck; } else { _equipment.alarmManager.Occur(AlarmCode.AL_0074_ROBOT_HAS_NOT_WAFER); } } break; } case TmcSteps.AlignHomeCheck: { if(_equipment.preAligner.IsRunEnable) { TmcStep = TmcSteps.AfterPutPreAlignerFlip; break; } break; } case TmcSteps.AfterPutPreAlignerFlip: { if (_equipment.robot.Put(Robot.StageList.AlignFlip)) { EquipmentLogManager.Instance.WriteProcessLog($"Put align flip"); TmcStep = TmcSteps.CheckAfterPutPreAlignerFlip; } else { //Put 내부에 alarm 발생 됨. } break; } case TmcSteps.CheckAfterPutPreAlignerFlip: { if (_equipment.robot.IsRunEnable) { if (_equipment.robot.IsWaferExist == false) { TmcStep = TmcSteps.AfterGetWaitPreAligner; } else { _equipment.alarmManager.Occur(AlarmCode.AL_0077_ROBOT_HAS_WAFER); } } break; } case TmcSteps.AfterGetWaitPreAligner: { if (_equipment.robot.GetReady(Robot.StageList.Align)) { TmcStep = TmcSteps.AfterAlign; } else { //Get Ready 내부에 alarm 발생 됨. } break; } case TmcSteps.AfterAlign: { _equipment.preAligner.Align(0); EquipmentLogManager.Instance.WriteProcessLog($"Pre algin start"); TmcStep = TmcSteps.AfterAlignWait; break; } case TmcSteps.AfterAlignWait: { if (_equipment.preAligner.IsRunEnable) { EquipmentLogManager.Instance.WriteProcessLog($"Pre algin end"); TmcStep = TmcSteps.AfterGetPreAligner; } break; } case TmcSteps.AfterGetPreAligner: { if (_equipment.robot.Get(Robot.StageList.Align)) { EquipmentLogManager.Instance.WriteProcessLog($"Get align"); TmcStep = TmcSteps.CheckAfterGetPreAligner; } else { //Get 내부에 alarm 발생 됨. } break; } case TmcSteps.CheckAfterGetPreAligner: { if (_equipment.robot.IsRunEnable) { if (_equipment.robot.IsWaferExist) { TmcStep = TmcSteps.PutLoadPort; } else { _equipment.alarmManager.Occur(AlarmCode.AL_0074_ROBOT_HAS_NOT_WAFER); } } break; } case TmcSteps.PutLoadPort: { if (currentFoup.portNumber == 1) { if (_equipment.robot.Put(Robot.StageList.Port1, _processNumber + 1)) { EquipmentLogManager.Instance.WriteProcessLog($"Put port : {currentFoup.portNumber} lot {_processNumber + 1}"); TmcStep = TmcSteps.CheckPutLoadPort; } else { //Put 내부에 alarm 발생 됨. } } else { if (_equipment.robot.Put(Robot.StageList.Port2, _processNumber + 1)) { EquipmentLogManager.Instance.WriteProcessLog($"Put port : {currentFoup.portNumber} lot {_processNumber + 1}"); TmcStep = TmcSteps.CheckPutLoadPort; } else { //Put 내부에 alarm 발생 됨. } } break; } case TmcSteps.CheckPutLoadPort: { if (_equipment.robot.IsRunEnable) { if (_equipment.robot.IsWaferExist == false) { _processNumber++; TmcStep = TmcSteps.ProcessDataCheck; } else { _equipment.alarmManager.Occur(AlarmCode.AL_0077_ROBOT_HAS_WAFER); } } break; } case TmcSteps.End: { EquipmentLogManager.Instance.WriteProcessLog($"Process end !!"); if (_equipment.IsAutoRun) { EquipmentLogManager.Instance.WriteProcessLog($"Auto run checked !!"); if (_equipment.port1Foup.status == Info.FoupInfo.FoupStatus.Complete) { _equipment.port1Foup.status = Info.FoupInfo.FoupStatus.Ready; } if (_equipment.port2Foup.status == Info.FoupInfo.FoupStatus.Complete) { _equipment.port2Foup.status = Info.FoupInfo.FoupStatus.Ready; } TmcStep = TmcSteps.StatusCheck; } else { TmcStep = TmcSteps.Wait; } break; } } } public void PmcSequence() { if(PmcStep != _pmcStepOld) { EquipmentLogManager.Instance.WritePmcSequenceLog(PmcStep.ToString()); _pmcStepOld = PmcStep; _pmcSequenceTimer.ReStart(); } switch(PmcStep) { case PmcSteps.Wait: { break; } case PmcSteps.StatusCheck: { _processEndBit = false; PmcStep = PmcSteps.BeforeMoveLoadPosition; break; } case PmcSteps.BeforeMoveLoadPosition: { if(_equipment.chamber.MoveLoadPosition()) { PmcStep = PmcSteps.CheckBeforeLoadPosition; } break; } case PmcSteps.CheckBeforeLoadPosition: { if(_equipment.chamber.IsInposition) { if(_equipment.chamber.IsLoadPosition) { PmcStep = PmcSteps.BeforeGateOpen; } else { PmcStep = PmcSteps.BeforeMoveLoadPosition; } } break; } case PmcSteps.BeforeGateOpen: { if (_equipment.chamber.IsGateOpen) { PmcStep = PmcSteps.BeforePinUp; } else { _equipment.chamber.GateOpen(); } break; } case PmcSteps.BeforePinUp: { if (_equipment.chamber.IsLiftPinUp) { PmcStep = PmcSteps.WaferPutWait; } else { _equipment.chamber.LiftPinUp(); } break; } case PmcSteps.WaferPutWait: { if(_processStartBit == true) { if (_equipment.robot.IsRunEnable && _equipment.chamber.WaferInfo.IsStatus == Info.WaferInfo.WaferInfo.WaferStatus.Exist) { _processStartBit = false; PmcStep = PmcSteps.BeforeVacuumOn; } } break; } case PmcSteps.BeforeVacuumOn: { if (_equipment.chamber.IsChuckVacuumOn) { EquipmentLogManager.Instance.WriteProcessLog($"Before vaccum on"); PmcStep = PmcSteps.BeforePinDown; } else { _equipment.chamber.ChuckVacuumOn(); } break; } case PmcSteps.BeforePinDown: { if (_equipment.chamber.IsLiftPinDown) { EquipmentLogManager.Instance.WriteProcessLog($"Before lift pin down"); PmcStep = PmcSteps.BeforeGateClose; } else { _equipment.chamber.LiftPinDown(); } break; } case PmcSteps.BeforeGateClose: { if(_equipment.chamber.IsGateClose) { EquipmentLogManager.Instance.WriteProcessLog($"Before gate close"); PmcStep = PmcSteps.Melting; } else { _equipment.chamber.GateClose(); } break; } case PmcSteps.Melting: { double[] CenterDataX = _equipment.powerPmac.GetAxisTeachData(PmacAxis.X_Axis, EnTeachData.CenterPosX); double[] CenterDataY = _equipment.powerPmac.GetAxisTeachData(PmacAxis.Y_Axis, EnTeachData.CenterPosY); double[] CenterDataT = _equipment.powerPmac.GetAxisTeachData(PmacAxis.X_Axis, EnTeachData.CenterPosT); _centerPositionX = CenterDataX[0]; _centerPositionY = CenterDataY[0]; _centerPositionT = CenterDataT[0]; PmcStep = PmcSteps.MoveCenterPosition; break; } case PmcSteps.MoveCenterPosition: { if(_equipment.chamber.MoveCenterPosition()) { EquipmentLogManager.Instance.WriteProcessLog($"Move center position"); PmcStep = PmcSteps.CheckCenterPosition; } break; } case PmcSteps.CheckCenterPosition: { if (_equipment.chamber.IsInposition) { if (_equipment.chamber.IsCenterPosition) { PmcStep = PmcSteps.GetRecipeData; } else { PmcStep = PmcSteps.MoveCenterPosition; } } break; } case PmcSteps.GetRecipeData: { string recipeName = _equipment.chamber.WaferInfo.RecipeName; if (_equipment.recipeManager.ExistsRecipe(recipeName)) { _currentRecipe = _equipment.recipeManager.GetRecipe(recipeName); RecipeExcuted?.BeginInvoke(_currentRecipe, null, null); if (_currentRecipe.ProcessInfoList.Count > 0) { _processNum = 0; _processTimer.ReStart(); EquipmentLogManager.Instance.WriteProcessLog($"Recipe ('{recipeName}') total process count : {_currentRecipe.ProcessInfoList.Count} start "); if (_equipment.modeParameterManager.ModeParameter.AlignUse) { PmcStep = PmcSteps.MoveAlignPosition; } else { PmcStep = PmcSteps.GetProcessInfoData; } } else { EquipmentLogManager.Instance.WriteProcessLog($"Recipe ('{recipeName}') process data count is 0"); if (TmcStep == TmcSteps.Wait) { _equipment.SetMessageBox("Manual 가공이 완료 되었습니다."); PmcStep = PmcSteps.End; } else { PmcStep = PmcSteps.AfterMoveLoadPosition; } } } else { EquipmentLogManager.Instance.WriteProcessLog($"Recipe ('{recipeName}') is not exist"); if (TmcStep == TmcSteps.Wait) { _equipment.SetMessageBox("Manual 가공이 완료 되었습니다."); PmcStep = PmcSteps.End; } else { PmcStep = PmcSteps.AfterMoveLoadPosition; } } break; } case PmcSteps.MoveAlignPosition: { if (_equipment.chamber.MoveAlignPosition()) { EquipmentLogManager.Instance.WriteProcessLog($"Move align position"); PmcStep = PmcSteps.CheckAlignPosition; } break; } case PmcSteps.CheckAlignPosition: { if (_equipment.chamber.IsInposition) { if (_equipment.chamber.IsAlignPosition) { EquipmentLogManager.Instance.WriteProcessLog($"Align start"); PmcStep = PmcSteps.VisionReady; } else { PmcStep = PmcSteps.MoveAlignPosition; } } break; } case PmcSteps.VisionReady: { _alignOffsetX = 0; _alignOffsetY = 0; _alignOffsetT = 0; _equipment.visionControl.SendVisionReady("Default"); PmcStep = PmcSteps.VisionReadyCheck; break; } case PmcSteps.VisionReadyCheck: { if(_equipment.visionControl.CommnadAcks[VisionToControlCommand.VisionReadyAck] && _equipment.visionControl.CommnadAcks[VisionToControlCommand.InspReadyEnd]) { PmcStep = PmcSteps.WaferDetectionReady; } else { if(_pmcSequenceTimer.Seconds > _equipment.settingParameterManager.SettingParameter.VisionTimeOut) { } } break; } case PmcSteps.WaferDetectionReady: { _equipment.visionControl.SendWaferDetectionReady(); PmcStep = PmcSteps.WaferDetection; break; } case PmcSteps.WaferDetectionReadyCheck: { if (_equipment.visionControl.CommnadAcks[VisionToControlCommand.WaferDetectionReadyAck] && _equipment.visionControl.CommnadAcks[VisionToControlCommand.WaferDetectionReadyEnd]) { PmcStep = PmcSteps.WaferDetection; } else { if (_pmcSequenceTimer.Seconds > _equipment.settingParameterManager.SettingParameter.VisionTimeOut) { } } break; } case PmcSteps.WaferDetection: { _equipment.visionControl.SendWaferDetectionStart(); PmcStep = PmcSteps.WaferDetectionCheck; break; } case PmcSteps.WaferDetectionCheck: { if (_equipment.visionControl.CommnadAcks[VisionToControlCommand.WaferDetectionStartAck] && _equipment.visionControl.CommnadAcks[VisionToControlCommand.WaferDetectionResult]) { if(_equipment.visionControl.WaferDetectionResultValue.Result == 0) { _alignOffsetX += _equipment.visionControl.WaferDetectionResultValue.ResultX; _alignOffsetY += _equipment.visionControl.WaferDetectionResultValue.ResultY; _alignOffsetT += _equipment.visionControl.WaferDetectionResultValue.ResultT; EquipmentLogManager.Instance.WriteProcessLog($"Align result ->"); EquipmentLogManager.Instance.WriteProcessLog($"X: {_equipment.visionControl.WaferDetectionResultValue.ResultX}, Y: {_equipment.visionControl.WaferDetectionResultValue.ResultY}, T: {_equipment.visionControl.WaferDetectionResultValue.ResultT}"); PmcStep = PmcSteps.MoveOffsetPosition; } else { EquipmentLogManager.Instance.WriteProcessLog($"Align complete"); PmcStep = PmcSteps.GetProcessInfoData; } } else { if (_pmcSequenceTimer.Seconds > _equipment.settingParameterManager.SettingParameter.VisionTimeOut) { } } break; } case PmcSteps.MoveOffsetPosition: { double posX = _equipment.powerPmac.m_AxisAllList[(int)PmacAxis.X_Axis].TeachList[(int)EnTeachData.AlignX].Position; double posY = _equipment.powerPmac.m_AxisAllList[(int)PmacAxis.Y_Axis].TeachList[(int)EnTeachData.AlignY].Position; double posT = _equipment.powerPmac.m_AxisAllList[(int)PmacAxis.T_Axis].TeachList[(int)EnTeachData.AlignT].Position; double speedX = _equipment.powerPmac.m_AxisAllList[(int)PmacAxis.X_Axis].TeachList[(int)EnTeachData.AlignX].Speed; double speedY = _equipment.powerPmac.m_AxisAllList[(int)PmacAxis.Y_Axis].TeachList[(int)EnTeachData.AlignY].Speed; double speedT = _equipment.powerPmac.m_AxisAllList[(int)PmacAxis.T_Axis].TeachList[(int)EnTeachData.AlignT].Speed; double accX = _equipment.powerPmac.m_AxisAllList[(int)PmacAxis.X_Axis].TeachList[(int)EnTeachData.AlignX].Accel; double accY = _equipment.powerPmac.m_AxisAllList[(int)PmacAxis.Y_Axis].TeachList[(int)EnTeachData.AlignY].Accel; double accT = _equipment.powerPmac.m_AxisAllList[(int)PmacAxis.T_Axis].TeachList[(int)EnTeachData.AlignT].Accel; _equipment.powerPmac.MoveAbs(PmacAxis.X_Axis, posX + _alignOffsetX, speedX, accX); _equipment.powerPmac.MoveAbs(PmacAxis.Y_Axis, posY + _alignOffsetY, speedY, accY); _equipment.powerPmac.MoveAbs(PmacAxis.T_Axis, posT + _alignOffsetT, speedT, accT); PmcStep = PmcSteps.CheckOffsetPositon; break; } case PmcSteps.CheckOffsetPositon: { if (_equipment.chamber.IsInposition) { double posX = _equipment.powerPmac.m_AxisAllList[(int)PmacAxis.X_Axis].TeachList[(int)EnTeachData.AlignX].Position; double posY = _equipment.powerPmac.m_AxisAllList[(int)PmacAxis.Y_Axis].TeachList[(int)EnTeachData.AlignY].Position; double posT = _equipment.powerPmac.m_AxisAllList[(int)PmacAxis.T_Axis].TeachList[(int)EnTeachData.AlignT].Position; if (_equipment.powerPmac.InpositionCheck(posX + _alignOffsetX, _equipment.powerPmac.GetAxisActualPos(PmacAxis.X_Axis)) && _equipment.powerPmac.InpositionCheck(posY + _alignOffsetY, _equipment.powerPmac.GetAxisActualPos(PmacAxis.Y_Axis)) && _equipment.powerPmac.InpositionCheck(posT + _alignOffsetT, _equipment.powerPmac.GetAxisActualPos(PmacAxis.T_Axis))) { EquipmentLogManager.Instance.WriteProcessLog($"Offset move."); PmcStep = PmcSteps.WaferDetectionReady; } else { } } break; } case PmcSteps.GetProcessInfoData: { if(_processInfo != null) { _oldProcessInfo = _processInfo.Clone(); } _processInfo = _currentRecipe.ProcessInfoList[_processNum]; _processInfo.SetProcessData(); if (_processInfo.IsProcessEnable) { EquipmentLogManager.Instance.WriteProcessLog($"Process {_processNum + 1} start !!"); PmcStep = PmcSteps.CoordTransform; } else { EquipmentLogManager.Instance.WriteProcessLog($"Process {_processNum + 1} is not enable"); PmcStep = PmcSteps.ProcessEnd; } break; } case PmcSteps.CoordTransform: { _equipment.scanner.ClearScanList(); double middlePosition = (_processInfo.ProcessStartY + _processInfo.ProcessEndY) / 2; if(_processNum % 2 == 0) // 짝수 진행방향 -> { foreach (Info.RecipeInfo.Coord coord in _processInfo.ProcessList) { _equipment.scanner.AddScanList(coord.ScanMode, coord.Y - middlePosition, (_processInfo.ProcessStartX - coord.X)); } } else // 홀수 진행방향 <- { _processInfo.ProcessList.Reverse(); for (int i = 0; i < _processInfo.ProcessList.Count; i += 2) { Info.RecipeInfo.Coord coordMark= _processInfo.ProcessList[i]; Info.RecipeInfo.Coord coordJump = _processInfo.ProcessList[i + 1]; _equipment.scanner.AddScanList(coordJump.ScanMode, coordJump.Y - middlePosition, _processInfo.ProcessEndX - coordJump.X); // 짝수 _equipment.scanner.AddScanList(coordMark.ScanMode, coordMark.Y - middlePosition, _processInfo.ProcessEndX - coordMark.X); // 짝수 } } EquipmentLogManager.Instance.WriteProcessLog($"Recipe energy is {_processInfo.Energy}"); //_equipment.crevis.WriteOutput(Crevis.DigitalOutput.LASER_SHUTTER_OPEN_SOL, true); // 측정 energy가 0이면 shutter 닫는거로..? // -> 그냥 Energy 측정 0되면 갠춘할듯. //if(_processInfo.Energy == 0) //{ // EquipmentLogManager.Instance.WriteProcessLog($"Measurement energy is 0"); // _equipment.crevis.WriteOutput(Crevis.DigitalOutput.LASER_SHUTTER_OPEN_SOL, false); // PmcStep = PmcSteps.MoveProcessStartPosition; // return; //} //else //{ // EquipmentLogManager.Instance.WriteProcessLog($"Measurement energy is {_processInfo.Energy}"); // _equipment.crevis.WriteOutput(Crevis.DigitalOutput.LASER_SHUTTER_OPEN_SOL, true); //} if (_equipment.modeParameterManager.ModeParameter.EnergyMeasurementUse) { // Measurement 진행 if (_oldProcessInfo == null || _oldProcessInfo.Energy != _processInfo.Energy) { // 서로 Energy가 다를 때 EquipmentLogManager.Instance.WriteProcessLog($"Energy deffrent : energy measure start !"); PmcStep = PmcSteps.CalDataAttenuatorSet; } else if ((DateTime.Now - _lastMeasurementTime).TotalSeconds > _equipment.settingParameterManager.SettingParameter.EnergyMeasurementCycle) { // 마지막 Measurement 시간이 setting 값보다 클 때 EquipmentLogManager.Instance.WriteProcessLog($"Measure time ({ _equipment.settingParameterManager.SettingParameter.EnergyMeasurementCycle} sec) over : energy measure start !"); PmcStep = PmcSteps.CalDataAttenuatorSet; } else if (_waferProcessCountAfterMeasurement > _equipment.settingParameterManager.SettingParameter.EnergyMeasurementWaferCountCycle) { // 마지막 Measurement 한 후 n개의 wafer가 진행 되었을 때 EquipmentLogManager.Instance.WriteProcessLog($"Wafer count over({_equipment.settingParameterManager.SettingParameter.EnergyMeasurementWaferCountCycle}) : energy measure start !"); PmcStep = PmcSteps.CalDataAttenuatorSet; } else { //Measurement 진행 안함. PmcStep = PmcSteps.MoveProcessStartPosition; } } else { //Measurement 진행 안함. PmcStep = PmcSteps.MoveProcessStartPosition; } break; } case PmcSteps.CalDataAttenuatorSet: { _measurementCount = 0; EquipmentLogManager.Instance.WriteProcessLog($"Energy measurement start count : {_measurementCount}"); double energy = _processInfo.Energy * (_equipment.settingParameterManager.SettingParameter.BeamWidth * _equipment.settingParameterManager.SettingParameter.BeamHeight / 100); energy = double.Parse($"{energy:F7}"); _setAttenuatorAngle = _equipment.attenuatorCalInfo.GetAttenuatorAngleForEnergy(energy); _equipment.attenuator.MoveAbsolute(_setAttenuatorAngle); PmcStep = PmcSteps.CalDataCheckAttenuator; break; } case PmcSteps.CalDataCheckAttenuator: { if (_equipment.attenuator.MotorState == Attenuator.MotorRunState.Stopped) { if (_equipment.attenuator.IsAttenuatorAngleCorrect(_setAttenuatorAngle)) { EquipmentLogManager.Instance.WriteProcessLog($"Attenuator setting {_setAttenuatorAngle} degree"); PmcStep = PmcSteps.MovePowerMeterPosition; } else { PmcStep = PmcSteps.CalDataAttenuatorSet; } } break; } case PmcSteps.MovePowerMeterPosition: { if (_equipment.chamber.MovePowerMeterPosition()) { EquipmentLogManager.Instance.WriteProcessLog($"Move power meter position."); PmcStep = PmcSteps.CheckPowerMeterPosition; } break; } case PmcSteps.CheckPowerMeterPosition: { if (_equipment.chamber.IsInposition) { if (_equipment.chamber.IsPowerMeterPosition) { PmcStep = PmcSteps.PowerMeterInitialize; } else { PmcStep = PmcSteps.MovePowerMeterPosition; } } break; } case PmcSteps.PowerMeterInitialize: { _equipment.powerMeter.ResetEnergyMeter(); _measurementTimer.ReStart(); PmcStep = PmcSteps.PowerMeterInitializeCheck; break; } case PmcSteps.PowerMeterInitializeCheck: { if (_equipment.powerMeter.Enable && _equipment.powerMeter.CurrentMeasurementMode == PowerMeter.MeasurementMode.Energy) { PmcStep = PmcSteps.LaserOn; } else { if (_measurementTimer.Seconds > 20) { EquipmentLogManager.Instance.WriteProcessLog($"Measurement 초기화가 되지 않았습니다. energy meter를 확인 해 주세요."); _equipment.SetMessageBox("Measurement 초기화가 되지 않았습니다. energy meter를 확인 해 주세요."); PmcStep = PmcSteps.PowerMeterInitialize; } } break; } case PmcSteps.LaserOn: { if (_equipment.chamber.IsPowerMeterPosition) { _equipment.scanner.LaserOn(); EquipmentLogManager.Instance.WriteProcessLog($"Laser on."); PmcStep = PmcSteps.MeasurementStart; } else { PmcStep = PmcSteps.MovePowerMeterPosition; } break; } case PmcSteps.MeasurementStart: { if (_equipment.scanner.IsLaserOn) { if (_pmcSequenceTimer.Seconds > _equipment.settingParameterManager.SettingParameter.EnergyMeterHeatingTime) { _equipment.powerMeter.ResetMeasurementsEnergy(); _measurementTimer.ReStart(); EquipmentLogManager.Instance.WriteProcessLog($"Energy measurement start."); EquipmentLogManager.Instance.WriteEnergyMeasureLog($"Energy measurement start."); PmcStep = PmcSteps.Measurement; } } else if(_pmcSequenceTimer.Seconds > 2) { PmcStep = PmcSteps.LaserOn; } break; } case PmcSteps.Measurement: { if (_equipment.settingParameterManager.SettingParameter.EnergyMeasurementTime < _measurementTimer.Seconds || _equipment.chamber.IsPowerMeterPosition == false) { if (_equipment.chamber.IsPowerMeterPosition == false) { _equipment.scanner.LaserOff(); PmcStep = PmcSteps.MeasurementEnd; } else { if (_equipment.settingParameterManager.SettingParameter.EnergyMeasurementTime < _measurementTimer.Seconds) { _equipment.scanner.LaserOff(); PmcStep = PmcSteps.MeasurementEnd; } } } break; } case PmcSteps.MeasurementEnd: { if (_equipment.scanner.IsLaserOn) { if (_pmcSequenceTimer.Seconds > 3) { if (_equipment.scanner.IsBusy) { _equipment.scanner.Stop(); } _equipment.scanner.LaserOff(); } return; } EquipmentLogManager.Instance.WriteProcessLog($"Energy measurement end."); PmcStep = PmcSteps.MeasurrmentDataCheck; break; } case PmcSteps.MeasurrmentDataCheck: { double energyAverage = _equipment.powerMeter.MeasurementAverageEnergyPerUnitArea; double limitRange = _processInfo.Energy * (_equipment.settingParameterManager.SettingParameter.EnergyMeasurementErrorOccuredRange / 100); double maxLimits = _processInfo.Energy + limitRange; double minLimits = _processInfo.Energy - limitRange; EquipmentLogManager.Instance.WriteProcessLog($"Target energy : { _processInfo.Energy}"); EquipmentLogManager.Instance.WriteProcessLog($"Everage energy : {energyAverage}"); EquipmentLogManager.Instance.WriteProcessLog($"Energy range : {minLimits} ~ {maxLimits}"); EquipmentLogManager.Instance.WriteEnergyMeasureLog($"Target energy : { _processInfo.Energy}"); EquipmentLogManager.Instance.WriteEnergyMeasureLog($"Everage energy : {energyAverage}"); EquipmentLogManager.Instance.WriteEnergyMeasureLog($"Energy range : {minLimits} ~ {maxLimits}"); if (minLimits <= energyAverage && energyAverage <= maxLimits) { _lastMeasurementTime = DateTime.Now; _waferProcessCountAfterMeasurement = 0; EquipmentLogManager.Instance.WriteProcessLog($"Energy measurement success "); EquipmentLogManager.Instance.WriteEnergyMeasureLog($"Energy measurement success "); PmcStep = PmcSteps.MoveProcessStartPosition; } else { if(_measurementCount > _equipment.settingParameterManager.SettingParameter.EnergyMeasurementRetryCount) { _equipment.alarmManager.Occur(AlarmCode.AL_0081_ENERGY_MEASUREMENT_FAIL); EquipmentLogManager.Instance.WriteProcessLog($"Energy measurement fail"); EquipmentLogManager.Instance.WriteEnergyMeasureLog($"Energy measurement fail"); _equipment.SetMessageBox("Power measurement 실패 !"); if (TmcStep == TmcSteps.Wait) { PmcStep = PmcSteps.End; } else { PmcStep = PmcSteps.AfterMoveLoadPosition; } return; } double energyPer1Degree = _equipment.attenuatorCalInfo.GetEnergyPer1Degree(); energyPer1Degree *= 100; energyPer1Degree = double.Parse($"{energyPer1Degree / (_equipment.settingParameterManager.SettingParameter.BeamWidth * _equipment.settingParameterManager.SettingParameter.BeamHeight):F4}"); double settingEnergy = _processInfo.Energy; float measurementStepAngle = _equipment.settingParameterManager.SettingParameter.EnergyMeasurmentStepAngle; if (energyAverage < minLimits) { if (settingEnergy - energyAverage < energyPer1Degree * measurementStepAngle) { if(energyPer1Degree == 0) { _setAttenuatorAngle += measurementStepAngle / 10; } else { _setAttenuatorAngle += float.Parse($"{(settingEnergy - energyAverage) / energyPer1Degree:F3}"); } } else { _setAttenuatorAngle += measurementStepAngle; } } else if(energyAverage > maxLimits) { if (energyAverage - settingEnergy < (energyPer1Degree * measurementStepAngle)) { if (energyPer1Degree == 0) { _setAttenuatorAngle -= measurementStepAngle / 10; } else { _setAttenuatorAngle -= float.Parse($"{(energyAverage - settingEnergy) / energyPer1Degree:F3}"); } } else { _setAttenuatorAngle -= measurementStepAngle; } } _measurementCount++; PmcStep = PmcSteps.AttenuatorSet; } break; } case PmcSteps.AttenuatorSet: { _equipment.attenuator.MoveAbsolute(_setAttenuatorAngle); EquipmentLogManager.Instance.WriteProcessLog($"Attenuator setting {_setAttenuatorAngle} degree"); EquipmentLogManager.Instance.WriteEnergyMeasureLog($"Attenuator setting {_setAttenuatorAngle} degree"); PmcStep = PmcSteps.CheckAttenuator; break; } case PmcSteps.CheckAttenuator: { if(_equipment.attenuator.MotorState == Attenuator.MotorRunState.Stopped) { if (_equipment.attenuator.IsAttenuatorAngleCorrect(_setAttenuatorAngle)) { if (_equipment.chamber.IsInposition) { if (_equipment.chamber.IsPowerMeterPosition) { PmcStep = PmcSteps.MeasurementStart; } else { PmcStep = PmcSteps.MovePowerMeterPosition; } } } else { PmcStep = PmcSteps.AttenuatorSet; } } break; } case PmcSteps.MoveProcessStartPosition: { double[] CenterDataY = _equipment.powerPmac.GetAxisTeachData(PmacAxis.Y_Axis, EnTeachData.CenterPosY); double[] CenterDataX = _equipment.powerPmac.GetAxisTeachData(PmacAxis.X_Axis, EnTeachData.CenterPosX); double processTime = (_processInfo.ProcessLength / _processInfo.ScannerProcessSpeed); // 차이값 _processStartPositionY = double.Parse($"{_centerPositionY + _alignOffsetY + (_processInfo.ProcessStartY - (Math.Abs(_processInfo.ProcessStartY - _processInfo.ProcessEndY) / 2)):f4}"); if (_processNum % 2 == 0) // 짝수 진행방향 -> { _processStartPositionX = double.Parse($"{_centerPositionX + _alignOffsetX + (_processInfo.ProcessStartX):f4}"); _processEndPositionX = double.Parse($"{_centerPositionX + _alignOffsetX + (_processInfo.ProcessEndX):f4}"); _stageVelocity = double.Parse($"{((_processEndPositionX - _processStartPositionX) / processTime):F3}"); } else // 홀수 진행방향 <- { _processStartPositionX = double.Parse($"{_centerPositionX + _alignOffsetX + (_processInfo.ProcessEndX):f4}"); _processEndPositionX = double.Parse($"{_centerPositionX + _alignOffsetX + (_processInfo.ProcessStartX):f4}"); _stageVelocity = double.Parse($"{((_processStartPositionX - _processEndPositionX) / processTime):F3}"); } bool check = true; check = _equipment.powerPmac.MoveAbs(PmacAxis.Y_Axis, _processStartPositionY, CenterDataY[1], CenterDataY[2]); check = _equipment.powerPmac.MoveAbs(PmacAxis.X_Axis, _processStartPositionX, CenterDataX[1], CenterDataX[2]); EquipmentLogManager.Instance.WriteProcessLog($"Move process start position"); PmcStep = PmcSteps.CheckProcessStartPosition; break; } case PmcSteps.CheckProcessStartPosition: { if (_equipment.chamber.IsInposition) { bool isMotorXProcessPosition = _processStartPositionX == _equipment.powerPmac.GetAxisActualPos(PmacAxis.X_Axis); bool isMotorYProcessPosition = _processStartPositionY == _equipment.powerPmac.GetAxisActualPos(PmacAxis.Y_Axis); if (isMotorXProcessPosition && isMotorYProcessPosition) { PmcStep = PmcSteps.ProcessStart; } else if (_pmcSequenceTimer.Seconds > 3) { PmcStep = PmcSteps.MoveProcessStartPosition; } } break; } case PmcSteps.ProcessStart: { //Scanner Setting. if (_equipment.scanner.Initialize()) { _equipment.scanner.SetScannerDelay(); _equipment.scanner.SetLaserTiming(); _equipment.scanner.SetLaserDelays(); _equipment.scanner.SetJumpMarkSpeed(_processInfo.ScannerProcessSpeed, _processInfo.ScannerProcessSpeed); if(_equipment.powerPmac.MoveAbs(PmacAxis.X_Axis, _processEndPositionX, _stageVelocity, _processInfo.AccTime * 100)) { _equipment.scanner.ExcuteScanList(true); EquipmentLogManager.Instance.WriteProcessLog($"Process ({_processNum + 1}) start"); PmcStep = PmcSteps.ProcessRunning; } } break; } case PmcSteps.ProcessRunning: { if (_equipment.chamber.IsInposition) { double processTime = (_processInfo.ProcessLength / _processInfo.ScannerProcessSpeed); // 차이값 bool isMotorXProcessPosition = _processEndPositionX == _equipment.powerPmac.GetAxisActualPos(PmacAxis.X_Axis); if (isMotorXProcessPosition && _equipment.scanner.IsBusy == false) { PmcStep = PmcSteps.ProcessEnd; } else if (_pmcSequenceTimer.Seconds > processTime + 10) { if (_equipment.scanner.IsBusy) { _equipment.scanner.Stop(); } _equipment.scanner.LaserOff(); EquipmentLogManager.Instance.WriteProcessLog($"가공 Error 가능성 있음."); PmcStep = PmcSteps.ProcessEnd; } } break; } case PmcSteps.ProcessEnd: { ProcessInfoExcuted?.BeginInvoke(_processInfo, _processNum, null, null); EquipmentLogManager.Instance.WriteProcessLog($"Process ({_processNum + 1}) end"); _processNum++; if (_currentRecipe.ProcessInfoList.Count == _processNum) { EquipmentLogManager.Instance.WriteProcessLog($"Recipe ({_currentRecipe.Name}) Process complete !!"); _processTimer.Stop(); WaferInfo waferInfo = _equipment.chamber.WaferInfo.Clone(); waferInfo.IsProcessComplete = true; _equipment.waferInfoManager.SetWaferInfo(WaferInfoManager.WaferNumbers.Chamber, waferInfo); if (TmcStep == TmcSteps.Wait) { _equipment.SetMessageBox("Manual 가공이 완료 되었습니다."); PmcStep = PmcSteps.End; } else { PmcStep = PmcSteps.AfterMoveLoadPosition; } } else { PmcStep = PmcSteps.GetProcessInfoData; } break; } case PmcSteps.AfterMoveLoadPosition: { if (_equipment.chamber.MoveLoadPosition()) { EquipmentLogManager.Instance.WriteProcessLog($"Move load position"); PmcStep = PmcSteps.CheckAfterLoadPosition; } break; } case PmcSteps.CheckAfterLoadPosition: { if (_equipment.chamber.IsInposition) { if (_equipment.chamber.IsLoadPosition) { PmcStep = PmcSteps.AfterGateOpen; } else { PmcStep = PmcSteps.AfterMoveLoadPosition; } } break; } case PmcSteps.AfterGateOpen: { if (_equipment.chamber.IsGateOpen) { EquipmentLogManager.Instance.WriteProcessLog($"After gate open"); PmcStep = PmcSteps.AfterVacuumOff; } else { _equipment.chamber.GateOpen(); } break; } case PmcSteps.AfterVacuumOff: { if (_equipment.chamber.IsChuckVacuumOn == false) { EquipmentLogManager.Instance.WriteProcessLog($"After vaccum off"); PmcStep = PmcSteps.AfterPinUp; } else { _equipment.chamber.ChuckVacuumOff(); } break; } case PmcSteps.AfterPinUp: { if(_pmcSequenceTimer.Seconds > 2) // Vacuum Off 대기 시간. { if (_equipment.chamber.IsLiftPinUp) { _processEndBit = true; EquipmentLogManager.Instance.WriteProcessLog($"After lift pin up"); PmcStep = PmcSteps.WaferEmptyWait; } else { _equipment.chamber.LiftPinUp(); } } break; } case PmcSteps.WaferEmptyWait: { if (_equipment.robot.IsRunEnable) { if (_chamberWaferEmptyBit && _equipment.chamber.WaferInfo.IsStatus == Info.WaferInfo.WaferInfo.WaferStatus.Empty) { PmcStep = PmcSteps.PinDown; } } break; } case PmcSteps.PinDown: { if (_equipment.chamber.IsLiftPinDown) { EquipmentLogManager.Instance.WriteProcessLog($"After Lift pin down"); PmcStep = PmcSteps.GateClose; } else { _equipment.chamber.LiftPinDown(); } break; } case PmcSteps.GateClose: { if (_equipment.chamber.IsGateClose) { EquipmentLogManager.Instance.WriteProcessLog($"After Gate close"); PmcStep = PmcSteps.End; } else { _equipment.chamber.GateClose(); } break; } case PmcSteps.End: { _processTimer.Stop(); if (_equipment.scanner.IsBusy) { _equipment.scanner.Stop(); } _equipment.scanner.LaserOff(); _equipment.powerPmac.MoveStop(PmacAxis.X_Axis); PmcStep = PmcSteps.Wait; break; } // ==================== Energy Drop Check Start ======================= case PmcSteps.EnergyDropCheckStart: { EquipmentLogManager.Instance.WriteEnergyDropCheckLog("Energy drop check start !!"); PmcStep = PmcSteps.EdcPowerMeterInitialize; break; } case PmcSteps.EdcPowerMeterInitialize: { _equipment.powerMeter.ResetEnergyMeter(); _measurementTimer.ReStart(); PmcStep = PmcSteps.EdcPowerMeterInitializeCheck; break; } case PmcSteps.EdcPowerMeterInitializeCheck: { if (_equipment.powerMeter.Enable && _equipment.powerMeter.CurrentMeasurementMode == PowerMeter.MeasurementMode.Energy) { EquipmentLogManager.Instance.WriteEnergyDropCheckLog("Power meter reset."); if (_equipment.chamber.IsPowerMeterPosition) { PmcStep = PmcSteps.EdcAttenuatorSet; } else { PmcStep = PmcSteps.EdcMoveCenterPosition; } } else { if (_measurementTimer.Seconds > 20) { EquipmentLogManager.Instance.WriteEnergyDropCheckLog("Measurement 초기화가 되지 않았습니다. energy meter를 확인 해 주세요."); _equipment.SetMessageBox("Measurement 초기화가 되지 않았습니다. energy meter를 확인 해 주세요."); PmcStep = PmcSteps.EdcPowerMeterInitialize; } } break; } case PmcSteps.EdcMoveCenterPosition: { if (_equipment.chamber.MoveCenterPosition()) { EquipmentLogManager.Instance.WriteEnergyDropCheckLog("Move center position."); PmcStep = PmcSteps.EdcCheckCenterPosition; } break; } case PmcSteps.EdcCheckCenterPosition: { if (_equipment.chamber.IsInposition) { if (_equipment.chamber.IsCenterPosition) { PmcStep = PmcSteps.EdcMovePowerMeterPosition; } else { PmcStep = PmcSteps.EdcMoveCenterPosition; } } break; } case PmcSteps.EdcMovePowerMeterPosition: { if (_equipment.chamber.MovePowerMeterPosition()) { EquipmentLogManager.Instance.WriteEnergyDropCheckLog("Move power meter position."); PmcStep = PmcSteps.EdcCheckPowerMeterPosition; } break; } case PmcSteps.EdcCheckPowerMeterPosition: { if (_equipment.chamber.IsInposition) { if (_equipment.chamber.IsPowerMeterPosition) { PmcStep = PmcSteps.EdcAttenuatorSet; } else { PmcStep = PmcSteps.EdcMovePowerMeterPosition; } } break; } case PmcSteps.EdcAttenuatorSet: { _equipment.attenuator.MoveAbsolute(_equipment.settingParameterManager.SettingParameter.EnergyDropCheckTargetAngle); PmcStep = PmcSteps.EdcCheckAttenuator; break; } case PmcSteps.EdcCheckAttenuator: { if (_equipment.attenuator.MotorState == Attenuator.MotorRunState.Stopped) { if (_equipment.attenuator.IsAttenuatorAngleCorrect(_equipment.settingParameterManager.SettingParameter.EnergyDropCheckTargetAngle)) { EquipmentLogManager.Instance.WriteEnergyDropCheckLog($"Attenuator setting {_equipment.settingParameterManager.SettingParameter.EnergyDropCheckTargetAngle} degree"); PmcStep = PmcSteps.EdcLaserOn; } else { PmcStep = PmcSteps.EdcAttenuatorSet; } } break; } case PmcSteps.EdcLaserOn: { if (_equipment.chamber.IsPowerMeterPosition) { EquipmentLogManager.Instance.WriteEnergyDropCheckLog($"Laser on !!"); _equipment.scanner.LaserOn(); PmcStep = PmcSteps.EdcMeasurementStart; } else { PmcStep = PmcSteps.EdcMovePowerMeterPosition; } break; } case PmcSteps.EdcMeasurementStart: { if (_equipment.scanner.IsLaserOn) { if (_pmcSequenceTimer.Seconds > _equipment.settingParameterManager.SettingParameter.EnergyMeterHeatingTime) { _equipment.powerMeter.ResetMeasurementsEnergy(); _measurementTimer.ReStart(); PmcStep = PmcSteps.EdcMeasurement; } } else if (_pmcSequenceTimer.Seconds > 2) { PmcStep = PmcSteps.EdcLaserOn; } break; } case PmcSteps.EdcMeasurement: { if (_equipment.settingParameterManager.SettingParameter.EnergyDropCheckMeasurementTime < _measurementTimer.Seconds || _equipment.chamber.IsPowerMeterPosition == false) { if (_equipment.chamber.IsPowerMeterPosition == false) { _equipment.scanner.LaserOff(); PmcStep = PmcSteps.EdcLaserOff; } else { if(_equipment.settingParameterManager.SettingParameter.EnergyDropCheckMeasurementTime < _measurementTimer.Seconds) { PmcStep = PmcSteps.EdcMeasurementLaserOff; } } } break; } case PmcSteps.EdcMeasurementLaserOff: { if (_equipment.scanner.IsBusy) { _equipment.scanner.Stop(); } _equipment.scanner.LaserOff(); PmcStep = PmcSteps.EdcMeasurementLaserOffCheck; break; } case PmcSteps.EdcMeasurementLaserOffCheck: { if (_equipment.scanner.IsLaserOn) { if (_pmcSequenceTimer.Seconds > 3) { PmcStep = PmcSteps.EdcMeasurementLaserOff; } return; } else { EquipmentLogManager.Instance.WriteEnergyDropCheckLog($"Laser off !!"); PmcStep = PmcSteps.EdcMeasurementEnd; } break; } case PmcSteps.EdcMeasurementEnd: { if (_equipment.scanner.IsBusy) { _equipment.scanner.Stop(); } _equipment.scanner.LaserOff(); PmcStep = PmcSteps.EdcMeasurementDataCheck; break; } case PmcSteps.EdcMeasurementDataCheck: { double energyAverage = _equipment.powerMeter.MeasurementAverageEnergyPerUnitArea; double limitRange = _equipment.settingParameterManager.SettingParameter.EnergyDropCheckTargetEnergy * (_equipment.settingParameterManager.SettingParameter.EnergyDropCheckErrorOccuredRange / 100); double maxLimits = _equipment.settingParameterManager.SettingParameter.EnergyDropCheckTargetEnergy + limitRange; double minLimits = _equipment.settingParameterManager.SettingParameter.EnergyDropCheckTargetEnergy - limitRange; EquipmentLogManager.Instance.WriteEnergyDropCheckLog($"Target energy : {_equipment.settingParameterManager.SettingParameter.EnergyDropCheckTargetEnergy}"); EquipmentLogManager.Instance.WriteEnergyDropCheckLog($"Everage energy : {energyAverage}"); EquipmentLogManager.Instance.WriteEnergyDropCheckLog($"Energy range : {minLimits} ~ {maxLimits}"); if (minLimits < energyAverage && energyAverage < maxLimits) { EquipmentLogManager.Instance.WriteEnergyDropCheckLog($"Energy is ok !!"); _equipment.equipmentInfo.SetEnergyDropCheckDate(); PmcStep = PmcSteps.EdcLaserOff; } else { EquipmentLogManager.Instance.WriteEnergyDropCheckLog($"Energy drop !!"); _equipment.alarmManager.Occur(AlarmCode.AL_1100_ENERGY_DROP_CHECK_WRONG); PmcStep = PmcSteps.EdcLaserOff; } break; } case PmcSteps.EdcLaserOff: { if (_equipment.scanner.IsBusy) { _equipment.scanner.Stop(); } _equipment.scanner.LaserOff(); PmcStep = PmcSteps.EdcLaserOffCheck; break; } case PmcSteps.EdcLaserOffCheck: { if (_equipment.scanner.IsLaserOn) { if (_pmcSequenceTimer.Seconds > 3) { PmcStep = PmcSteps.EdcLaserOff; } } else { PmcStep = PmcSteps.EnergyDropCheckEnd; } break; } case PmcSteps.EnergyDropCheckEnd: { EquipmentLogManager.Instance.WriteEnergyDropCheckLog($"Energy drop check end !!"); PmcStep = PmcSteps.Wait; break; } // ==================== Attenuator Cal Start ======================= case PmcSteps.AttenuatorCalStart: { _attenuatorCalData.Clear(); _currentAttenuatorCalAngle = _equipment.settingParameterManager.SettingParameter.AttenuatorCalStartAngle; EquipmentLogManager.Instance.WriteAttenuatorCalLog($"Attenuator cal start !!"); PmcStep = PmcSteps.AcPowerMeterInitialize; break; } case PmcSteps.AcPowerMeterInitialize: { _equipment.powerMeter.ResetEnergyMeter(); _measurementTimer.ReStart(); PmcStep = PmcSteps.AcPowerMeterInitializeCheck; break; } case PmcSteps.AcPowerMeterInitializeCheck: { if (_equipment.powerMeter.Enable && _equipment.powerMeter.CurrentMeasurementMode == PowerMeter.MeasurementMode.Energy) { if (_equipment.chamber.IsInposition) { EquipmentLogManager.Instance.WriteAttenuatorCalLog("Power meter reset."); if (_equipment.chamber.IsPowerMeterPosition) { PmcStep = PmcSteps.AcAttenuatorSet; } else { PmcStep = PmcSteps.AcMoveCenterPosition; } } } else { if (_measurementTimer.Seconds > 20) { EquipmentLogManager.Instance.WriteAttenuatorCalLog("Measurement 초기화가 되지 않았습니다. energy meter를 확인 해 주세요."); _equipment.SetMessageBox("Measurement 초기화가 되지 않았습니다. energy meter를 확인 해 주세요."); PmcStep = PmcSteps.AcPowerMeterInitialize; } } break; } case PmcSteps.AcMoveCenterPosition: { if (_equipment.chamber.MoveCenterPosition()) { EquipmentLogManager.Instance.WriteAttenuatorCalLog("Move center position."); PmcStep = PmcSteps.AcCheckCenterPosition; } break; } case PmcSteps.AcCheckCenterPosition: { if (_equipment.chamber.IsInposition) { if (_equipment.chamber.IsCenterPosition) { PmcStep = PmcSteps.AcMovePowerMeterPosition; } else { PmcStep = PmcSteps.AcMoveCenterPosition; } } break; } case PmcSteps.AcMovePowerMeterPosition: { if (_equipment.chamber.MovePowerMeterPosition()) { EquipmentLogManager.Instance.WriteAttenuatorCalLog("Move power meter position."); PmcStep = PmcSteps.AcCheckPowerMeterPosition; } break; } case PmcSteps.AcCheckPowerMeterPosition: { if (_equipment.chamber.IsInposition) { if (_equipment.chamber.IsPowerMeterPosition) { PmcStep = PmcSteps.AcAttenuatorSet; } else { PmcStep = PmcSteps.AcMovePowerMeterPosition; } } break; } case PmcSteps.AcAttenuatorSet: { _equipment.attenuator.MoveAbsolute(_currentAttenuatorCalAngle); PmcStep = PmcSteps.AcCheckAttenuator; break; } case PmcSteps.AcCheckAttenuator: { if (_equipment.attenuator.MotorState == Attenuator.MotorRunState.Stopped) { if (_equipment.attenuator.IsAttenuatorAngleCorrect(_currentAttenuatorCalAngle)) { EquipmentLogManager.Instance.WriteAttenuatorCalLog($"Attenuator setting {_equipment.settingParameterManager.SettingParameter.EnergyDropCheckTargetAngle} degree"); PmcStep = PmcSteps.AcCoolingTimeWait; } else { PmcStep = PmcSteps.AcAttenuatorSet; } } break; } case PmcSteps.AcCoolingTimeWait: { if (_measurementTimer.Seconds > _equipment.settingParameterManager.SettingParameter.AttenuatorCalCoolingTime) { EquipmentLogManager.Instance.WriteAttenuatorCalLog($"Cooling time wait !"); PmcStep = PmcSteps.AcLaserOn; } break; } case PmcSteps.AcLaserOn: { if (_equipment.chamber.IsPowerMeterPosition) { _equipment.scanner.LaserOn(); EquipmentLogManager.Instance.WriteAttenuatorCalLog($"Laser on !!"); PmcStep = PmcSteps.AcMeasurementStart; } break; } case PmcSteps.AcMeasurementStart: { if (_equipment.scanner.IsLaserOn) { if (_pmcSequenceTimer.Seconds > _equipment.settingParameterManager.SettingParameter.EnergyMeterHeatingTime) { _equipment.powerMeter.ResetMeasurementsEnergy(); _measurementTimer.ReStart(); PmcStep = PmcSteps.AcMeasurement; } } else if (_pmcSequenceTimer.Seconds > 2) { PmcStep = PmcSteps.AcLaserOn; } break; } case PmcSteps.AcMeasurement: { if (_equipment.settingParameterManager.SettingParameter.AttenuatorCalMeasurementTime < _measurementTimer.Seconds || _equipment.chamber.IsPowerMeterPosition == false) { if (_equipment.chamber.IsPowerMeterPosition == false) { _equipment.scanner.LaserOff(); PmcStep = PmcSteps.AcLaserOff; } else { if(_equipment.settingParameterManager.SettingParameter.AttenuatorCalMeasurementTime < _measurementTimer.Seconds) { PmcStep = PmcSteps.AcMeasurementLaserOff; } } } break; } case PmcSteps.AcMeasurementLaserOff: { _measurementTimer.ReStart(); if (_equipment.scanner.IsBusy) { _equipment.scanner.Stop(); } _equipment.scanner.LaserOff(); PmcStep = PmcSteps.AcMeasurementLaserOffCheck; break; } case PmcSteps.AcMeasurementLaserOffCheck: { if (_equipment.scanner.IsLaserOn) { if (_pmcSequenceTimer.Seconds > 3) { PmcStep = PmcSteps.AcMeasurementLaserOff; } return; } else { EquipmentLogManager.Instance.WriteAttenuatorCalLog($"Laser off !!"); PmcStep = PmcSteps.AcMeasurementEnd; } break; } case PmcSteps.AcMeasurementEnd: { PmcStep = PmcSteps.AcMeasurementDataCheck; break; } case PmcSteps.AcMeasurementDataCheck: { AttenuatorCalData attenuatorCalData = new AttenuatorCalData(); attenuatorCalData.AttenuatorAngle = _currentAttenuatorCalAngle; attenuatorCalData.Energy = _equipment.powerMeter.MeasurementAverageEnergy; _attenuatorCalData.Add(attenuatorCalData); EquipmentLogManager.Instance.WriteAttenuatorCalLog($"Attenuator angle : {attenuatorCalData.AttenuatorAngle} energy : {attenuatorCalData.Energy}"); //종료 if (_currentAttenuatorCalAngle >= _equipment.settingParameterManager.SettingParameter.AttenuatorCalEndAngle) { _equipment.attenuatorCalInfo.SetAttenuatorCalData(_attenuatorCalData.ToArray()); _equipment.equipmentInfo.SetAttenuatorCalDate(); PmcStep = PmcSteps.AcLaserOff; } // 마지막 else if (_currentAttenuatorCalAngle < _equipment.settingParameterManager.SettingParameter.AttenuatorCalEndAngle && _currentAttenuatorCalAngle + _equipment.settingParameterManager.SettingParameter.AttenuatorCalAngleStep > _equipment.settingParameterManager.SettingParameter.AttenuatorCalEndAngle) { _currentAttenuatorCalAngle = _equipment.settingParameterManager.SettingParameter.AttenuatorCalEndAngle; PmcStep = PmcSteps.AcPowerMeterInitialize; } // 계속 진행 else { _currentAttenuatorCalAngle += _equipment.settingParameterManager.SettingParameter.AttenuatorCalAngleStep; PmcStep = PmcSteps.AcPowerMeterInitialize; } break; } case PmcSteps.AcLaserOff: { if (_equipment.scanner.IsBusy) { _equipment.scanner.Stop(); } _equipment.scanner.LaserOff(); PmcStep = PmcSteps.AcLaserOffCheck; break; } case PmcSteps.AcLaserOffCheck: { if (_equipment.scanner.IsLaserOn) { if (_pmcSequenceTimer.Seconds > 3) { PmcStep = PmcSteps.AcLaserOff; } return; } else { EquipmentLogManager.Instance.WriteAttenuatorCalLog($"Laser off !!"); PmcStep = PmcSteps.AttenuatorCalEnd; } break; } case PmcSteps.AttenuatorCalEnd: { EquipmentLogManager.Instance.WriteAttenuatorCalLog($"Attenuator Cal end !!"); PmcStep = PmcSteps.Wait; break; } } } public bool ProcessStart() { if (TmcStep == TmcSteps.Wait && PmcStep == PmcSteps.Wait) { TmcStep = Sequence.TmcSteps.StatusCheck; return true; } else { return false; } } public bool ManualProcessStart() { if (PmcStep == PmcSteps.Wait) { PmcStep = Sequence.PmcSteps.MoveCenterPosition; return true; } else { return false; } } public bool ProcessStop() { TmcStep = TmcSteps.End; PmcStep = PmcSteps.End; return true; } public bool EnergyDropCheckStart() { if(PmcStep == PmcSteps.Wait) { PmcStep = PmcSteps.EnergyDropCheckStart; return true; } else { return false; } } public bool AttenuatorCalStart() { if (PmcStep == PmcSteps.Wait) { PmcStep = PmcSteps.AttenuatorCalStart; return true; } else { return false; } } public bool EnergyDropCheckStop() { if(PmcSteps.EnergyDropCheckStart <= PmcStep && PmcStep <= PmcSteps.EnergyDropCheckEnd) { PmcStep = PmcSteps.EdcLaserOff; return true; } else { return false; } } public bool AttenuatorCalStop() { if (PmcSteps.AttenuatorCalStart <= PmcStep && PmcStep <= PmcSteps.AttenuatorCalEnd) { PmcStep = PmcSteps.AcLaserOff; return true; } else { return false; } } } }