PufVacuum.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. using Aitex.Core.RT.DataCenter;
  2. using Aitex.Core.RT.Device;
  3. using Aitex.Core.RT.Log;
  4. using Aitex.Core.RT.OperationCenter;
  5. using Aitex.Core.RT.SCCore;
  6. using MECF.Framework.Common.Beckhoff.ModuleIO;
  7. using MECF.Framework.Common.Equipment;
  8. using MECF.Framework.Common.TwinCat;
  9. using CyberX8_Core;
  10. using System;
  11. using System.Collections.Generic;
  12. using Aitex.Core.Util;
  13. using MECF.Framework.Common.IOCore;
  14. namespace CyberX8_RT.Devices.PUF
  15. {
  16. public class PufVacuum : BaseDevice, IDevice
  17. {
  18. #region 常量
  19. private const string CHUCK = "Chuck";
  20. private const string SIDEA_CHUCK_OUT = "SideAChuckOut";
  21. private const string SIDEA_CHUCK_IN = "SideAChuckIn";
  22. private const string SIDEB_CHUCK_OUT = "SideBChuckOut";
  23. private const string SIDEB_CHUCK_IN = "SideBChuckIn";
  24. private const string CHUCKA_VAC = "ChuckAVac";
  25. private const string CHUCKB_VAC = "ChuckBVac";
  26. private const string CHUCKA_RELEASE = "ChuckARelease";
  27. private const string CHUCKB_RELEASE = "ChuckBRelease";
  28. private const string CHUCKA_VACUUM_STATUS = "ChuckAVacuumStatus";
  29. private const string CHUCKB_VACUUM_STATUS = "ChuckBVacuumStaus";
  30. private const string CHUCKA = "ChuckA";
  31. private const string CHUCKB = "ChuckB";
  32. private const string VACUUM_LEAK = "VacuumLeak";
  33. #endregion
  34. #region 内部变量
  35. private bool _chuck = false;
  36. private bool _sideAChuckOut = false;
  37. private bool _sideAChuckIn = false;
  38. private bool _sideBChuckOut=false;
  39. private bool _sideBChuckIn = false;
  40. private bool _chuckAWaferPresent;
  41. private bool _chuckBWaferPresent;
  42. private bool _chuckAReleased;
  43. private bool _chuckBReleased;
  44. private double _chuckAValue;
  45. private double _chuckBValue;
  46. private double _chuckVacuumCloseLimit;
  47. private double _chuckVacuumOpenLimit;
  48. private double _chuckVacuumWaferAbsent;
  49. private double _chuckVacuumWaferPresent;
  50. private string _chuckAVacuumStatus = "";
  51. private string _chuckBVacuumStatus = "";
  52. private DateTime _leakADateTime = DateTime.Now;
  53. private System.Timers.Timer _leakATimer;
  54. private DateTime _leakBDateTime = DateTime.Now;
  55. private System.Timers.Timer _leakBTimer;
  56. /// <summary>
  57. /// 变量是否初始化字典
  58. /// </summary>
  59. private Dictionary<string, bool> _variableInitializeDic = new Dictionary<string, bool>();
  60. /// <summary>
  61. /// 首次加载数据成功
  62. /// </summary>
  63. private bool _firstLoad = false;
  64. #endregion
  65. #region 属性
  66. /// <summary>
  67. /// ChuckA Wafer Present状态
  68. /// </summary>
  69. public bool ChuckAWaferPresent
  70. {
  71. get { return _chuckAWaferPresent; }
  72. set { _chuckAWaferPresent = value; }
  73. }
  74. /// <summary>
  75. /// ChuckB Wafer Present
  76. /// </summary>
  77. public bool ChuckBWaferPresent
  78. {
  79. get { return _chuckBWaferPresent; }
  80. set { _chuckBWaferPresent = value; }
  81. }
  82. /// <summary>
  83. /// Side A Vacuum状态
  84. /// </summary>
  85. public string ChuckAVacuumStatus
  86. {
  87. get { return _chuckAVacuumStatus; }
  88. }
  89. /// <summary>
  90. /// Side B Vacuum状态
  91. /// </summary>
  92. public string ChuckBVacuumStatus
  93. {
  94. get { return _chuckBVacuumStatus; }
  95. }
  96. /// <summary>
  97. /// Side B 是否关闭真空
  98. /// </summary>
  99. public bool ISChuckBReleased
  100. {
  101. get { return _chuckBReleased; }
  102. }
  103. /// <summary>
  104. /// Side A是否关闭真空
  105. /// </summary>
  106. public bool IsChuckAReleased
  107. {
  108. get { return _chuckAReleased; }
  109. }
  110. /// <summary>
  111. /// Chuck
  112. /// </summary>
  113. public bool Chuck
  114. {
  115. get { return _chuck; }
  116. }
  117. public bool SideAChuckOut
  118. {
  119. get { return _sideAChuckOut; }
  120. }
  121. public bool SideAChuckIn
  122. {
  123. get { return _sideAChuckIn; }
  124. }
  125. public bool SideBChuckOut
  126. {
  127. get { return _sideBChuckOut; }
  128. }
  129. public bool SideBChuckIn
  130. {
  131. get { return _sideBChuckIn;}
  132. }
  133. /// <summary>
  134. /// 所有io变量是否初始化
  135. /// </summary>
  136. public bool IOInitialized { get { return AllIoVariableInitialized(); } }
  137. #endregion
  138. #region 事件
  139. public event EventHandler<string> OnVacuumLeak;
  140. public event EventHandler<string> OnVacuumResume;
  141. #endregion
  142. /// <summary>
  143. /// 构造函数
  144. /// </summary>
  145. /// <param name="moduleName"></param>
  146. public PufVacuum(string moduleName):base(moduleName,"Vacuum","Vacuum","Vacuum")
  147. {
  148. LoadConfigParameter();
  149. _leakATimer = new System.Timers.Timer(500);
  150. _leakATimer.Elapsed += LeakATimer_Elapsed;
  151. _leakBTimer=new System.Timers.Timer(500);
  152. _leakBTimer.Elapsed += LeakBTimer_Elapsed;
  153. }
  154. /// <summary>
  155. /// 加载配置参数
  156. /// </summary>
  157. private void LoadConfigParameter()
  158. {
  159. _chuckVacuumCloseLimit = SC.GetValue<double>($"{Module}.ChuckVacuumCloseLimit");
  160. _chuckVacuumOpenLimit = SC.GetValue<double>($"{Module}.ChuckVacuumOpenLimit");
  161. _chuckVacuumWaferAbsent = SC.GetValue<double>($"{Module}.ChuckVacuumWaferAbsent");
  162. _chuckVacuumWaferPresent = SC.GetValue<double>($"{Module}.ChuckVacuumWaferPresent");
  163. }
  164. /// <summary>
  165. /// Leak定时器
  166. /// </summary>
  167. /// <param name="sender"></param>
  168. /// <param name="e"></param>
  169. /// <exception cref="NotImplementedException"></exception>
  170. private void LeakATimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
  171. {
  172. if(DateTime.Now.Subtract(_leakADateTime).TotalSeconds>=2)
  173. {
  174. _chuckAVacuumStatus = VACUUM_LEAK;
  175. LOG.WriteLog(eEvent.ERR_PUF, Module, $"ChuckA vacuum leak");
  176. if (OnVacuumLeak != null)
  177. {
  178. OnVacuumLeak(this, Module);
  179. }
  180. _leakATimer.Stop();
  181. }
  182. }
  183. /// <summary>
  184. /// LeakB定时器
  185. /// </summary>
  186. /// <param name="sender"></param>
  187. /// <param name="e"></param>
  188. /// <exception cref="NotImplementedException"></exception>
  189. private void LeakBTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
  190. {
  191. if (DateTime.Now.Subtract(_leakBDateTime).TotalSeconds >= 2)
  192. {
  193. _chuckBVacuumStatus = VACUUM_LEAK;
  194. LOG.WriteLog(eEvent.ERR_PUF, Module, $"ChuckB vacuum leak");
  195. if (OnVacuumLeak != null)
  196. {
  197. OnVacuumLeak(this, Module);
  198. }
  199. _leakBTimer.Stop();
  200. }
  201. }
  202. /// <summary>
  203. /// 初始化
  204. /// </summary>
  205. /// <returns></returns>
  206. public bool Initialize()
  207. {
  208. SubscribeData();
  209. InitializeOperation();
  210. SubscribeValueAction();
  211. return true;
  212. }
  213. /// <summary>
  214. /// 初始化操作
  215. /// </summary>
  216. private void InitializeOperation()
  217. {
  218. OP.Subscribe($"{Module}.{PufMotionVaccumOpertaion.VacuumAOn}", VaccumAOnOperation);
  219. OP.Subscribe($"{Module}.{PufMotionVaccumOpertaion.VacuumBOn}", VaccumBOnOperation);
  220. OP.Subscribe($"{Module}.ChuckOn", (cmd,args) => { return ChuckOn(); });
  221. OP.Subscribe($"{Module}.ChuckOff", (cmd, args) => { return ChuckOff(); });
  222. }
  223. /// <summary>
  224. /// 订阅变量数值发生变化
  225. /// </summary>
  226. private void SubscribeValueAction()
  227. {
  228. BeckhoffIoSubscribeUpdateVariable(CHUCKA_VAC);
  229. BeckhoffIoSubscribeUpdateVariable(CHUCKB_VAC);
  230. BeckhoffIoSubscribeUpdateVariable(CHUCKA_RELEASE);
  231. BeckhoffIoSubscribeUpdateVariable(CHUCKB_RELEASE);
  232. BeckhoffIoSubscribeUpdateVariable(CHUCK);
  233. BeckhoffIoSubscribeUpdateVariable(SIDEA_CHUCK_IN);
  234. BeckhoffIoSubscribeUpdateVariable(SIDEA_CHUCK_OUT);
  235. BeckhoffIoSubscribeUpdateVariable(SIDEB_CHUCK_IN);
  236. BeckhoffIoSubscribeUpdateVariable(SIDEB_CHUCK_OUT);
  237. }
  238. /// <summary>
  239. /// 订阅IO变量
  240. /// </summary>
  241. /// <param name="variable"></param>
  242. private void BeckhoffIoSubscribeUpdateVariable(string variable)
  243. {
  244. _variableInitializeDic[variable] = false;
  245. IOModuleManager.Instance.SubscribeModuleVariable($"{Module}", variable, UpdateVariableValue);
  246. }
  247. /// <summary>
  248. /// 是否所有IO变量初始化完成
  249. /// </summary>
  250. /// <returns></returns>
  251. private bool AllIoVariableInitialized()
  252. {
  253. foreach (string item in _variableInitializeDic.Keys)
  254. {
  255. if (!_variableInitializeDic[item])
  256. {
  257. LOG.WriteLog(eEvent.ERR_DRYER, Module, $"{item} is not initialized");
  258. return false;
  259. }
  260. }
  261. return true;
  262. }
  263. /// <summary>
  264. /// 订阅数据
  265. /// </summary>
  266. private void SubscribeData()
  267. {
  268. DATA.Subscribe($"{Module}.{CHUCK}", () => _chuck, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  269. DATA.Subscribe($"{Module}.{SIDEA_CHUCK_IN}", () => _sideAChuckIn, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  270. DATA.Subscribe($"{Module}.{SIDEA_CHUCK_OUT}", () => _sideAChuckOut, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  271. DATA.Subscribe($"{Module}.{SIDEB_CHUCK_IN}", () => _sideBChuckIn, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  272. DATA.Subscribe($"{Module}.{SIDEB_CHUCK_OUT}", () => _sideBChuckOut, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  273. DATA.Subscribe($"{Module}.{CHUCKA_RELEASE}", () => _chuckAReleased,SubscriptionAttribute.FLAG.IgnoreSaveDB);
  274. DATA.Subscribe($"{Module}.{CHUCKB_RELEASE}", () => _chuckBReleased, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  275. DATA.Subscribe($"{Module}.{CHUCKA_VAC}", () => _chuckAValue, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  276. DATA.Subscribe($"{Module}.{CHUCKB_VAC}", () => _chuckBValue, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  277. DATA.Subscribe($"{Module}.{CHUCKA_VACUUM_STATUS}", () => _chuckAVacuumStatus, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  278. DATA.Subscribe($"{Module}.{CHUCKB_VACUUM_STATUS}", () => _chuckBVacuumStatus, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  279. }
  280. /// 更新变量数值
  281. /// </summary>
  282. /// <param name="variable"></param>
  283. /// <param name="value"></param>
  284. private void UpdateVariableValue(string variable, object value)
  285. {
  286. if(!_firstLoad)
  287. {
  288. _firstLoad = true;
  289. VacuumAOn();
  290. VacuumBOn();
  291. }
  292. if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable])
  293. {
  294. _variableInitializeDic[variable] = true;
  295. }
  296. if (variable == $"{CHUCKA_RELEASE}")
  297. {
  298. _chuckAReleased = (bool)value;
  299. var item = JudgeWaferPresent(_chuckAValue, _chuckAReleased, CHUCKA);
  300. _chuckAWaferPresent = item.Item1;
  301. _chuckAVacuumStatus = item.Item2;
  302. if (_chuckAVacuumStatus != VACUUM_LEAK && item.Item2 == VACUUM_LEAK)
  303. {
  304. _leakADateTime = DateTime.Now;
  305. _leakATimer.Start();
  306. }
  307. else if (item.Item2 != VACUUM_LEAK)
  308. {
  309. _leakBTimer.Stop();
  310. }
  311. }
  312. else if(variable==$"{CHUCKB_RELEASE}")
  313. {
  314. _chuckBReleased=(bool)value;
  315. var item = JudgeWaferPresent(_chuckBValue, _chuckBReleased, CHUCKB);
  316. if (_chuckBVacuumStatus != VACUUM_LEAK && item.Item2 == VACUUM_LEAK)
  317. {
  318. _leakBDateTime = DateTime.Now;
  319. _leakBTimer.Start();
  320. }
  321. else if (item.Item2 != VACUUM_LEAK)
  322. {
  323. _leakBTimer.Stop();
  324. }
  325. _chuckBWaferPresent = item.Item1;
  326. _chuckBVacuumStatus = item.Item2;
  327. }
  328. else if(variable==$"{CHUCKA_VAC}")
  329. {
  330. _chuckAValue = (double)value;
  331. var item = JudgeWaferPresent(_chuckAValue, _chuckAReleased, CHUCKA);
  332. if(_chuckAVacuumStatus!= VACUUM_LEAK&&item.Item2== VACUUM_LEAK)
  333. {
  334. _leakADateTime = DateTime.Now;
  335. _leakATimer.Start();
  336. }
  337. else if (item.Item2 != VACUUM_LEAK)
  338. {
  339. _leakATimer.Stop();
  340. }
  341. _chuckAWaferPresent =item.Item1;
  342. _chuckAVacuumStatus=item.Item2;
  343. }
  344. else if(variable==$"{CHUCKB_VAC}")
  345. {
  346. _chuckBValue=(double)value;
  347. var item = JudgeWaferPresent(_chuckBValue, _chuckBReleased, CHUCKB);
  348. if (_chuckBVacuumStatus != VACUUM_LEAK && item.Item2 == VACUUM_LEAK)
  349. {
  350. _leakBDateTime = DateTime.Now;
  351. _leakBTimer.Start();
  352. }
  353. else if(item.Item2!=VACUUM_LEAK)
  354. {
  355. _leakBTimer.Stop();
  356. }
  357. _chuckBWaferPresent = item.Item1;
  358. _chuckBVacuumStatus = item.Item2;
  359. }
  360. else
  361. {
  362. UpdateChuck(variable, (bool)value);
  363. }
  364. }
  365. /// <summary>
  366. /// 更新 chuck
  367. /// </summary>
  368. /// <param name="variable"></param>
  369. /// <param name="value"></param>
  370. private void UpdateChuck(string variable,bool value)
  371. {
  372. switch (variable)
  373. {
  374. case CHUCK:
  375. _chuck = value;
  376. break;
  377. case SIDEA_CHUCK_IN:
  378. _sideAChuckIn = value;
  379. break;
  380. case SIDEA_CHUCK_OUT:
  381. _sideAChuckOut = value;
  382. break;
  383. case SIDEB_CHUCK_IN:
  384. _sideBChuckIn = value;
  385. break;
  386. case SIDEB_CHUCK_OUT:
  387. _sideBChuckOut = value;
  388. break;
  389. }
  390. }
  391. /// <summary>
  392. /// 判定Wafer Present
  393. /// </summary>
  394. /// <param name="chuckValue"></param>
  395. /// <param name="chuckRelease"></param>
  396. /// <returns></returns>
  397. private (bool,string) JudgeWaferPresent(double chuckValue,bool chuckRelease,string chuck)
  398. {
  399. LoadConfigParameter();
  400. if (!chuckRelease)
  401. {
  402. if(chuckValue < _chuckVacuumWaferPresent)
  403. {
  404. ResumeVacuum();
  405. return (true,"WaferPresent");
  406. }
  407. else if( chuckValue > _chuckVacuumWaferAbsent)
  408. {
  409. ResumeVacuum();
  410. return (false,"WaferAbsent");
  411. }
  412. else
  413. {
  414. return (false,"InvalidData");
  415. }
  416. }
  417. else
  418. {
  419. if(chuckValue<=_chuckVacuumCloseLimit)
  420. {
  421. return (false,"VacuumLeak");
  422. }
  423. else if(chuckValue<=_chuckVacuumOpenLimit)
  424. {
  425. ResumeVacuum();
  426. return (false, "VacuumOff");
  427. }
  428. else
  429. {
  430. ResumeVacuum();
  431. return (false, "");
  432. }
  433. }
  434. }
  435. /// <summary>
  436. /// 故障恢复
  437. /// </summary>
  438. private void ResumeVacuum()
  439. {
  440. if (OnVacuumResume != null)
  441. {
  442. OnVacuumResume(this, Module);
  443. }
  444. }
  445. /// <summary>
  446. /// VacuumAOn操作
  447. /// </summary>
  448. /// <param name="cmd"></param>
  449. /// <param name="args"></param>
  450. /// <returns></returns>
  451. private bool VaccumAOnOperation(string cmd, object[] args)
  452. {
  453. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKA_RELEASE}");
  454. if(!string.IsNullOrEmpty(ioName))
  455. {
  456. IOModuleManager.Instance.WriteIoValue(ioName, args[1]);
  457. }
  458. return true;
  459. }
  460. /// <summary>
  461. /// VacuumBOn操作
  462. /// </summary>
  463. /// <param name="cmd"></param>
  464. /// <param name="args"></param>
  465. /// <returns></returns>
  466. private bool VaccumBOnOperation(string cmd, object[] args)
  467. {
  468. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKB_RELEASE}");
  469. if (!string.IsNullOrEmpty(ioName))
  470. {
  471. return IOModuleManager.Instance.WriteIoValue(ioName, args[1]);
  472. }
  473. return true;
  474. }
  475. /// <summary>
  476. /// Chuck On
  477. /// </summary>
  478. /// <returns></returns>
  479. private bool ChuckOn()
  480. {
  481. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCK}");
  482. if (!string.IsNullOrEmpty(ioName))
  483. {
  484. return IOModuleManager.Instance.WriteIoValue(ioName, true);
  485. }
  486. return true;
  487. }
  488. /// <summary>
  489. /// Chuck Off
  490. /// </summary>
  491. /// <returns></returns>
  492. private bool ChuckOff()
  493. {
  494. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCK}");
  495. if (!string.IsNullOrEmpty(ioName))
  496. {
  497. return IOModuleManager.Instance.WriteIoValue(ioName, false);
  498. }
  499. return true;
  500. }
  501. /// <summary>
  502. /// VacuumA关闭
  503. /// </summary>
  504. public bool VacuumAOff()
  505. {
  506. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKA_RELEASE}");
  507. if (!string.IsNullOrEmpty(ioName))
  508. {
  509. return IOModuleManager.Instance.WriteIoValue(ioName, true);
  510. }
  511. return false;
  512. }
  513. /// <summary>
  514. /// VacuumB关闭
  515. /// </summary>
  516. public bool VacuumBOff()
  517. {
  518. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKB_RELEASE}");
  519. if (!string.IsNullOrEmpty(ioName))
  520. {
  521. return IOModuleManager.Instance.WriteIoValue(ioName, true);
  522. }
  523. return false;
  524. }
  525. /// <summary>
  526. /// VacuumA打开
  527. /// </summary>
  528. public bool VacuumAOn()
  529. {
  530. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKA_RELEASE}");
  531. if (!string.IsNullOrEmpty(ioName))
  532. {
  533. return IOModuleManager.Instance.WriteIoValue(ioName, false);
  534. }
  535. return false;
  536. }
  537. /// <summary>
  538. /// VacuumB打开
  539. /// </summary>
  540. public bool VacuumBOn()
  541. {
  542. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CHUCKB_RELEASE}");
  543. if (!string.IsNullOrEmpty(ioName))
  544. {
  545. return IOModuleManager.Instance.WriteIoValue(ioName, false);
  546. }
  547. return false;
  548. }
  549. /// <summary>
  550. /// 监控
  551. /// </summary>
  552. public void Monitor()
  553. {
  554. }
  555. /// <summary>
  556. /// 重置
  557. /// </summary>
  558. public void Reset()
  559. {
  560. }
  561. /// <summary>
  562. /// 中止
  563. /// </summary>
  564. public void Terminate()
  565. {
  566. }
  567. }
  568. }