using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Device; using Aitex.Core.RT.Log; using Aitex.Core.RT.OperationCenter; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using MECF.Framework.Common.Algorithm; using MECF.Framework.Common.Beckhoff.ModuleIO; using MECF.Framework.Common.CommonData.Prewet; using MECF.Framework.Common.Device.ResistivityProbe; using MECF.Framework.Common.Device.Rinse; using MECF.Framework.Common.Persistent.Prewet; using MECF.Framework.Common.Persistent.Rinse; using MECF.Framework.Common.RecipeCenter; using MECF.Framework.Common.ToolLayout; using MECF.Framework.Common.TwinCat; using System.Collections.Generic; using System.Reflection; using CyberX8_RT.Modules; using CyberX8_RT.Modules.Rinse; using CyberX8_RT.Devices.Resistivity; using CyberX8_RT.Modules.Prewet; using MECF.Framework.Common.IOCore; namespace CyberX8_RT.Devices.Rinse { public class RinseDevice : BaseDevice, IDevice { private enum RinseOperation { None } #region 常量 private const string WATER_LEVEL="WaterLevel"; private const string WAFER_HOLDER_CLAMP="WaferHolderClamp"; private const string N2_VALVE="N2Valve"; private const string FILL_VALVE="FillValve"; private const string DRAIN_VALVE="DrainValve"; private const string WASTE_VALVE="WasteValve"; private const string RESISTIVITY="Resistivity"; private const string PERSISTENT_VALUE = "PersistentValue"; private const string RINSEDATA = "RinseData"; private const string RINSEITEM = "RinseItem"; private const string RESISTIVITYVALUE = "Resistivity"; #endregion #region 内部变量 /// /// 数据 /// private RinseData _rinseData = new RinseData(); /// /// Rinse 持久性数值对象 /// private RinsePersistentValue _rinsePersistentValue; /// /// 变量是否初始化字典 /// private Dictionary _variableInitializeDic = new Dictionary(); /// /// ByPass Inter Locks /// private bool _bypassInterLocks = false; /// /// RinseItem /// private RinseItem _rinseItem = new RinseItem(); /// /// 工艺当前执行小步骤 /// private string _currentStateMachine = "Init"; /// /// 工艺当前执行大步骤 /// private string _currentStatus = "Init"; /// /// 水阻值 /// private double _resistivityValue; /// /// 水阻计控制器 /// private ResistivityController _resistivityController; #endregion #region 属性 /// /// Rinse数据 /// public RinseData RinseData { get { return _rinseData; } } /// /// 所有io变量是否初始化 /// public bool IOInitialized { get { return AllIoVariableInitialized(); } } /// /// 所有io变量是否初始化 /// public RinseItem RinseItem { get { return _rinseItem; } } /// /// 当前状态机 /// public string CurrentStateMachine { get { return _currentStateMachine; } } #endregion /// /// 构造函数 /// /// /// public RinseDevice(string moduleName) : base(moduleName, moduleName, moduleName, moduleName) { } /// /// 初始化 /// /// public bool Initialize() { SubscribeData(); SubscribeValueAction(); InitializeOperation(); return true; } /// /// 订阅数据 /// private void SubscribeData() { _rinsePersistentValue = RinsePersistentManager.Instance.GetRinsePersistentValue(Module); if (_rinsePersistentValue == null) { LOG.WriteLog(eEvent.ERR_RINSE, Module, "Persistent Value Object is not exist"); } _rinseItem = RinseItemManager.Instance.GetRinseItem(Module); _resistivityController = DEVICE.GetDevice(RinseItem.ResistivityID); DATA.Subscribe($"{Module}.{PERSISTENT_VALUE}", () => _rinsePersistentValue,SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.{RINSEDATA}", () => _rinseData, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.CurrentStateMachine", () => _currentStateMachine, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.CurrentStatus", () => _currentStatus, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.Resistivity.ID", () => _resistivityController != null ? _resistivityController.Module : "", SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.{RESISTIVITYVALUE}", () => { if (_resistivityController != null) { string value = _resistivityController.ResisitivityValue; if(double.TryParse(value, out _resistivityValue)) { return _resistivityValue; } else { return 0; } } else { return 0; } }, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.WaterLevel", () => RinseData.WaterLevel, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.DIFillEnable",()=>RinseData.FillValve, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.DrainEnable", () => RinseData.DrainValve, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.N2Enable",()=>RinseData.N2Valve, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.WaferShuttleClamped",()=>RinseData.WaferHolderClamp, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.WasteEnable", () => RinseData.WasteValve, SubscriptionAttribute.FLAG.IgnoreSaveDB); } /// /// 订阅变量数值发生变化 /// private void SubscribeValueAction() { BeckhoffIoSubscribeUpdateVariable(WATER_LEVEL); BeckhoffIoSubscribeUpdateVariable(WASTE_VALVE); BeckhoffIoSubscribeUpdateVariable(WAFER_HOLDER_CLAMP); BeckhoffIoSubscribeUpdateVariable(N2_VALVE); BeckhoffIoSubscribeUpdateVariable(FILL_VALVE); BeckhoffIoSubscribeUpdateVariable(DRAIN_VALVE); } /// /// 初始化Operation /// private void InitializeOperation() { OP.Subscribe($"{Module}.ClampValveOn", (cmd, args) => { return WaferHolderClampValveOn(); }); OP.Subscribe($"{Module}.ClampValveOff", (cmd, args) => { return WaferHolderClampValveOff(); }); OP.Subscribe($"{Module}.N2ValveOn", (cmd, args) => { return N2ValveOn(); }); OP.Subscribe($"{Module}.N2ValveOff", (cmd, args) => { return N2ValveOff(); }); OP.Subscribe($"{Module}.FillValveOn", (cmd, args) => { return FillValveOn(); }); OP.Subscribe($"{Module}.FillValveOff", (cmd, args) => { return FillValveOff(); }); OP.Subscribe($"{Module}.DrainValveOn", (cmd, args) => { return DrainValveOn(); }); OP.Subscribe($"{Module}.DrainValveOff", (cmd, args) => { return DrainValveOff(); }); OP.Subscribe($"{Module}.WasteValveOn", (cmd, args) => { return WasteValveOff() ;}); OP.Subscribe($"{Module}.WasteValveOff", (cmd, args) => { return WasteValveOn() ;}); OP.Subscribe($"{Module}.ByPassInterLocks", (cms, args) => { _bypassInterLocks = (bool)(args[0]); return true; }); OP.Subscribe($"{Module}.DisabledAction", DisabledOperation); OP.Subscribe($"{Module}.ManualAction", ManualOperation); OP.Subscribe($"{Module}.AutoAction", AutoOperation); OP.Subscribe($"{Module}.EngineeringModeAction", EngineeringModeOperation); OP.Subscribe($"{Module}.ProductionModeAction", ProductionModeOperation); } /// /// 订阅IO变量 /// /// private void BeckhoffIoSubscribeUpdateVariable(string variable) { _variableInitializeDic[variable] = false; IOModuleManager.Instance.SubscribeModuleVariable(Module, variable, UpdateVariableValue); } /// /// 更新变量数值 /// /// /// private void UpdateVariableValue(string variable, object value) { if (!RinseData.IsDataInitialized) { RinseData.IsDataInitialized = true; } PropertyInfo property = RinseData.GetType().GetProperty(variable); if (property != null) { property.SetValue(RinseData, value); } if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable]) { _variableInitializeDic[variable] = true; } } /// /// 是否所有IO变量初始化完成 /// /// private bool AllIoVariableInitialized() { foreach (string item in _variableInitializeDic.Keys) { if (!_variableInitializeDic[item]) { LOG.WriteLog(eEvent.ERR_DRYER, Module, $"{item} is not initialized"); return false; } } return true; } #region Operation /// /// DisabledAction /// /// /// /// private bool DisabledOperation(string cmd, object[] args) { string currentOperation = "Disabled"; RinseEntity rinseEntity = Singleton.Instance.GetModule(Module); if (rinseEntity == null || _rinsePersistentValue == null) return false; if (_rinsePersistentValue.OperatingMode != "Disabled") rinseEntity.EnterInit(); _rinsePersistentValue.OperatingMode = currentOperation; RinsePersistentManager.Instance.UpdatePersistentValue(Module); return true; } /// /// ManualAction /// /// /// /// private bool ManualOperation(string cmd, object[] args) { string currentOperation = "Manual"; RinseEntity rinseEntity = Singleton.Instance.GetModule(Module); if (rinseEntity == null || _rinsePersistentValue == null) return false; if (_rinsePersistentValue.OperatingMode == "Auto" && rinseEntity.IsBusy) { LOG.WriteLog(eEvent.ERR_RINSE, Module, $"{Module} is Busy, can't change to manual mode"); return false; } if (_rinsePersistentValue.OperatingMode != "Manual") rinseEntity.EnterInit(); _rinsePersistentValue.OperatingMode = currentOperation; RinsePersistentManager.Instance.UpdatePersistentValue(Module); return true; } /// /// AutoAction /// /// /// /// private bool AutoOperation(string cmd, object[] args) { string currentOperation = "Auto"; RinseEntity rinseEntity = Singleton.Instance.GetModule(Module); if (rinseEntity == null || _rinsePersistentValue == null) return false; if (_rinsePersistentValue.OperatingMode != "Auto") rinseEntity.EnterInit(); _rinsePersistentValue.OperatingMode = currentOperation; RinsePersistentManager.Instance.UpdatePersistentValue(Module); return true; } /// /// EngineeringModeAction /// /// /// /// private bool EngineeringModeOperation(string cmd, object[] args) { string currentRecipeOperation = "Engineering"; _rinsePersistentValue.RecipeOperatingMode = currentRecipeOperation; RinsePersistentManager.Instance.UpdatePersistentValue(Module); return true; } /// /// ProductionAction /// /// /// /// private bool ProductionModeOperation(string cmd, object[] args) { string currentRecipeOperation = "Production"; _rinsePersistentValue.RecipeOperatingMode = currentRecipeOperation; RinsePersistentManager.Instance.UpdatePersistentValue(Module); return true; } #endregion /// /// 更新当前工艺小步骤 /// /// public void UpdateStateMachine(string tmp) { _currentStateMachine = tmp; } /// /// 更新当前工艺大步骤 /// /// public void UpdateStatus(string tmp) { _currentStatus = tmp; } #region Wafer Holder Clamp Valve /// /// Wafer Holder Clamp Valve On /// /// public bool WaferHolderClampValveOn() { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WAFER_HOLDER_CLAMP}"); return IOModuleManager.Instance.WriteIoValue(ioName, true); } /// /// Wafer Holder Clamp Valve Off /// /// public bool WaferHolderClampValveOff() { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WAFER_HOLDER_CLAMP}"); return IOModuleManager.Instance.WriteIoValue(ioName, false); } #endregion #region N2 Valve /// /// N2 Valve On /// /// public bool N2ValveOn() { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{N2_VALVE}"); return IOModuleManager.Instance.WriteIoValue(ioName, true); } /// /// N2 Valve Off /// /// public bool N2ValveOff() { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{N2_VALVE}"); return IOModuleManager.Instance.WriteIoValue(ioName, false); } #endregion #region Fill Valve /// /// Fill Valve On /// /// public bool FillValveOn() { if(!_bypassInterLocks) { //Clamp Status必须为Clamped if(!_rinseData.WaferHolderClamp) { LOG.WriteLog(eEvent.ERR_RINSE, Module, "Clamp Status is not Clamped"); return false; } } string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{FILL_VALVE}"); return IOModuleManager.Instance.WriteIoValue(ioName, true); } /// /// Fill Valve Off /// /// public bool FillValveOff() { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{FILL_VALVE}"); return IOModuleManager.Instance.WriteIoValue(ioName, false); } #endregion #region Drain Valve /// /// Drain Valve On /// /// public bool DrainValveOn() { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{DRAIN_VALVE}"); return IOModuleManager.Instance.WriteIoValue(ioName, true); } /// /// Drain Valve Off /// /// public bool DrainValveOff() { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{DRAIN_VALVE}"); return IOModuleManager.Instance.WriteIoValue(ioName, false); } #endregion #region Waste Valve /// /// Waste Valve On /// /// public bool WasteValveOn() { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WASTE_VALVE}"); return IOModuleManager.Instance.WriteIoValue(ioName, true); } /// /// Waste Valve Off(等价于Metal Valve On) /// /// public bool WasteValveOff() { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WASTE_VALVE}"); return IOModuleManager.Instance.WriteIoValue(ioName, false); } #endregion public void Monitor() { } public void Reset() { } public void Terminate() { } } }