using Aitex.Core.RT.Device; using Aitex.Core.RT.Event; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Aitex.Sorter.Common; using MECF.Framework.Common.Device.Bases; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using FurnaceRT.Equipments.PMs; using FurnaceRT.Equipments.FIMSs; using FurnaceRT.Equipments.Systems; using static FurnaceRT.Equipments.FIMSs.FIMSModule; using Aitex.Core.Common; using System.Text.RegularExpressions; using Aitex.Core.RT.Device.Unit; namespace FurnaceRT.Equipments.WaferRobots { public class WaferRobotMap : ModuleRoutine, IRoutine { enum RoutineStep { Map, CheckBeforeMap, CheckAfterMap, CheckMappingFinish, } private ModuleName _mapFIMS; private int _slotNumber; private string _slotMap; private bool _isCompareWithSlotMap; private bool _isCreateWafer; private Hand _blade; private WaferRobotModule _waferRobotModule; private int _timeout = 0; private int _timeout2 = 10; private RD_TRIG _holdTrig = new RD_TRIG(); private R_TRIG _emergencyStopTrig = new R_TRIG(); private R_TRIG _pauseTrig = new R_TRIG(); private R_TRIG _resumeTrig = new R_TRIG(); private RoutineStep _routineStep; private double _durationTime = 0; private bool _isHasAlarm = false; private bool _needStartCheck = true; public WaferRobotMap(WaferRobotModule waferRobotModule) { _waferRobotModule = waferRobotModule; Module = waferRobotModule.Module; Name = "Map"; } public void Init(ModuleName mapFIMS, int slotNumber, Hand blade, string slotMap, bool isCompareWithSlotMap, bool isCreateWafer, bool isHasAlarm) { _mapFIMS = mapFIMS; _slotNumber = slotNumber; _blade = blade; _slotMap = slotMap; _isCompareWithSlotMap = isCompareWithSlotMap; _isCreateWafer = isCreateWafer; var para = new List { _mapFIMS, _slotNumber, _blade, slotMap, isCompareWithSlotMap, isCreateWafer, true };//增加参数true,表示执行过程中有alarm _waferRobotModule.MapFailAlarm.RetryMessage = (int)WaferRobotModule.MSG.MapRetry; _waferRobotModule.MapFailAlarm.RetryMessageParas = para.ToArray(); _waferRobotModule.MapTimeoutAlarm.RetryMessage = (int)WaferRobotModule.MSG.MapRetry; _waferRobotModule.MapTimeoutAlarm.RetryMessageParas = para.ToArray(); _isHasAlarm = isHasAlarm; if (!_isHasAlarm) _needStartCheck = true; } public Result Start(params object[] objs) { // 抛出过alarm就不reset if (!_isHasAlarm) { Reset(); } else { _historySteps.Remove((int)_routineStep); _isHasAlarm = false; ResetState(); } _holdTrig.RST = true; _emergencyStopTrig.RST = true; _pauseTrig.RST = true; _resumeTrig.RST = true; _timeout = SC.GetValue($"{Module}.PickTimeout"); if (_needStartCheck) { if (_mapFIMS == ModuleName.FIMS1 || _mapFIMS == ModuleName.FIMS2) { if (!Singleton.Instance.Modules.ContainsKey(_mapFIMS)) { _waferRobotModule.PickWaferFailAlarm.Set($"{_mapFIMS} is not install"); return Result.FAIL; } if (!CarrierManager.Instance.CheckHasCarrier(_mapFIMS, 0)) { _waferRobotModule.MapFailAlarm.Set($"no carrier at {_mapFIMS}"); return Result.FAIL; } var fims = Singleton.Instance.Modules[_mapFIMS] as FIMSModule; if (fims != null && !fims.CheckReadyForTransfer(ModuleHelper.Converter(Module), _blade, 0, EnumTransferType.Map, out string reason)) { _waferRobotModule.MapFailAlarm.Set(reason); return Result.FAIL; } fims.IsMapping = true; } if (ModuleHelper.IsPm(_mapFIMS)) { var pmModule = Singleton.Instance.Modules[_mapFIMS] as PMModule; if (pmModule != null && !pmModule.CheckReadyForTransfer(ModuleHelper.Converter(_waferRobotModule.Module), _blade, 0, EnumTransferType.Map, out string reason)) { _waferRobotModule.MapFailAlarm.Set(reason); return Result.FAIL; } } } Notify($"Start"); return Result.RUN; } public void Abort() { if (_mapFIMS == ModuleName.FIMS1 || _mapFIMS == ModuleName.FIMS2) (Singleton.Instance.Modules[_mapFIMS] as FIMSModule).IsMapping = false; _waferRobotModule.Stop(); } public override Result Monitor() { try { CheckBeforeMap((int)RoutineStep.CheckBeforeMap, _mapFIMS, _blade); Map((int)RoutineStep.Map, _mapFIMS, _blade, _timeout); CheckMappingFinish((int)RoutineStep.CheckMappingFinish, _mapFIMS, _timeout2); CheckAfterMap((int)RoutineStep.CheckAfterMap, _mapFIMS, _slotNumber, _slotMap, _isCompareWithSlotMap, _isCreateWafer); } catch (RoutineBreakException) { return Result.RUN; } catch (RoutineFaildException ex) { if (_mapFIMS == ModuleName.FIMS1 || _mapFIMS == ModuleName.FIMS2) (Singleton.Instance.Modules[_mapFIMS] as FIMSModule).IsMapping = false; return Result.FAIL; } if (_mapFIMS == ModuleName.FIMS1 || _mapFIMS == ModuleName.FIMS2) (Singleton.Instance.Modules[_mapFIMS] as FIMSModule).IsMapping = false; Notify("Finished"); return Result.DONE; } private void CheckAfterMap(int id, ModuleName mapModule, int slotNumber, string slotMap, bool isCompareWithSlotMap, bool isCreateWafer) { Tuple ret = Execute(id, () => { Notify("Check after map condition"); string reason = string.Empty; //_waferRobotModule.WaferRobotDevice.SlotMap = "1111111111111111111111111"; if (SC.GetValue($"System.IsSimulatorMode")) _waferRobotModule.WaferRobotDevice.SlotMap = "1111111111111111111111111"; int waferCount = _waferRobotModule.WaferRobotDevice.SlotMap.Length == 0 ? 0 : Regex.Matches(_waferRobotModule.WaferRobotDevice.SlotMap, "1").Count; //if (waferCount != slotNumber) //{ // _waferRobotModule.MapFailAlarm.Set($"Mapping result {waferCount} unequal to input number {slotNumber}"); // return false; //} if (isCompareWithSlotMap && string.IsNullOrEmpty(_waferRobotModule.WaferRobotDevice.SlotMap)) { _waferRobotModule.MapFailAlarm.Set($"Mapping result is null"); return false; } var carrier = CarrierManager.Instance.GetCarrier(mapModule, 0); if (carrier != null) { carrier.IsMapped = true; carrier.IsMapOK = true; } ModuleName originModule = ModuleName.System; WaferType waferType = WaferType.None; if (mapModule != ModuleName.PM1) { originModule = carrier.InternalModuleName; Enum.TryParse(carrier.CarrierType.ToString(), out waferType); } waferCount = 0; //"返回结果,格式:“MAP 1 0 D C 1 1” 1:单片,D:叠片 C:跨槽 0:无片" for (int i = 0; i < _waferRobotModule.WaferRobotDevice.SlotMap.Length; i++) { switch (_waferRobotModule.WaferRobotDevice.SlotMap[i]) { case '1': if (isCreateWafer) { if (WaferManager.Instance.CheckHasWafer(mapModule, i)) WaferManager.Instance.DeleteWafer(mapModule, i); WaferManager.Instance.CreateWafer(mapModule, i, originModule, i, WaferStatus.Normal, waferType); CarrierManager.Instance.UpdateWaferIn(originModule, 0, true); } waferCount++; break; case '0': if (isCreateWafer) { if (WaferManager.Instance.CheckHasWafer(mapModule, i)) WaferManager.Instance.DeleteWafer(mapModule, i); } break; case 'D': if (isCreateWafer) { if (WaferManager.Instance.CheckHasWafer(mapModule, i)) WaferManager.Instance.DeleteWafer(mapModule, i); WaferManager.Instance.CreateWafer(mapModule, i, originModule, i, WaferStatus.Double, waferType); CarrierManager.Instance.UpdateWaferIn(originModule, 0, true); } reason += $"slot={i + 1} double wafer\n"; break; case 'C': if (isCreateWafer) { if (WaferManager.Instance.CheckHasWafer(mapModule, i)) WaferManager.Instance.DeleteWafer(mapModule, i); WaferManager.Instance.CreateWafer(mapModule, i, originModule, i, WaferStatus.Crossed, waferType); CarrierManager.Instance.UpdateWaferIn(originModule, 0, true); } reason += $"slot={i + 1} crossed wafer\n"; break; } } if (!string.IsNullOrEmpty(reason)) { if (carrier != null) carrier.IsMapOK = false; _waferRobotModule.MapFailAlarm.Set(reason); return false; } //if (waferCount != slotNumber) //{ // if (carrier != null) // carrier.IsMapOK = false; // _waferRobotModule.MapFailAlarm.Set($"mapping result wafer count={waferCount}, set wafer count={slotNumber}, not match"); // return false; //} if (carrier != null) carrier.HasWaferIn = waferCount > 0; //if (isCompareWithSlotMap && slotMap != _waferRobotModule.WaferRobotDevice.SlotMap) //{ // if (carrier != null) // carrier.IsMapOK = false; // _waferRobotModule.MapFailAlarm.Set($"mapping result slot map={_waferRobotModule.WaferRobotDevice.SlotMap}, set slot map={slotMap}, not match"); // return false; //} return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } } _needStartCheck = false; } private void CheckBeforeMap(int id, ModuleName source, Hand blade) { Tuple ret = Execute(id, () => { Notify("Check map condition"); string reason = string.Empty; if (_waferRobotModule.WaferRobotDevice.IsError) { _waferRobotModule.MapFailAlarm.Set($"pick from {source} failed for robot error, error code={_waferRobotModule.WaferRobotDevice.ErrorCode}"); return false; } if (!_waferRobotModule.WaferRobotDevice.IsIdle) { _waferRobotModule.MapFailAlarm.Set($"pick from {source} failed for robot isn't Ready"); return false; } if (source == ModuleName.FIMS1 || source == ModuleName.FIMS2) { var stage = Singleton.Instance.Modules[source] as FIMSModule; if (stage == null && !stage.CheckReadyForTransfer(ModuleHelper.Converter(Module), _blade, 0, EnumTransferType.Map, out reason)) { _waferRobotModule.MapFailAlarm.Set(reason); return false; } } if (ModuleHelper.IsPm(source)) { var pmModule = Singleton.Instance.Modules[_mapFIMS] as PMModule; if (pmModule != null && !pmModule.CheckReadyForTransfer(ModuleHelper.Converter(_waferRobotModule.Module), _blade, 0, EnumTransferType.Map, out reason)) { _waferRobotModule.MapFailAlarm.Set(reason); return false; } } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } } _needStartCheck = false; } private void Map(int id, ModuleName source, Hand hand, int timeout) { _routineStep = (RoutineStep)Enum.Parse(typeof(RoutineStep), id.ToString()); Tuple ret = ExecuteAndWait(id, () => { Notify("Map"); string reason; if (!_waferRobotModule.RobotMap(source, hand, out reason)) { _waferRobotModule.MapFailAlarm.Set(reason); return false; } return true; }, () => { if (_waferRobotModule.WaferRobotDevice.IsReady() && !_waferRobotModule.WaferRobotDevice.IsError) { return true; } return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { //_waferRobotModule.MapFailAlarm.Description = $"{_waferRobotModule.WaferRobotDevice.ErrorCode}"; _waferRobotModule.MapFailAlarm.Set($"mapping {source} failed for robot error, error code={_waferRobotModule.WaferRobotDevice.ErrorCode}"); throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { //_waferRobotModule.PickWaferTimeoutAlarm.Description = $"timeout over {timeout} seconds"; _waferRobotModule.MapTimeoutAlarm.Set($"timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private void CheckMappingFinish(int id, ModuleName source, int timeout) { _routineStep = (RoutineStep)Enum.Parse(typeof(RoutineStep), id.ToString()); Tuple ret = ExecuteAndWait(id, () => { Notify("Check EX1/EX2 Home Position"); return true; }, () => { var sensor1 = DEVICE.GetDevice($"PM1.SensorWaferRobotEX1AxisHomePosition"); var sensor2 = DEVICE.GetDevice($"PM1.SensorWaferRobotEX2AxisHomePosition"); if (sensor1 != null && sensor1.Value && sensor2 != null && sensor2.Value) { return true; } return false; }, timeout * 1000); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else if (ret.Item2 == Result.TIMEOUT) //timeout { //_waferRobotModule.PickWaferTimeoutAlarm.Description = $"timeout over {timeout} seconds"; _waferRobotModule.MapTimeoutAlarm.Set($"check wafer robot EX1/EX2 home position timeout over {timeout} seconds"); throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } } }