using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Device; using Aitex.Core.RT.Log; using Aitex.Core.RT.OperationCenter; using Aitex.Core.RT.SCCore; using MECF.Framework.Common.Beckhoff.ModuleIO; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.TwinCat; using CyberX8_Core; using System; using System.Collections.Generic; using Aitex.Core.Util; using MECF.Framework.Common.IOCore; namespace CyberX8_RT.Devices.PUF { public class PufVacuum : BaseDevice, IDevice { #region 常量 private const string CHUCKA_VAC = "ChuckAVac"; private const string CHUCKB_VAC = "ChuckBVac"; private const string CHUCKA_RELEASE = "ChuckARelease"; private const string CHUCKB_RELEASE = "ChuckBRelease"; private const string CHUCKA_VACUUM_STATUS = "ChuckAVacuumStatus"; private const string CHUCKB_VACUUM_STATUS = "ChuckBVacuumStaus"; private const string CHUCKA = "ChuckA"; private const string CHUCKB = "ChuckB"; private const string VACUUM_LEAK = "VacuumLeak"; #endregion #region 内部变量 private bool _chuckAWaferPresent; private bool _chuckBWaferPresent; private bool _chuckAReleased; private bool _chuckBReleased; private double _chuckAValue; private double _chuckBValue; private double _chuckVacuumCloseLimit; private double _chuckVacuumOpenLimit; private double _chuckVacuumWaferAbsent; private double _chuckVacuumWaferPresent; private string _chuckAVacuumStatus = ""; private string _chuckBVacuumStatus = ""; private DateTime _leakADateTime = DateTime.Now; private System.Timers.Timer _leakATimer; private DateTime _leakBDateTime = DateTime.Now; private System.Timers.Timer _leakBTimer; /// /// 变量是否初始化字典 /// private Dictionary _variableInitializeDic = new Dictionary(); /// /// 首次加载数据成功 /// private bool _firstLoad = false; #endregion #region 属性 /// /// ChuckA Wafer Present状态 /// public bool ChuckAWaferPresent { get { return _chuckAWaferPresent; } set { _chuckAWaferPresent = value; } } /// /// ChuckB Wafer Present /// public bool ChuckBWaferPresent { get { return _chuckBWaferPresent; } set { _chuckBWaferPresent = value; } } /// /// Side A Vacuum状态 /// public string ChuckAVacuumStatus { get { return _chuckAVacuumStatus; } } /// /// Side B Vacuum状态 /// public string ChuckBVacuumStatus { get { return _chuckBVacuumStatus; } } /// /// Side B 是否关闭真空 /// public bool ISChuckBReleased { get { return _chuckBReleased; } } /// /// Side A是否关闭真空 /// public bool IsChuckAReleased { get { return _chuckAReleased; } } /// /// 所有io变量是否初始化 /// public bool IOInitialized { get { return AllIoVariableInitialized(); } } #endregion #region 事件 public event EventHandler OnVacuumLeak; public event EventHandler OnVacuumResume; #endregion /// /// 构造函数 /// /// public PufVacuum(string moduleName):base(moduleName,"Vacuum","Vacuum","Vacuum") { LoadConfigParameter(); _leakATimer = new System.Timers.Timer(500); _leakATimer.Elapsed += LeakATimer_Elapsed; _leakBTimer=new System.Timers.Timer(500); _leakBTimer.Elapsed += LeakBTimer_Elapsed; } /// /// 加载配置参数 /// private void LoadConfigParameter() { _chuckVacuumCloseLimit = SC.GetValue($"{Module}.ChuckVacuumCloseLimit"); _chuckVacuumOpenLimit = SC.GetValue($"{Module}.ChuckVacuumOpenLimit"); _chuckVacuumWaferAbsent = SC.GetValue($"{Module}.ChuckVacuumWaferAbsent"); _chuckVacuumWaferPresent = SC.GetValue($"{Module}.ChuckVacuumWaferPresent"); } /// /// Leak定时器 /// /// /// /// private void LeakATimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { if(DateTime.Now.Subtract(_leakADateTime).TotalSeconds>=2) { _chuckAVacuumStatus = VACUUM_LEAK; LOG.WriteLog(eEvent.ERR_PUF, Module, $"ChuckA vacuum leak"); if (OnVacuumLeak != null) { OnVacuumLeak(this, Module); } _leakATimer.Stop(); } } /// /// LeakB定时器 /// /// /// /// private void LeakBTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { if (DateTime.Now.Subtract(_leakBDateTime).TotalSeconds >= 2) { _chuckBVacuumStatus = VACUUM_LEAK; LOG.WriteLog(eEvent.ERR_PUF, Module, $"ChuckB vacuum leak"); if (OnVacuumLeak != null) { OnVacuumLeak(this, Module); } _leakBTimer.Stop(); } } /// /// 初始化 /// /// public bool Initialize() { SubscribeData(); InitializeOperation(); SubscribeValueAction(); return true; } /// /// 初始化操作 /// private void InitializeOperation() { OP.Subscribe($"{Module}.{PufMotionVaccumOpertaion.VacuumAOn}", VaccumAOnOperation); OP.Subscribe($"{Module}.{PufMotionVaccumOpertaion.VacuumBOn}", VaccumBOnOperation); } /// /// 订阅变量数值发生变化 /// private void SubscribeValueAction() { BeckhoffIoSubscribeUpdateVariable(CHUCKA_VAC); BeckhoffIoSubscribeUpdateVariable(CHUCKB_VAC); BeckhoffIoSubscribeUpdateVariable(CHUCKA_RELEASE); BeckhoffIoSubscribeUpdateVariable(CHUCKB_RELEASE); } /// /// 订阅IO变量 /// /// private void BeckhoffIoSubscribeUpdateVariable(string variable) { _variableInitializeDic[variable] = false; IOModuleManager.Instance.SubscribeModuleVariable($"{Module}", variable, UpdateVariableValue); } /// /// 是否所有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; } /// /// 订阅数据 /// private void SubscribeData() { DATA.Subscribe($"{Module}.{CHUCKA_RELEASE}", () => _chuckAReleased,SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.{CHUCKB_RELEASE}", () => _chuckBReleased, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.{CHUCKA_VAC}", () => _chuckAValue, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.{CHUCKB_VAC}", () => _chuckBValue, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.{CHUCKA_VACUUM_STATUS}", () => _chuckAVacuumStatus, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.{CHUCKB_VACUUM_STATUS}", () => _chuckBVacuumStatus, SubscriptionAttribute.FLAG.IgnoreSaveDB); } /// 更新变量数值 /// /// /// private void UpdateVariableValue(string variable, object value) { if(!_firstLoad) { _firstLoad = true; VacuumAOn(); VacuumBOn(); } if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable]) { _variableInitializeDic[variable] = true; } if (variable == $"{CHUCKA_RELEASE}") { _chuckAReleased = (bool)value; var item = JudgeWaferPresent(_chuckAValue, _chuckAReleased, CHUCKA); _chuckAWaferPresent = item.Item1; _chuckAVacuumStatus = item.Item2; if (_chuckAVacuumStatus != VACUUM_LEAK && item.Item2 == VACUUM_LEAK) { _leakADateTime = DateTime.Now; _leakATimer.Start(); } else if (item.Item2 != VACUUM_LEAK) { _leakBTimer.Stop(); } } else if(variable==$"{CHUCKB_RELEASE}") { _chuckBReleased=(bool)value; var item = JudgeWaferPresent(_chuckBValue, _chuckBReleased, CHUCKB); if (_chuckBVacuumStatus != VACUUM_LEAK && item.Item2 == VACUUM_LEAK) { _leakBDateTime = DateTime.Now; _leakBTimer.Start(); } else if (item.Item2 != VACUUM_LEAK) { _leakBTimer.Stop(); } _chuckBWaferPresent = item.Item1; _chuckBVacuumStatus = item.Item2; } else if(variable==$"{CHUCKA_VAC}") { _chuckAValue = (double)value; var item = JudgeWaferPresent(_chuckAValue, _chuckAReleased, CHUCKA); if(_chuckAVacuumStatus!= VACUUM_LEAK&&item.Item2== VACUUM_LEAK) { _leakADateTime = DateTime.Now; _leakATimer.Start(); } else if (item.Item2 != VACUUM_LEAK) { _leakATimer.Stop(); } _chuckAWaferPresent =item.Item1; _chuckAVacuumStatus=item.Item2; } else if(variable==$"{CHUCKB_VAC}") { _chuckBValue=(double)value; var item = JudgeWaferPresent(_chuckBValue, _chuckBReleased, CHUCKB); if (_chuckBVacuumStatus != VACUUM_LEAK && item.Item2 == VACUUM_LEAK) { _leakBDateTime = DateTime.Now; _leakBTimer.Start(); } else if(item.Item2!=VACUUM_LEAK) { _leakBTimer.Stop(); } _chuckBWaferPresent = item.Item1; _chuckBVacuumStatus = item.Item2; } } /// /// 判定Wafer Present /// /// /// /// private (bool,string) JudgeWaferPresent(double chuckValue,bool chuckRelease,string chuck) { LoadConfigParameter(); if (!chuckRelease) { if(chuckValue < _chuckVacuumWaferPresent) { ResumeVacuum(); return (true,"WaferPresent"); } else if( chuckValue > _chuckVacuumWaferAbsent) { ResumeVacuum(); return (false,"WaferAbsent"); } else { return (false,"InvalidData"); } } else { if(chuckValue<=_chuckVacuumCloseLimit) { return (false,"VacuumLeak"); } else if(chuckValue<=_chuckVacuumOpenLimit) { ResumeVacuum(); return (false, "VacuumOff"); } else { ResumeVacuum(); return (false, ""); } } } /// /// 故障恢复 /// private void ResumeVacuum() { if (OnVacuumResume != null) { OnVacuumResume(this, Module); } } /// /// VacuumAOn操作 /// /// /// /// private bool VaccumAOnOperation(string cmd, object[] args) { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKA_RELEASE}"); if(!string.IsNullOrEmpty(ioName)) { IOModuleManager.Instance.WriteIoValue(ioName, args[1]); } return true; } /// /// VacuumBOn操作 /// /// /// /// private bool VaccumBOnOperation(string cmd, object[] args) { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKB_RELEASE}"); if (!string.IsNullOrEmpty(ioName)) { IOModuleManager.Instance.WriteIoValue(ioName, args[1]); } return true; } /// /// VacuumA关闭 /// public bool VacuumAOff() { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKA_RELEASE}"); if (!string.IsNullOrEmpty(ioName)) { return IOModuleManager.Instance.WriteIoValue(ioName, true); } return false; } /// /// VacuumB关闭 /// public bool VacuumBOff() { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKB_RELEASE}"); if (!string.IsNullOrEmpty(ioName)) { return IOModuleManager.Instance.WriteIoValue(ioName, true); } return false; } /// /// VacuumA打开 /// public bool VacuumAOn() { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKA_RELEASE}"); if (!string.IsNullOrEmpty(ioName)) { return IOModuleManager.Instance.WriteIoValue(ioName, false); } return false; } /// /// VacuumB打开 /// public bool VacuumBOn() { string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKB_RELEASE}"); if (!string.IsNullOrEmpty(ioName)) { return IOModuleManager.Instance.WriteIoValue(ioName, false); } return false; } /// /// 监控 /// public void Monitor() { } /// /// 重置 /// public void Reset() { } /// /// 中止 /// public void Terminate() { } } }