| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616 | 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 CHUCK = "Chuck";        private const string SIDEA_CHUCK_OUT = "SideAChuckOut";        private const string SIDEA_CHUCK_IN = "SideAChuckIn";        private const string SIDEB_CHUCK_OUT = "SideBChuckOut";        private const string SIDEB_CHUCK_IN = "SideBChuckIn";        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 _chuck = false;        private bool _sideAChuckOut = false;        private bool _sideAChuckIn = false;        private bool _sideBChuckOut=false;        private bool _sideBChuckIn = false;        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 R_TRIG _leakATrig = new R_TRIG();        private DateTime _leakBDateTime = DateTime.Now;        private R_TRIG _leakBTrig = new R_TRIG();        /// <summary>        /// 变量是否初始化字典        /// </summary>        private Dictionary<string, bool> _variableInitializeDic = new Dictionary<string, bool>();        /// <summary>        /// 首次加载数据成功        /// </summary>        private bool _firstLoad = false;        #endregion        #region 属性        /// <summary>        /// ChuckA Wafer Present状态        /// </summary>        public bool ChuckAWaferPresent        {            get { return _chuckAWaferPresent; }            set { _chuckAWaferPresent = value; }        }        /// <summary>        /// ChuckB Wafer Present        /// </summary>        public bool ChuckBWaferPresent        {            get { return _chuckBWaferPresent; }            set { _chuckBWaferPresent = value; }        }        /// <summary>        /// Side A Vacuum状态        /// </summary>        public string ChuckAVacuumStatus        {            get { return _chuckAVacuumStatus; }        }        /// <summary>        /// Side B Vacuum状态        /// </summary>        public string ChuckBVacuumStatus        {            get { return _chuckBVacuumStatus; }        }        /// <summary>        /// Side B 是否关闭真空        /// </summary>        public bool ISChuckBReleased        {            get { return _chuckBReleased; }        }        /// <summary>        /// Side A是否关闭真空        /// </summary>        public bool IsChuckAReleased        {            get { return _chuckAReleased; }        }        /// <summary>        /// Chuck        /// </summary>        public bool Chuck        {            get { return _chuck; }        }        public bool SideAChuckOut        {            get { return _sideAChuckOut;  }        }        public bool SideAChuckIn        {            get { return _sideAChuckIn; }        }        public bool SideBChuckOut        {            get { return _sideBChuckOut; }        }        public bool SideBChuckIn        {            get { return _sideBChuckIn;}        }        /// <summary>        /// 所有io变量是否初始化        /// </summary>        public bool IOInitialized { get { return AllIoVariableInitialized(); } }        #endregion        #region 事件        public event EventHandler<string> OnVacuumLeak;        public event EventHandler<string> OnVacuumResume;        #endregion        /// <summary>        /// 构造函数        /// </summary>        /// <param name="moduleName"></param>        public PufVacuum(string moduleName):base(moduleName,"Vacuum","Vacuum","Vacuum")        {            LoadConfigParameter();        }        /// <summary>        /// 加载配置参数        /// </summary>        private void LoadConfigParameter()        {            _chuckVacuumCloseLimit = SC.GetValue<double>($"{Module}.ChuckVacuumCloseLimit");            _chuckVacuumOpenLimit = SC.GetValue<double>($"{Module}.ChuckVacuumOpenLimit");            _chuckVacuumWaferAbsent = SC.GetValue<double>($"{Module}.ChuckVacuumWaferAbsent");            _chuckVacuumWaferPresent = SC.GetValue<double>($"{Module}.ChuckVacuumWaferPresent");        }        /// <summary>        /// 初始化        /// </summary>        /// <returns></returns>        public bool Initialize()        {            SubscribeData();            InitializeOperation();            SubscribeValueAction();            return true;        }        /// <summary>        /// 初始化操作        /// </summary>        private void InitializeOperation()        {            OP.Subscribe($"{Module}.{PufMotionVaccumOpertaion.VacuumAOn}", VaccumAOnOperation);            OP.Subscribe($"{Module}.{PufMotionVaccumOpertaion.VacuumBOn}", VaccumBOnOperation);            OP.Subscribe($"{Module}.ChuckOn", (cmd,args) => { return ChuckOn(); });            OP.Subscribe($"{Module}.ChuckOff", (cmd, args) => { return ChuckOff(); });        }        /// <summary>        /// 订阅变量数值发生变化        /// </summary>        private void SubscribeValueAction()        {            BeckhoffIoSubscribeUpdateVariable(CHUCKA_VAC);            BeckhoffIoSubscribeUpdateVariable(CHUCKB_VAC);            BeckhoffIoSubscribeUpdateVariable(CHUCKA_RELEASE);            BeckhoffIoSubscribeUpdateVariable(CHUCKB_RELEASE);            BeckhoffIoSubscribeUpdateVariable(CHUCK);            BeckhoffIoSubscribeUpdateVariable(SIDEA_CHUCK_IN);            BeckhoffIoSubscribeUpdateVariable(SIDEA_CHUCK_OUT);            BeckhoffIoSubscribeUpdateVariable(SIDEB_CHUCK_IN);            BeckhoffIoSubscribeUpdateVariable(SIDEB_CHUCK_OUT);        }        /// <summary>        /// 订阅IO变量        /// </summary>        /// <param name="variable"></param>        private void BeckhoffIoSubscribeUpdateVariable(string variable)        {            _variableInitializeDic[variable] = false;            IOModuleManager.Instance.SubscribeModuleVariable($"{Module}", variable, UpdateVariableValue);        }        /// <summary>        /// 是否所有IO变量初始化完成        /// </summary>        /// <returns></returns>        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;        }        /// <summary>        /// 订阅数据        /// </summary>        private void SubscribeData()        {            DATA.Subscribe($"{Module}.{CHUCK}", () => _chuck, SubscriptionAttribute.FLAG.IgnoreSaveDB);            DATA.Subscribe($"{Module}.{SIDEA_CHUCK_IN}", () => _sideAChuckIn, SubscriptionAttribute.FLAG.IgnoreSaveDB);            DATA.Subscribe($"{Module}.{SIDEA_CHUCK_OUT}", () => _sideAChuckOut, SubscriptionAttribute.FLAG.IgnoreSaveDB);            DATA.Subscribe($"{Module}.{SIDEB_CHUCK_IN}", () => _sideBChuckIn, SubscriptionAttribute.FLAG.IgnoreSaveDB);            DATA.Subscribe($"{Module}.{SIDEB_CHUCK_OUT}", () => _sideBChuckOut, SubscriptionAttribute.FLAG.IgnoreSaveDB);            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);        }        /// 更新变量数值        /// </summary>        /// <param name="variable"></param>        /// <param name="value"></param>        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;                _leakATrig.CLK = item.Item2 == VACUUM_LEAK;                if (_leakATrig.Q)                {                    _leakADateTime = DateTime.Now;                }            }            else if(variable==$"{CHUCKB_RELEASE}")            {                _chuckBReleased=(bool)value;                var item = JudgeWaferPresent(_chuckBValue, _chuckBReleased, CHUCKB);                _leakBTrig.CLK = item.Item2 == VACUUM_LEAK;                if (_leakBTrig.Q)                {                    _leakBDateTime = DateTime.Now;                }                _chuckBWaferPresent = item.Item1;                _chuckBVacuumStatus = item.Item2;            }            else if(variable==$"{CHUCKA_VAC}")            {                _chuckAValue = (double)value;                var item = JudgeWaferPresent(_chuckAValue, _chuckAReleased, CHUCKA);                _leakATrig.CLK = item.Item2 == VACUUM_LEAK;                if (_leakATrig.Q)                {                    _leakADateTime = DateTime.Now;                }                _chuckAWaferPresent =item.Item1;                _chuckAVacuumStatus=item.Item2;            }            else if(variable==$"{CHUCKB_VAC}")            {                _chuckBValue=(double)value;                var item = JudgeWaferPresent(_chuckBValue, _chuckBReleased, CHUCKB);                _leakBTrig.CLK = item.Item2 == VACUUM_LEAK;                if (_leakBTrig.Q)                {                    _leakBDateTime = DateTime.Now;                }                _chuckBWaferPresent = item.Item1;                _chuckBVacuumStatus = item.Item2;            }            else            {                UpdateChuck(variable, (bool)value);            }        }        /// <summary>        /// 更新 chuck        /// </summary>        /// <param name="variable"></param>        /// <param name="value"></param>        private void UpdateChuck(string variable,bool value)        {            switch (variable)            {                case CHUCK:                    _chuck = value;                    LOG.WriteLog(eEvent.INFO_PUF, Module, $"Chuck value is {value}");                    break;                case SIDEA_CHUCK_IN:                    _sideAChuckIn = value;                    LOG.WriteLog(eEvent.INFO_PUF, Module, $"SideA Chuck In value is {value}");                    break;                case SIDEA_CHUCK_OUT:                    _sideAChuckOut = value;                    LOG.WriteLog(eEvent.INFO_PUF, Module, $"SideA Chuck Out value is {value}");                    break;                case SIDEB_CHUCK_IN:                    _sideBChuckIn = value;                    LOG.WriteLog(eEvent.INFO_PUF, Module, $"SideB Chuck In value is {value}");                    break;                case SIDEB_CHUCK_OUT:                    _sideBChuckOut = value;                    LOG.WriteLog(eEvent.INFO_PUF, Module, $"SideB Chuck Out value is {value}");                    break;            }        }        /// <summary>        /// 检验ChuckOut        /// </summary>        /// <returns></returns>        public bool CheckChuckOut()        {            if (!_chuck)            {                return false;            }            if (!_sideAChuckOut)            {                return false;            }            if (!_sideBChuckOut)            {                return false;            }            if (_sideAChuckIn)            {                return false;            }            if (_sideBChuckIn)            {                return false;            }            return true;        }        /// <summary>        /// 检验ChuckIn        /// </summary>        /// <returns></returns>        public bool CheckChuckIn()        {            if (_chuck)            {                return false;            }            if (_sideAChuckOut)            {                return false;            }            if (_sideBChuckOut)            {                return false;            }            if (!_sideAChuckIn)            {                return false;            }            if (!_sideBChuckIn)            {                return false;            }            return true;        }        /// <summary>        /// 判定Wafer Present        /// </summary>        /// <param name="chuckValue"></param>        /// <param name="chuckRelease"></param>        /// <returns></returns>        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, "");                }            }        }        /// <summary>        /// 故障恢复        /// </summary>        private void ResumeVacuum()        {            if (OnVacuumResume != null)            {                OnVacuumResume(this, Module);            }        }        /// <summary>        /// VacuumAOn操作        /// </summary>        /// <param name="cmd"></param>        /// <param name="args"></param>        /// <returns></returns>        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;        }        /// <summary>        /// VacuumBOn操作        /// </summary>        /// <param name="cmd"></param>        /// <param name="args"></param>        /// <returns></returns>        private bool VaccumBOnOperation(string cmd, object[] args)        {            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKB_RELEASE}");            if (!string.IsNullOrEmpty(ioName))            {                return IOModuleManager.Instance.WriteIoValue(ioName, args[1]);            }            return true;        }        /// <summary>        /// Chuck On        /// </summary>        /// <returns></returns>        public bool ChuckOn()        {            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCK}");            if (!string.IsNullOrEmpty(ioName))            {                return IOModuleManager.Instance.WriteIoValue(ioName, true);            }            return false;        }        /// <summary>        /// Chuck Off        /// </summary>        /// <returns></returns>        public bool ChuckOff()        {            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCK}");            if (!string.IsNullOrEmpty(ioName))            {                return IOModuleManager.Instance.WriteIoValue(ioName, false);            }            return false;        }        /// <summary>        /// VacuumA关闭        /// </summary>        public bool VacuumAOff()        {            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKA_RELEASE}");            if (!string.IsNullOrEmpty(ioName))            {                return IOModuleManager.Instance.WriteIoValue(ioName, true);            }            return false;        }        /// <summary>        /// VacuumB关闭        /// </summary>        public bool VacuumBOff()        {            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKB_RELEASE}");            if (!string.IsNullOrEmpty(ioName))            {                return IOModuleManager.Instance.WriteIoValue(ioName, true);            }            return false;        }        /// <summary>        /// VacuumA打开        /// </summary>        public bool VacuumAOn()        {            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKA_RELEASE}");            if (!string.IsNullOrEmpty(ioName))            {                return IOModuleManager.Instance.WriteIoValue(ioName, false);            }            return false;        }        /// <summary>        /// VacuumB打开        /// </summary>        public bool VacuumBOn()        {            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKB_RELEASE}");            if (!string.IsNullOrEmpty(ioName))            {                return IOModuleManager.Instance.WriteIoValue(ioName, false);            }            return false;        }        /// <summary>        /// 定时器        /// </summary>        public void OnTimer()        {            if (_leakATrig.CLK && DateTime.Now.Subtract(_leakADateTime).TotalSeconds >= 2&&_chuckAVacuumStatus!=VACUUM_LEAK)            {                _chuckAVacuumStatus = VACUUM_LEAK;                LOG.WriteLog(eEvent.ERR_PUF, Module, $"ChuckA vacuum leak");                if (OnVacuumLeak != null)                {                    OnVacuumLeak(this, Module);                }            }            if (_leakBTrig.CLK && DateTime.Now.Subtract(_leakBDateTime).TotalSeconds >= 2 && _chuckBVacuumStatus != VACUUM_LEAK)            {                _chuckBVacuumStatus = VACUUM_LEAK;                LOG.WriteLog(eEvent.ERR_PUF, Module, $"ChuckB vacuum leak");                if (OnVacuumLeak != null)                {                    OnVacuumLeak(this, Module);                }            }        }        /// <summary>        /// 监控        /// </summary>        public void Monitor()        {        }        /// <summary>        /// 重置        /// </summary>        public void Reset()        {        }        /// <summary>        /// 中止        /// </summary>        public void Terminate()        {        }    }}
 |