using Aitex.Core.RT.IOCore; using Aitex.Core.RT.Log; using Aitex.Core.Util; using System; using System.Xml; namespace EFEM.RT.Devices.Flipper { public class JetFlipper : FlipperBase { private DIAccessor _diIsOrigin;//是否在原点即0°-- IsOrigin==true && IsHorizontal==true为0° private DIAccessor _diIsHorizontal;//是否在水平 -- IsOrigin==false && IsHorizontal==true为180° private DIAccessor _diIsTurnOK;//是否在旋转中 private DIAccessor _diIsClampOK;//是否在Clamp中 private DIAccessor _diTurnOverMotorAlarm;//无法旋转警告 private DIAccessor _diEnableToRobot;//是否Robot可伸向 private DIAccessor _diIsClampOpen;//是否打开Clamp(UnGrip) private DIAccessor _diIsClampClose;//是否关闭Clamp(Grip) private DIAccessor _diClampMotorAlarm;//无法夹紧警告 private DOAccessor _doTurnOverRunMode;//旋转模式 -- TurnHome_START_STOP==true && TurnOverRunMode=false旋转到0° private DOAccessor _doTurnHome_START_STOP;//开始/停止动作,取决于Run Mode -- TurnHome_START_STOP==true && TurnOverRunMode=true 旋转到180° private DOAccessor _doTurnOverPositionA;//转到预设角度A private DOAccessor _doTurnOverPositionB;//转到预设角度B private DOAccessor _doTurnOverPositionC;//转到预设角度C private DOAccessor _doClampRunMode;//Clamp模式 -- ClampHome_START_STOP==true && ClampRunMode=false为Clamp关闭 private DOAccessor _doClampHome_START_STOP;//Clamp开始/停止动作 -- ClampHome_START_STOP==true && ClampRunMode=true为Clamp打开 private DOAccessor _doClampPositionA;//到预设位置A private DOAccessor _doClampPositionB;//到预设位置B private DOAccessor _doClampPositionC;//到预设位置C private DOAccessor _doClearClampAlarm;//清除Clamp警告 private DOAccessor _doClearTurnOverAlarm;//清除TurnOver警告 private DOAccessor _doTurnOverJOGP;//TurnOver JogP private DOAccessor _doTurnOverJOGN;//TurnOver JogN private DOAccessor _doTurnOverJOG0;//TurnOver 设置原点位 private DOAccessor _doClampJOGP;//Clamp JogP private DOAccessor _doClampJOGN;//Clamp JogN private DOAccessor _doClampJOG0;//Clamp 设置原点位(前提ClampClosed) private bool _NotFlipped => _diIsOrigin.Value && _diIsHorizontal.Value; private string _module; private FlipperState _state; private DeviceTimer _timer; private bool _targetClampON; private string jogNP; public override bool IsBusy => !_diIsTurnOK.Value || !_diIsClampOK.Value;//旋转且夹紧完成 public override bool IsError => !_diClampMotorAlarm.Value || !_diTurnOverMotorAlarm.Value; public override bool IsReadyForRobot => _diEnableToRobot.Value;//是否Robot可以向Flipper取放 public override bool IsClampOpen => _diIsClampOpen.Value;//是否打开 public override bool IsClampClose => _diIsClampClose.Value;//是否打开 public bool IsFlipperOrigin => _diIsOrigin.Value && _diIsHorizontal.Value;//是否在原点(0°) public bool IsFlipperHorizontal => _diIsHorizontal.Value && !_diIsOrigin.Value;//是否在反面(180°) public bool IsFlipperOverOrigin => _diIsOrigin.Value;//是否反转(UI) public override FlipperState State => _state; public R_TRIG _trigError = new R_TRIG(); //flipper的业务主要分为3件事 //clamp //TurnOver //Home/Initialize public JetFlipper(string module, XmlElement node, string ioModule = "") { base.Module = (string.IsNullOrEmpty(node.GetAttribute("module")) ? module : node.GetAttribute("module")); base.Name = node.GetAttribute("id"); base.Display = node.GetAttribute("display"); base.DeviceID = node.GetAttribute("schematicId"); //Name = module.ToString(); _module = module; _state = FlipperState.Init; _diIsOrigin = ParseDiNode("diFlipperTurnOverOriginSensor", node, ioModule); _diIsHorizontal = ParseDiNode("diFlipperTurnOverHorizontalSensor", node, ioModule); _diIsTurnOK = ParseDiNode("diFlipperTurnOverMotorPosCompleted", node, ioModule); _diTurnOverMotorAlarm = ParseDiNode("diFlipperTurnOverMotorAlarm", node, ioModule); _diEnableToRobot = ParseDiNode("diFlipperEnableToRobot", node, ioModule); _diIsClampClose = ParseDiNode("diFlipperClampClosedSensor", node, ioModule); _diIsClampOpen = ParseDiNode("diFlipperClampOpenedSensor", node, ioModule); _diIsClampOK = ParseDiNode("diFlipperClampMotorPosCompleted", node, ioModule); _diClampMotorAlarm = ParseDiNode("diFlipperClampMotorAlarm", node, ioModule); _doTurnOverRunMode = ParseDoNode("doFlipperTurnOverMotorModeSW", node, ioModule); _doClampRunMode = ParseDoNode("doFlipperClampMotorModeSW", node, ioModule); _doTurnHome_START_STOP = ParseDoNode("doFlipperTurnOverStartStop", node, ioModule); _doClampHome_START_STOP = ParseDoNode("doFlipperClampSTARTSTOP", node, ioModule); _doTurnOverPositionA = ParseDoNode("doFlipperTurnOverSEL0", node, ioModule); _doTurnOverPositionB = ParseDoNode("doFlipperTurnOverSEL1", node, ioModule); _doTurnOverPositionC = ParseDoNode("doFlipperTurnOverSEL2", node, ioModule); _doClampPositionA = ParseDoNode("doFlipperClampSEL0", node, ioModule); _doClampPositionB = ParseDoNode("doFlipperClampSEL1", node, ioModule); _doClampPositionC = ParseDoNode("doFlipperClampSEL2", node, ioModule); _doClearClampAlarm = ParseDoNode("doFlipperClampPGMRES", node, ioModule); _doClearTurnOverAlarm = ParseDoNode("doFlipperTurnOverPgmres", node, ioModule); _doTurnOverJOGP = ParseDoNode("doFlipperTurnOverSEL0", node, ioModule); _doTurnOverJOGN = ParseDoNode("doFlipperTurnOverSEL1", node, ioModule); _doTurnOverJOG0 = ParseDoNode("doFlipperTurnOverSEL2", node, ioModule); _doClampJOGP = ParseDoNode("doFlipperClampSEL0", node, ioModule); _doClampJOGN = ParseDoNode("doFlipperClampSEL1", node, ioModule); _doClampJOG0 = ParseDoNode("doFlipperClampSEL2", node, ioModule); _timer = new DeviceTimer(); } public override bool Home() { //在夹子关闭的状态下方可执行 否则在旋转过程中可能会导致wafer滑落 //IO中已有interlock 是否拦两层? //整Home动作不能直接一个命令 应该分为两组 首先是闭合确认 然后是旋转home //LogObject.Error(_module.ToString(), $"flipper HOME:status = {_state}."); if (_state == FlipperState.Init || _state == FlipperState.Idle || _state == FlipperState.Error || _state == FlipperState.Gripping) { string reason = ""; LOG.Info($"{_module.ToString()}: Home start"); _state = FlipperState.Homing; return true; //超时时间60s //_timer.Start(60000); } else { _trigError.CLK = true; _state = FlipperState.Error; LOG.Error($"{_module.ToString()}: Home failed. Status:{_state}."); return false; } } public override void Monitor() { try { //超时就直接错误 //if (_timer.IsTimeout()) // _state = FlipperState.Error; switch (State) { case FlipperState.Gripping: if (IsClampClose) { _doClampRunMode.SetValue(false, out _); _doClampHome_START_STOP.SetValue(false, out _); _state = FlipperState.Idle; LOG.Info($"{_module.ToString()}: Grip is completed"); } else { //_doClampHome_START_STOP.SetValue(true, out _); _doClampRunMode.SetValue(false, out _); _doClampHome_START_STOP.SetValue(true, out _); } break; case FlipperState.UnGripping: if (IsClampOpen) { _doClampRunMode.SetValue(false, out _); _doClampHome_START_STOP.SetValue(false, out _); _state = FlipperState.Idle; LOG.Info($"{_module.ToString()}: UnGrip is completed"); } else { _doClampRunMode.SetValue(true, out _); _doClampHome_START_STOP.SetValue(true, out _); //_doClampPositionA.SetValue(true, out _); } break; case FlipperState.TurnOverJog: if (jogNP == "P") { _doTurnOverJOGP.SetValue(true, out _); } else { _doTurnOverJOGN.SetValue(true, out _); } break; case FlipperState.TurnOverJogStop: if (jogNP == "P") { _doTurnOverJOGP.SetValue(false, out _); } else { _doTurnOverJOGN.SetValue(false, out _); } _state = FlipperState.Idle; break; case FlipperState.Turning: //_diIsHorizontal = true and _diIsOrigin = true: 0° //_diIsHorizontal = true and _diIsOrigin = false: 180° if (_diIsHorizontal.Value && !_diIsOrigin.Value)//180° { _doTurnOverRunMode.SetValue(false, out _); _doTurnHome_START_STOP.SetValue(false, out _); _state = FlipperState.Idle; } else { _doTurnOverRunMode.SetValue(true, out _); _doTurnHome_START_STOP.SetValue(true, out _); } break; case FlipperState.Homing: if (_diIsHorizontal.Value && _diIsOrigin.Value)//0°为Home位置 { _doTurnOverRunMode.SetValue(false, out _); _doTurnHome_START_STOP.SetValue(false, out _); _state = FlipperState.Idle; } else { _doTurnOverRunMode.SetValue(false, out _); _doTurnHome_START_STOP.SetValue(true, out _); } break; case FlipperState.Idle: _doClampRunMode.SetValue(false, out _); _doClampHome_START_STOP?.SetValue(false, out _); _doTurnOverRunMode.SetValue(false, out _); _doTurnHome_START_STOP.SetValue(false, out _); break; default: break; } //如果是错误 _trigError.CLK = State == FlipperState.Error; //DO_SafetytoFLP触发(待添加) if (_diIsHorizontal.Value && _diIsClampOpen.Value && _diEnableToRobot.Value) { //+ Safety to FLP sw interlock逻辑 } } catch (Exception ex) { LOG.Error($"{_module.ToString()}: {ex}"); } } public override bool TurnOver() { if (_state == FlipperState.Idle && IsClampClose) { if (_NotFlipped) _state = FlipperState.Turning; else _state = FlipperState.Homing; LOG.Info($"{_module.ToString()}: Turn over start"); return true; //超时时间60s //_timer.Start(60000); } else { if (_state != FlipperState.Idle) { LOG.Error($"{_module.ToString()}: Turn over failed. Status:{_state}"); } if (!IsClampClose) { LOG.Error($"{_module.ToString()}: Turn over failed. Clamp is not closed"); } _trigError.CLK = true; _state = FlipperState.Error; return false; } } public override bool Clamp(bool ClampOn) { _targetClampON = ClampOn; if (_state == FlipperState.Idle || _state == FlipperState.Init) { //关闭 if (ClampOn) { LOG.Info($"{_module.ToString()}: Clamp start"); _state = FlipperState.Gripping; } //打开 else { LOG.Info($"{_module.ToString()}: UnClamp start"); _state = FlipperState.UnGripping; } return true; } else { LOG.Error($"{_module.ToString()}: Clamp failed. Status:{_state}"); return false; } } public bool TrunOverJog(string NorP) { LOG.Info($"{_module.ToString()}: TurnOverJog-{NorP} start"); jogNP = NorP; if (jogNP == "P") { _state = FlipperState.TurnOverJog; } else { _state = FlipperState.TurnOverJog; } return true; } public bool TrunOverJogStop(string NorP) { LOG.Info($"{_module.ToString()}: TurnOverJog-{NorP} stop"); jogNP = NorP; if (jogNP == "P") { _state = FlipperState.TurnOverJogStop; } else { _state = FlipperState.TurnOverJogStop; } return true; } public override void Reset() { //错误条件下方可执行 if (State == FlipperState.Error) { string error_reason; if (_doClearClampAlarm.SetValue(false, out error_reason) && _doClearTurnOverAlarm.SetValue(false, out error_reason)) { _trigError.RST = true;//清除错误 _state = FlipperState.Idle;//可以直接出状态 } else { LOG.Error($"{_module.ToString()}: Clear error failed. Reason:{error_reason}"); } } _state = FlipperState.Idle; } public override void ShowAction() { LOG.Info($"{_module.ToString()}: TurnOver complete:{_diIsTurnOK.Value}, Clamp complete:{_diIsClampOK.Value}"); } public bool IsEnableTransferWafer(out string reason) { reason = ""; return true; } } }