IoTurnOver.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. using System.Xml;
  2. using Aitex.Core.RT.DataCenter;
  3. using Aitex.Core.RT.Event;
  4. using Aitex.Core.RT.IOCore;
  5. using Aitex.Core.RT.Log;
  6. using Aitex.Core.RT.OperationCenter;
  7. using Aitex.Core.RT.SCCore;
  8. using Aitex.Core.Util;
  9. using MECF.Framework.Common.Equipment;
  10. using MECF.Framework.Common.SubstrateTrackings;
  11. namespace Aitex.Core.RT.Device.Unit
  12. {
  13. /// <summary>
  14. ///
  15. /// </summary>
  16. public class IoTurnOver : BaseDevice, IDevice
  17. {
  18. private readonly DIAccessor _di0Degree;
  19. private readonly DIAccessor _di180Degree;
  20. private readonly DIAccessor _diAlarm;
  21. private readonly DIAccessor _diBusy;
  22. private readonly DIAccessor _diGrip;
  23. private readonly DIAccessor _diOrigin;
  24. private readonly DIAccessor _diPlacement;
  25. private readonly DIAccessor _diPressureError;
  26. private readonly DIAccessor _diUngrip;
  27. private readonly DOAccessor _doGrip;
  28. private readonly DOAccessor _doM0;
  29. private readonly DOAccessor _doM1;
  30. private readonly DOAccessor _doOrigin;
  31. private readonly DOAccessor _doResetError;
  32. private readonly DOAccessor _doStop;
  33. private readonly DOAccessor _doUngrip;
  34. //private bool _cmdLoop;
  35. //private int _interval;
  36. private DeviceTimer _loopTimeout = new DeviceTimer();
  37. private readonly DeviceTimer _loopTimer = new DeviceTimer();
  38. private readonly SCConfigItem _scLoopInterval;
  39. //private SCConfigItem _scLoopTimeout;
  40. private TurnOverState _state = TurnOverState.Idle;
  41. public TurnOverState State => _state;
  42. private R_TRIG _trigCloseError = new R_TRIG();
  43. private R_TRIG _trigOpenError = new R_TRIG();
  44. private R_TRIG _trigReset = new R_TRIG();
  45. private R_TRIG _trigSetPointDone = new R_TRIG();
  46. public const string EventWaferTurnOverStart = "WAFER_TURN_OVER_START";
  47. public const string EventWaferTurnOverEnd = "WAFER_TURN_OVER_COMPLETE";
  48. // DI_TurnOverPlacement
  49. // DI_TurnOverGrip
  50. // DI_TurnOverUngrip
  51. // DI_TurnOverBusy
  52. // DI_TurnOverPressureError
  53. //
  54. // DI_TurnOverAlarm
  55. // DI_TurnOverOrigin
  56. // DI_TurnOver0Degree
  57. // DI_TurnOver180Degree
  58. //
  59. // DO_TurnOverGrip
  60. // DO_TurnOverUngrip
  61. // DO_TurnOverM0
  62. // DO_TurnOverM1
  63. // DO_TurnOverStop
  64. //
  65. // DO_TurnOverOrigin
  66. // DO_TurnOverResetError
  67. public IoTurnOver(string module, XmlElement node, string ioModule = "")
  68. {
  69. Module = node.GetAttribute("module");
  70. Name = node.GetAttribute("id");
  71. Display = node.GetAttribute("display");
  72. DeviceID = node.GetAttribute("schematicId");
  73. _diPlacement = ParseDiNode("DI_TurnOverPlacement", node, ioModule);
  74. _diGrip = ParseDiNode("DI_TurnOverGrip", node, ioModule);
  75. _diUngrip = ParseDiNode("DI_TurnOverUngrip", node, ioModule);
  76. _diBusy = ParseDiNode("DI_TurnOverBusy", node, ioModule);
  77. _diPressureError = ParseDiNode("DI_TurnOverPressureError", node, ioModule);
  78. _diAlarm = ParseDiNode("DI_TurnOverAlarm", node, ioModule);
  79. _diOrigin = ParseDiNode("DI_TurnOverOrigin", node, ioModule);
  80. _di0Degree = ParseDiNode("DI_TurnOver0Degree", node, ioModule);
  81. _di180Degree = ParseDiNode("DI_TurnOver180Degree", node, ioModule);
  82. _doGrip = ParseDoNode("DO_TurnOverGrip", node, ioModule);
  83. _doUngrip = ParseDoNode("DO_TurnOverUngrip", node, ioModule);
  84. _doM0 = ParseDoNode("DO_TurnOverM0", node, ioModule);
  85. _doM1 = ParseDoNode("DO_TurnOverM1", node, ioModule);
  86. _doStop = ParseDoNode("DO_TurnOverStop", node, ioModule);
  87. _doOrigin = ParseDoNode("DO_TurnOverOrigin", node, ioModule);
  88. _doResetError = ParseDoNode("DO_TurnOverResetError", node, ioModule);
  89. _scLoopInterval = SC.GetConfigItem("Turnover.IntervalTimeLimit");
  90. }
  91. public int TimelimitAction
  92. {
  93. get
  94. {
  95. if (SC.ContainsItem($"Turnover.TimeLimitTurnoverAction"))
  96. return SC.GetValue<int>($"Turnover.TimeLimitTurnoverAction");
  97. return 60;
  98. }
  99. }
  100. public bool IsHomed => _diOrigin.Value;
  101. public bool IsPlacement => !_diPlacement.Value;
  102. public bool IsAlarm => !_diAlarm.Value;
  103. public bool IsPressureError => _diPressureError ==null? false: !_diPressureError.Value;
  104. public bool IsBusy => _diBusy.Value || _state != TurnOverState.Idle;
  105. public bool IsIdle => !_diBusy.Value;
  106. public bool IsGrip => _diGrip.Value;
  107. public bool IsUnGrip => _diUngrip.Value;
  108. public bool Is0Degree => _di0Degree.Value;
  109. public bool Is180Degree => _di180Degree.Value;
  110. public bool IsEnableWaferTransfer => Is0Degree && !IsBusy && IsUnGrip && !IsAlarm &&
  111. IsPlacement;
  112. public bool Initialize()
  113. {
  114. DATA.Subscribe($"{Module}.{Name}.State", () => _state.ToString());
  115. DATA.Subscribe($"{Module}.{Name}.IsHomed", () => IsHomed);
  116. DATA.Subscribe($"{Module}.{Name}.IsBusy", () => IsBusy);
  117. DATA.Subscribe($"{Module}.{Name}.IsGrip", () => IsGrip);
  118. DATA.Subscribe($"{Module}.{Name}.IsUnGrip", () => IsUnGrip);
  119. DATA.Subscribe($"{Module}.{Name}.Is0Degree", () => Is0Degree);
  120. DATA.Subscribe($"{Module}.{Name}.Is180Degree", () => Is180Degree);
  121. DATA.Subscribe($"{Module}.{Name}.IsPlacement", () => IsPlacement);
  122. DATA.Subscribe($"{Module}.{Name}.IsAlarm", () => IsAlarm);
  123. DATA.Subscribe($"{Module}.{Name}.IsPressureError", () => IsPressureError);
  124. DATA.Subscribe($"{Module}.{Name}.GripCmd", () => _doGrip.Value);
  125. DATA.Subscribe($"{Module}.{Name}.TurnTo0Cmd", () => _doM0.Value);
  126. DATA.Subscribe($"{Module}.{Name}.TurnTo180Cmd", () => _doM1.Value);
  127. DATA.Subscribe($"{Module}.{Name}.HomeCmd", () => _doOrigin.Value);
  128. DATA.Subscribe($"{Module}.{Name}.ResetCmd", () => _doResetError.Value);
  129. DATA.Subscribe($"{Module}.{Name}.StopCmd", () => _doStop==null?false: _doStop.Value);
  130. DATA.Subscribe($"{Module}.{Name}.UnGripCmd", () => _doUngrip.Value);
  131. EV.Subscribe(new EventItem("Event", EventWaferTurnOverStart, "Start Turn Over"));
  132. EV.Subscribe(new EventItem("Event", EventWaferTurnOverEnd, "Turn Over End"));
  133. //System.TurnoverStation.
  134. OP.Subscribe($"{Module}.{Name}.Home", (cmd, param) =>
  135. {
  136. if (!Home(out var reason))
  137. {
  138. EV.PostWarningLog(Module, $"{Name} can not home, {reason}");
  139. return false;
  140. }
  141. return true;
  142. });
  143. OP.Subscribe($"{Module}.{Name}.Grip", (cmd, param) =>
  144. {
  145. if (!Grip(out var reason))
  146. {
  147. EV.PostWarningLog(Module, $"{Name} can not grip, {reason}");
  148. return false;
  149. }
  150. return true;
  151. });
  152. OP.Subscribe($"{Module}.{Name}.Ungrip", (cmd, param) =>
  153. {
  154. if (!UnGrip(out var reason))
  155. {
  156. EV.PostWarningLog(Module, $"{Name} can not ungrip, {reason}");
  157. return false;
  158. }
  159. return true;
  160. });
  161. OP.Subscribe($"{Module}.{Name}.TurnTo0", (cmd, param) =>
  162. {
  163. if (!TurnTo0(out var reason))
  164. {
  165. EV.PostWarningLog(Module, $"{Name} can not turn to 0 degree, {reason}");
  166. return false;
  167. }
  168. return true;
  169. });
  170. OP.Subscribe($"{Module}.{Name}.TurnTo180", (cmd, param) =>
  171. {
  172. if (!TurnTo180(out var reason))
  173. {
  174. EV.PostWarningLog(Module, $"{Name} can not turn to 180 degree, {reason}");
  175. return false;
  176. }
  177. return true;
  178. });
  179. OP.Subscribe($"{Module}.{Name}.Stop", (cmd, param) =>
  180. {
  181. if (!Stop(out var reason))
  182. {
  183. EV.PostWarningLog(Module, $"{Name} can not turn to 180 degree, {reason}");
  184. return false;
  185. }
  186. return true;
  187. });
  188. return true;
  189. }
  190. public void Terminate()
  191. {
  192. }
  193. public void Monitor()
  194. {
  195. if (IsAlarm || IsPressureError)
  196. {
  197. _state = TurnOverState.Error;
  198. _doGrip.SetValue(false, out _);
  199. _doM0.SetValue(false, out _);
  200. _doM1.SetValue(false, out _);
  201. _doOrigin.SetValue(false, out _);
  202. if(_doStop !=null)
  203. _doStop.SetValue(false, out _);
  204. _doUngrip.SetValue(false, out _);
  205. return;
  206. }
  207. switch (_state)
  208. {
  209. case TurnOverState.OnHoming:
  210. _doM0.SetValue(false, out _);
  211. _doM1.SetValue(false, out _);
  212. _doOrigin.SetValue(true, out _);
  213. if (IsHomed)
  214. {
  215. if (!_doOrigin.SetValue(false, out var reason))
  216. LOG.Error($"{Module} reset DO failed, {reason}");
  217. _state = TurnOverState.Idle;
  218. }
  219. else if (_loopTimer.IsTimeout())
  220. {
  221. if (!_doOrigin.SetValue(false, out var reason))
  222. LOG.Error($"{Module} reset DO failed, {reason}");
  223. EV.PostAlarmLog(Module, $"{Module} {Name} Can not Home in {_scLoopInterval.IntValue} seconds");
  224. _state = TurnOverState.Error;
  225. }
  226. break;
  227. case TurnOverState.OnGripping:
  228. if (IsGrip)
  229. {
  230. //if (!_doGrip.SetValue(false, out var reason)) LOG.Error($"{Module} reset DO failed, {reason}");
  231. _state = TurnOverState.Idle;
  232. }
  233. else if (_loopTimer.IsTimeout())
  234. {
  235. //if (!_doOrigin.SetValue(false, out var reason))
  236. // LOG.Error($"{Module} reset DO failed, {reason}");
  237. EV.PostAlarmLog(Module, $"{Module} {Name} Can not Grip in {_scLoopInterval.IntValue} seconds");
  238. _state = TurnOverState.Error;
  239. }
  240. break;
  241. case TurnOverState.OnUnGripping:
  242. if (IsUnGrip)
  243. {
  244. //if (!_doUngrip.SetValue(false, out var reason))
  245. // LOG.Error($"{Module} reset DO failed, {reason}");
  246. _state = TurnOverState.Idle;
  247. }
  248. else if (_loopTimer.IsTimeout())
  249. {
  250. //if (!_doUngrip.SetValue(false, out var reason))
  251. // LOG.Error($"{Module} reset DO failed, {reason}");
  252. EV.PostAlarmLog(Module,
  253. $"{Module} {Name} Can not UnGrip in {_scLoopInterval.IntValue} seconds");
  254. _state = TurnOverState.Error;
  255. }
  256. break;
  257. case TurnOverState.OnTurningTo0:
  258. if (_doM1.Value == true) _doM1.SetValue(false, out _);
  259. if (_doM0.Value == false) _doM0.SetValue(true, out _);
  260. if (Is0Degree && !_diBusy.Value)
  261. { if (!_doM0.SetValue(false, out var reason)) LOG.Error($"{Module} reset DO failed, {reason}");
  262. _state = TurnOverState.Idle;
  263. }
  264. else if (_loopTimer.IsTimeout())
  265. {
  266. ////if (!_doM0.SetValue(false, out var reason))
  267. // LOG.Error($"{Module} reset DO failed, {reason}");
  268. EV.PostAlarmLog(Module,
  269. $"{Module} {Name} Can not Turn to 0 in {_scLoopInterval.IntValue} seconds");
  270. _state = TurnOverState.Error;
  271. }
  272. break;
  273. case TurnOverState.OnTurningTo180:
  274. if(_doM1.Value == false) _doM1.SetValue(true, out _);
  275. if (_doM0.Value == true) _doM0.SetValue(false, out _);
  276. if (Is180Degree &&!_diBusy.Value)
  277. {
  278. if (!_doM1.SetValue(false, out var reason)) LOG.Error($"{Module} reset DO failed, {reason}");
  279. _state = TurnOverState.Idle;
  280. var wafer = WaferManager.Instance.GetWafer(ModuleName.TurnOverStation, 0);
  281. if (!wafer.IsEmpty)
  282. {
  283. var dvid = new SerializableDictionary<string, string>()
  284. {
  285. {"LOT_ID", wafer.LotId},
  286. {"WAFER_ID", wafer.WaferID},
  287. {"ARRIVE_POS_NAME", "TRN1"},
  288. };
  289. EV.Notify(EventWaferTurnOverEnd, dvid);
  290. }
  291. }
  292. else if (_loopTimer.IsTimeout())
  293. {
  294. //if (!_doM1.SetValue(false, out var reason)) LOG.Error($"{Module} reset DO failed, {reason}");
  295. EV.PostAlarmLog(Module,
  296. $"{Module} {Name} Can not Turn to 180 in {_scLoopInterval.IntValue} seconds");
  297. _state = TurnOverState.Error;
  298. }
  299. break;
  300. case TurnOverState.OnErrorCleaning:
  301. if (!IsAlarm)
  302. {
  303. if (!_doResetError.SetValue(false, out var reason))
  304. LOG.Error($"{Module} reset DO failed, {reason}");
  305. _state = TurnOverState.Idle;
  306. }
  307. break;
  308. case TurnOverState.Stopping:
  309. if (!IsBusy)
  310. {
  311. if (_doStop != null)
  312. {
  313. if (!_doStop.SetValue(false, out var reason))
  314. LOG.Error($"{Module} reset DO failed, {reason}");
  315. }
  316. _state = TurnOverState.Stop;
  317. }
  318. break;
  319. default:
  320. //if (!_diBusy.Value && !_doStop.Value) _state = DeviceState.Idle;
  321. break;
  322. }
  323. }
  324. public void Reset()
  325. {
  326. _doGrip.SetValue(false, out _);
  327. _doM0.SetValue(false, out _);
  328. _doM1.SetValue(false, out _);
  329. _doOrigin.SetValue(false, out _);
  330. if(_doStop!=null)
  331. _doStop.SetValue(false, out _);
  332. _doUngrip.SetValue(false, out _);
  333. ResetError(out _);
  334. }
  335. public bool Home(out string reason)
  336. {
  337. reason = string.Empty;
  338. EV.PostInfoLog(Module, $"{Module}.{Name} Home");
  339. //if (IsPressureError)
  340. //{
  341. // reason = "Turn over station pressure error";
  342. // return false;
  343. //}
  344. _doM0.SetValue(false, out _);
  345. _doM1.SetValue(false, out _);
  346. _doOrigin.SetValue(true, out _);
  347. _state = TurnOverState.OnHoming;
  348. _loopTimer.Start(_scLoopInterval.IntValue * 1000);
  349. return true;
  350. }
  351. public bool Grip(out string reason)
  352. {
  353. reason = string.Empty;
  354. EV.PostInfoLog(Module, $"{Module}.{Name} Grip");
  355. if (IsPressureError)
  356. {
  357. reason = "Turn over station pressure error";
  358. EV.PostAlarmLog(Module, $"{Module}.{Name} pressure error.");
  359. return false;
  360. }
  361. //if (_doGrip.Value)
  362. //{
  363. // reason = "Gripping, can't do again";
  364. // EV.PostAlarmLog(Module, $"{Module}.{Name} {reason}.");
  365. // return false;
  366. //}
  367. _doUngrip.SetValue(false, out _);
  368. _doGrip.SetValue(true, out _);
  369. _state = TurnOverState.OnGripping;
  370. _loopTimer.Start(_scLoopInterval.IntValue * 1000);
  371. return true;
  372. }
  373. public bool UnGrip(out string reason)
  374. {
  375. reason = string.Empty;
  376. EV.PostInfoLog(Module, $"{Module}.{Name} UnGrip");
  377. if (IsPressureError)
  378. {
  379. reason = "Turn over station pressure error";
  380. return false;
  381. }
  382. //if (_doUngrip.Value)
  383. //{
  384. // reason = "UnGripping, can't do again";
  385. // return false;
  386. //}
  387. _doGrip.SetValue(false, out _);
  388. _doUngrip.SetValue(true, out _);
  389. _state = TurnOverState.OnUnGripping;
  390. _loopTimer.Start(_scLoopInterval.IntValue * 1000);
  391. return true;
  392. }
  393. public bool TurnTo0(out string reason)
  394. {
  395. reason = string.Empty;
  396. EV.PostInfoLog(Module, $"{Module}.{Name} Turn to 0");
  397. //if (IsPressureError)
  398. //{
  399. // reason = "Turn over station pressure error";
  400. // return false;
  401. //}
  402. //if (_doM0.Value)
  403. //{
  404. // reason = "Turning, can't do again";
  405. // return false;
  406. //}
  407. _state = TurnOverState.OnTurningTo0;
  408. //if (_doM1.Value == true) _doM1.SetValue(false, out _);
  409. //if (_doM0.Value == false) _doM0.SetValue(true, out _);
  410. _loopTimer.Start(_scLoopInterval.IntValue * 1000);
  411. return true;
  412. }
  413. public bool TurnTo180(out string reason)
  414. {
  415. reason = string.Empty;
  416. EV.PostInfoLog(Module, $"{Module}.{Name} Turn to 180");
  417. //if (IsPressureError)
  418. //{
  419. // reason = "Turn over station pressure error";
  420. // return false;
  421. //}
  422. //if (_doM1.Value)
  423. //{
  424. // reason = "Turning, can't do again";
  425. // return false;
  426. //}
  427. _state = TurnOverState.OnTurningTo180;
  428. //if (_doM0.Value == true) _doM0.SetValue(false, out _);
  429. //if (_doM1.Value == false) _doM1.SetValue(true, out _);
  430. _loopTimer.Start(_scLoopInterval.IntValue * 1000);
  431. var wafer = WaferManager.Instance.GetWafer(ModuleName.TurnOverStation,0);
  432. if (!wafer.IsEmpty)
  433. {
  434. var dvid = new SerializableDictionary<string, string>()
  435. {
  436. {"LOT_ID", wafer.LotId},
  437. {"WAFER_ID", wafer.WaferID},
  438. {"ARRIVE_POS_NAME", "TRN1"}
  439. };
  440. EV.Notify(EventWaferTurnOverStart, dvid);
  441. }
  442. return true;
  443. }
  444. public bool Stop(out string reason)
  445. {
  446. reason = string.Empty;
  447. EV.PostInfoLog(Module, $"{Module}.{Name} Stop");
  448. if (_doStop != null)
  449. {
  450. if (_doStop.Value)
  451. {
  452. reason = "Stopping, can't do again";
  453. return false;
  454. }
  455. _doStop.SetValue(true, out _);
  456. }
  457. _state = TurnOverState.Stopping;
  458. _loopTimer.Start(_scLoopInterval.IntValue * 1000);
  459. return true;
  460. }
  461. private bool ResetError(out string reason)
  462. {
  463. reason = string.Empty;
  464. //EV.PostInfoLog(Module, $"{Module}.{Name} Reset Error");
  465. if (_doResetError.Value)
  466. return true;
  467. _doResetError.SetValue(true, out _);
  468. _state = TurnOverState.OnErrorCleaning;
  469. _loopTimer.Start(_scLoopInterval.IntValue * 1000);
  470. return true;
  471. }
  472. }
  473. public enum TurnOverState
  474. {
  475. Idle,
  476. OnHoming,
  477. OnTurningTo0,
  478. OnTurningTo180,
  479. OnGripping,
  480. OnUnGripping,
  481. Error,
  482. OnErrorCleaning,
  483. Stopping,
  484. Stop
  485. }
  486. }