IoTurnOver.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803
  1. using System;
  2. using System.Xml;
  3. using Aitex.Core.RT.DataCenter;
  4. using Aitex.Core.RT.Event;
  5. using Aitex.Core.RT.IOCore;
  6. using Aitex.Core.RT.Log;
  7. using Aitex.Core.RT.OperationCenter;
  8. using Aitex.Core.RT.SCCore;
  9. using Aitex.Core.Util;
  10. using MECF.Framework.Common.Equipment;
  11. using MECF.Framework.Common.SubstrateTrackings;
  12. using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Flipper.FlipperBase;
  13. namespace Aitex.Core.RT.Device.Unit
  14. {
  15. /// <summary>
  16. ///
  17. /// </summary>
  18. public class IoTurnOver : FlipperBaseDevice
  19. {
  20. private readonly DIAccessor _di0Degree;
  21. private readonly DIAccessor _di180Degree;
  22. private readonly DIAccessor _diAlarm;
  23. private readonly DIAccessor _diBusy;
  24. private readonly DIAccessor _diGrip;
  25. private readonly DIAccessor _diOrigin;
  26. private readonly DIAccessor _diPlacement;
  27. private readonly DIAccessor _diPressureError;
  28. private readonly DIAccessor _diUngrip;
  29. private readonly DOAccessor _doGrip;
  30. private readonly DOAccessor _doM0;
  31. private readonly DOAccessor _doM1;
  32. private readonly DOAccessor _doOrigin;
  33. private readonly DOAccessor _doResetError;
  34. private readonly DOAccessor _doStop;
  35. private readonly DOAccessor _doUngrip;
  36. private DateTime _dtActionStart;
  37. //private DeviceTimer _loopTimeout = new DeviceTimer();
  38. //private readonly DeviceTimer _loopTimer = new DeviceTimer();
  39. //private readonly SCConfigItem _scLoopInterval;
  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. // DI_TurnOverPlacement
  47. // DI_TurnOverGrip
  48. // DI_TurnOverUngrip
  49. // DI_TurnOverBusy
  50. // DI_TurnOverPressureError
  51. //
  52. // DI_TurnOverAlarm
  53. // DI_TurnOverOrigin
  54. // DI_TurnOver0Degree
  55. // DI_TurnOver180Degree
  56. //
  57. // DO_TurnOverGrip
  58. // DO_TurnOverUngrip
  59. // DO_TurnOverM0
  60. // DO_TurnOverM1
  61. // DO_TurnOverStop
  62. //
  63. // DO_TurnOverOrigin
  64. // DO_TurnOverResetError
  65. public string Display, DeviceID;
  66. private PeriodicJob _thread;
  67. public IoTurnOver(string module, XmlElement node, string ioModule = ""):base(node.GetAttribute("module"), node.GetAttribute("id"))
  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. InitializeIoTurnover();
  91. }
  92. public override bool IsPlacement
  93. {
  94. get
  95. {
  96. if(_diPlacement !=null) return !_diPlacement.Value;
  97. return WaferManager.Instance.CheckHasWafer(ModuleName.TurnOverStation, 0);
  98. }
  99. }
  100. public bool IsAlarm => !_diAlarm.Value;
  101. public bool IsPressureError => _diPressureError ==null? false: !_diPressureError.Value;
  102. public override FlipperPosEnum CurrentFlipperPosition
  103. {
  104. get
  105. {
  106. if (_di0Degree.Value && !_di180Degree.Value) return FlipperPosEnum.FrontSide;
  107. if (!_di0Degree.Value && _di180Degree.Value) return FlipperPosEnum.BackSide;
  108. return FlipperPosEnum.Unknow;
  109. }
  110. }
  111. public override GripPosEnum CurrentGripperPositon
  112. {
  113. get
  114. {
  115. if (_diGrip.Value && !_diUngrip.Value) return GripPosEnum.Close;
  116. if (!_diGrip.Value && _diUngrip.Value) return GripPosEnum.Open;
  117. return GripPosEnum.Unknow;
  118. }
  119. }
  120. //public bool IsBusy => _diBusy.Value || _state != TurnOverState.Idle;
  121. //public bool IsIdle => !_diBusy.Value && _state == TurnOverState.Idle;
  122. //public bool IsGrip => _diGrip.Value && !_diUngrip.Value;
  123. //public bool IsUnGrip => _diUngrip.Value && !_diGrip.Value;
  124. //public bool Is0Degree => _di0Degree.Value &&!_di180Degree.Value;
  125. //public bool Is180Degree => _di180Degree.Value&&!_di0Degree.Value;
  126. //public bool IsEnableWaferTransfer => Is0Degree && !IsBusy && IsUnGrip && !IsAlarm &&
  127. // IsPlacement;
  128. public bool InitializeIoTurnover()
  129. {
  130. //DATA.Subscribe($"{Module}.{Name}.State", () => _state.ToString());
  131. DATA.Subscribe($"{Module}.{Name}.IsHomed", () => _diOrigin.Value);
  132. DATA.Subscribe($"{Module}.{Name}.IsBusy", () => _diBusy.Value);
  133. DATA.Subscribe($"{Module}.{Name}.IsGrip", () => _diGrip.Value);
  134. DATA.Subscribe($"{Module}.{Name}.IsUnGrip", () => _diUngrip.Value);
  135. DATA.Subscribe($"{Module}.{Name}.Is0Degree", () => _di0Degree.Value);
  136. DATA.Subscribe($"{Module}.{Name}.Is180Degree", () => _di180Degree.Value);
  137. DATA.Subscribe($"{Module}.{Name}.IsPlacement", () => IsPlacement);
  138. DATA.Subscribe($"{Module}.{Name}.IsAlarm", () => _diAlarm.Value);
  139. DATA.Subscribe($"{Module}.{Name}.IsPressureError", () => _diPressureError==null?false: _diPressureError.Value);
  140. DATA.Subscribe($"{Module}.{Name}.GripCmd", () => _doGrip.Value);
  141. DATA.Subscribe($"{Module}.{Name}.TurnTo0Cmd", () => _doM0.Value);
  142. DATA.Subscribe($"{Module}.{Name}.TurnTo180Cmd", () => _doM1.Value);
  143. DATA.Subscribe($"{Module}.{Name}.HomeCmd", () => _doOrigin.Value);
  144. DATA.Subscribe($"{Module}.{Name}.ResetCmd", () => _doResetError.Value);
  145. DATA.Subscribe($"{Module}.{Name}.StopCmd", () => _doStop==null?false: _doStop.Value);
  146. DATA.Subscribe($"{Module}.{Name}.UnGripCmd", () => _doUngrip.Value);
  147. _trigError = new R_TRIG();
  148. _thread = new PeriodicJob(50, OnTimerMonitor, $"{Module}.{Name} MonitorHandler", true);
  149. return true;
  150. }
  151. private R_TRIG _trigError;
  152. private bool OnTimerMonitor()
  153. {
  154. _trigError.CLK = (_diAlarm != null && !_diAlarm.Value) || (_diPressureError != null && !_diPressureError.Value);
  155. if(_trigError.Q)
  156. {
  157. OnError($"{FlipperModuleName}Error");
  158. }
  159. return true;
  160. }
  161. public override void Terminate()
  162. {
  163. }
  164. //public void Monitor()
  165. //{
  166. // if (IsAlarm || IsPressureError)
  167. // {
  168. // _state = TurnOverState.Error;
  169. // _doGrip.SetValue(false, out _);
  170. // _doM0.SetValue(false, out _);
  171. // _doM1.SetValue(false, out _);
  172. // _doOrigin.SetValue(false, out _);
  173. // if(_doStop !=null)
  174. // _doStop.SetValue(false, out _);
  175. // _doUngrip.SetValue(false, out _);
  176. // return;
  177. // }
  178. // switch (_state)
  179. // {
  180. // case TurnOverState.OnHoming:
  181. // _doM0.SetValue(false, out _);
  182. // _doM1.SetValue(false, out _);
  183. // _doOrigin.SetValue(true, out _);
  184. // if (IsHomed)// && _di0Degree.Value)
  185. // {
  186. // if (!_doOrigin.SetValue(false, out var reason))
  187. // LOG.Error($"{Module} reset DO failed, {reason}");
  188. // _state = TurnOverState.Idle;
  189. // }
  190. // else if (_loopTimer.IsTimeout())
  191. // {
  192. // if (!_doOrigin.SetValue(false, out var reason))
  193. // LOG.Error($"{Module} reset DO failed, {reason}");
  194. // EV.PostAlarmLog(Module, $"{Module} {Name} Can not Home in {_scLoopInterval.IntValue} seconds");
  195. // _state = TurnOverState.Error;
  196. // }
  197. // break;
  198. // case TurnOverState.OnGripping:
  199. // if (IsGrip)
  200. // {
  201. // //if (!_doGrip.SetValue(false, out var reason)) LOG.Error($"{Module} reset DO failed, {reason}");
  202. // _state = TurnOverState.Idle;
  203. // }
  204. // else if (_loopTimer.IsTimeout())
  205. // {
  206. // //if (!_doOrigin.SetValue(false, out var reason))
  207. // // LOG.Error($"{Module} reset DO failed, {reason}");
  208. // EV.PostAlarmLog(Module, $"{Module} {Name} Can not Grip in {_scLoopInterval.IntValue} seconds");
  209. // _state = TurnOverState.Error;
  210. // }
  211. // break;
  212. // case TurnOverState.OnUnGripping:
  213. // if (IsUnGrip)
  214. // {
  215. // //if (!_doUngrip.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 (!_doUngrip.SetValue(false, out var reason))
  222. // // LOG.Error($"{Module} reset DO failed, {reason}");
  223. // EV.PostAlarmLog(Module,
  224. // $"{Module} {Name} Can not UnGrip in {_scLoopInterval.IntValue} seconds");
  225. // _state = TurnOverState.Error;
  226. // }
  227. // break;
  228. // case TurnOverState.OnTurningTo0:
  229. // if (_doM1.Value == true) _doM1.SetValue(false, out _);
  230. // if (_doM0.Value == false) _doM0.SetValue(true, out _);
  231. // if (Is0Degree && !_diBusy.Value)
  232. // { if (!_doM0.SetValue(false, out var reason)) LOG.Error($"{Module} reset DO failed, {reason}");
  233. // _state = TurnOverState.Idle;
  234. // }
  235. // else if (_loopTimer.IsTimeout())
  236. // {
  237. // ////if (!_doM0.SetValue(false, out var reason))
  238. // // LOG.Error($"{Module} reset DO failed, {reason}");
  239. // EV.PostAlarmLog(Module,
  240. // $"{Module} {Name} Can not Turn to 0 in {_scLoopInterval.IntValue} seconds");
  241. // _state = TurnOverState.Error;
  242. // }
  243. // break;
  244. // case TurnOverState.OnTurningTo180:
  245. // if(_doM1.Value == false) _doM1.SetValue(true, out _);
  246. // if (_doM0.Value == true) _doM0.SetValue(false, out _);
  247. // if (Is180Degree &&!_diBusy.Value)
  248. // {
  249. // if (!_doM1.SetValue(false, out var reason)) LOG.Error($"{Module} reset DO failed, {reason}");
  250. // _state = TurnOverState.Idle;
  251. // var wafer = WaferManager.Instance.GetWafer(ModuleName.TurnOverStation, 0);
  252. // if (!wafer.IsEmpty)
  253. // {
  254. // var dvid = new SerializableDictionary<string, string>()
  255. // {
  256. // {"LOT_ID", wafer.LotId},
  257. // {"WAFER_ID", wafer.WaferID},
  258. // {"ARRIVE_POS_NAME", "TRN1"},
  259. // };
  260. // EV.Notify(EventWaferTurnOverEnd, dvid);
  261. // }
  262. // }
  263. // else if (_loopTimer.IsTimeout())
  264. // {
  265. // //if (!_doM1.SetValue(false, out var reason)) LOG.Error($"{Module} reset DO failed, {reason}");
  266. // EV.PostAlarmLog(Module,
  267. // $"{Module} {Name} Can not Turn to 180 in {_scLoopInterval.IntValue} seconds");
  268. // _state = TurnOverState.Error;
  269. // }
  270. // break;
  271. // case TurnOverState.OnErrorCleaning:
  272. // if (!IsAlarm)
  273. // {
  274. // if (!_doResetError.SetValue(false, out var reason))
  275. // LOG.Error($"{Module} reset DO failed, {reason}");
  276. // _state = TurnOverState.Idle;
  277. // }
  278. // break;
  279. // case TurnOverState.Stopping:
  280. // if (!IsBusy)
  281. // {
  282. // if (_doStop != null)
  283. // {
  284. // if (!_doStop.SetValue(false, out var reason))
  285. // LOG.Error($"{Module} reset DO failed, {reason}");
  286. // }
  287. // _state = TurnOverState.Stop;
  288. // }
  289. // break;
  290. // default:
  291. // //if (!_diBusy.Value && !_doStop.Value) _state = DeviceState.Idle;
  292. // break;
  293. // }
  294. //}
  295. //public bool Home(out string reason)
  296. //{
  297. // reason = string.Empty;
  298. // EV.PostInfoLog(Module, $"{Module}.{Name} Home");
  299. // //if (IsPressureError)
  300. // //{
  301. // // reason = "Turn over station pressure error";
  302. // // return false;
  303. // //}
  304. // _doM0.SetValue(false, out _);
  305. // _doM1.SetValue(false, out _);
  306. // _doOrigin.SetValue(true, out _);
  307. // _state = TurnOverState.OnHoming;
  308. // _loopTimer.Start(_scLoopInterval.IntValue * 1000);
  309. // return true;
  310. //}
  311. //public bool Grip(out string reason)
  312. //{
  313. // reason = string.Empty;
  314. // EV.PostInfoLog(Module, $"{Module}.{Name} Grip");
  315. // if (IsPressureError)
  316. // {
  317. // reason = "Turn over station pressure error";
  318. // EV.PostAlarmLog(Module, $"{Module}.{Name} pressure error.");
  319. // return false;
  320. // }
  321. // //if (_doGrip.Value)
  322. // //{
  323. // // reason = "Gripping, can't do again";
  324. // // EV.PostAlarmLog(Module, $"{Module}.{Name} {reason}.");
  325. // // return false;
  326. // //}
  327. // _doUngrip.SetValue(false, out _);
  328. // _doGrip.SetValue(true, out _);
  329. // _state = TurnOverState.OnGripping;
  330. // _loopTimer.Start(_scLoopInterval.IntValue * 1000);
  331. // return true;
  332. //}
  333. //public bool UnGrip(out string reason)
  334. //{
  335. // reason = string.Empty;
  336. // EV.PostInfoLog(Module, $"{Module}.{Name} UnGrip");
  337. // if (IsPressureError)
  338. // {
  339. // reason = "Turn over station pressure error";
  340. // return false;
  341. // }
  342. // //if (_doUngrip.Value)
  343. // //{
  344. // // reason = "UnGripping, can't do again";
  345. // // return false;
  346. // //}
  347. // _doGrip.SetValue(false, out _);
  348. // _doUngrip.SetValue(true, out _);
  349. // _state = TurnOverState.OnUnGripping;
  350. // _loopTimer.Start(_scLoopInterval.IntValue * 1000);
  351. // return true;
  352. //}
  353. //public bool TurnTo0(out string reason)
  354. //{
  355. // reason = string.Empty;
  356. // EV.PostInfoLog(Module, $"{Module}.{Name} Turn to 0");
  357. // //if (IsPressureError)
  358. // //{
  359. // // reason = "Turn over station pressure error";
  360. // // return false;
  361. // //}
  362. // //if (_doM0.Value)
  363. // //{
  364. // // reason = "Turning, can't do again";
  365. // // return false;
  366. // //}
  367. // _state = TurnOverState.OnTurningTo0;
  368. // //if (_doM1.Value == true) _doM1.SetValue(false, out _);
  369. // //if (_doM0.Value == false) _doM0.SetValue(true, out _);
  370. // _loopTimer.Start(_scLoopInterval.IntValue * 1000);
  371. // return true;
  372. //}
  373. //public bool TurnTo180(out string reason)
  374. //{
  375. // reason = string.Empty;
  376. // EV.PostInfoLog(Module, $"{Module}.{Name} Turn to 180");
  377. // //if (IsPressureError)
  378. // //{
  379. // // reason = "Turn over station pressure error";
  380. // // return false;
  381. // //}
  382. // //if (_doM1.Value)
  383. // //{
  384. // // reason = "Turning, can't do again";
  385. // // return false;
  386. // //}
  387. // _state = TurnOverState.OnTurningTo180;
  388. // //if (_doM0.Value == true) _doM0.SetValue(false, out _);
  389. // //if (_doM1.Value == false) _doM1.SetValue(true, out _);
  390. // _loopTimer.Start(_scLoopInterval.IntValue * 1000);
  391. // var wafer = WaferManager.Instance.GetWafer(ModuleName.TurnOverStation,0);
  392. // if (!wafer.IsEmpty)
  393. // {
  394. // var dvid = new SerializableDictionary<string, string>()
  395. // {
  396. // {"LOT_ID", wafer.LotId},
  397. // {"WAFER_ID", wafer.WaferID},
  398. // {"ARRIVE_POS_NAME", "TRN1"}
  399. // };
  400. // EV.Notify(EventWaferTurnOverStart, dvid);
  401. // }
  402. // return true;
  403. //}
  404. //public bool Stop(out string reason)
  405. //{
  406. // reason = string.Empty;
  407. // EV.PostInfoLog(Module, $"{Module}.{Name} Stop");
  408. // if (_doStop != null)
  409. // {
  410. // if (_doStop.Value)
  411. // {
  412. // reason = "Stopping, can't do again";
  413. // return false;
  414. // }
  415. // _doStop.SetValue(true, out _);
  416. // }
  417. // _state = TurnOverState.Stopping;
  418. // _loopTimer.Start(_scLoopInterval.IntValue * 1000);
  419. // return true;
  420. //}
  421. //private bool ResetError(out string reason)
  422. //{
  423. // reason = string.Empty;
  424. // //EV.PostInfoLog(Module, $"{Module}.{Name} Reset Error");
  425. // if (_doResetError.Value)
  426. // return true;
  427. // _doResetError.SetValue(true, out _);
  428. // _state = TurnOverState.OnErrorCleaning;
  429. // _loopTimer.Start(_scLoopInterval.IntValue * 1000);
  430. // return true;
  431. //}
  432. public DOAccessor ParseDoNode(string name, XmlElement node, string ioModule = "")
  433. {
  434. if (!string.IsNullOrEmpty(node.GetAttribute(name).Trim()))
  435. return IO.DO[string.IsNullOrEmpty(ioModule) ? node.GetAttribute(name).Trim() : $"{ioModule}.{node.GetAttribute(name).Trim()}"];
  436. return null;
  437. }
  438. public DIAccessor ParseDiNode(string name, XmlElement node, string ioModule = "")
  439. {
  440. if (!string.IsNullOrEmpty(node.GetAttribute(name).Trim()))
  441. return IO.DI[string.IsNullOrEmpty(ioModule) ? node.GetAttribute(name).Trim() : $"{ioModule}.{node.GetAttribute(name).Trim()}"];
  442. return null;
  443. }
  444. protected override bool fStartGrip(object[] param)
  445. {
  446. _doGrip.SetValue(true, out _);
  447. _doUngrip.SetValue(false, out _);
  448. _dtActionStart = DateTime.Now;
  449. return true;
  450. }
  451. protected override bool fMonitorGrip(object[] param)
  452. {
  453. IsBusy = false;
  454. if (DateTime.Now - _dtActionStart > TimeSpan.FromSeconds(TimelimitAction))
  455. {
  456. OnError("Grip timeout");
  457. return false;
  458. }
  459. if (_diGrip.Value && !_diUngrip.Value && !_diBusy.Value)
  460. {
  461. EV.PostInfoLog("Flipper", $"{FlipperModuleName} grip completed");
  462. return true;
  463. }
  464. return false;
  465. }
  466. protected override bool fStartUnGrip(object[] param)
  467. {
  468. _doGrip.SetValue(false, out _);
  469. _doUngrip.SetValue(true, out _);
  470. _dtActionStart = DateTime.Now;
  471. return true;
  472. }
  473. protected override bool fMonitorUnGrip(object[] param)
  474. {
  475. IsBusy = false;
  476. if (DateTime.Now - _dtActionStart > TimeSpan.FromSeconds(TimelimitAction))
  477. {
  478. OnError("UnGrip timeout");
  479. return false;
  480. }
  481. if (!_diGrip.Value && _diUngrip.Value && !_diBusy.Value)
  482. {
  483. EV.PostInfoLog("Flipper", $"{FlipperModuleName} ungrip completed");
  484. return true;
  485. }
  486. return false;
  487. }
  488. protected override bool fStartHome(object[] param)
  489. {
  490. _doM0.SetValue(false, out _);
  491. _doM1.SetValue(false, out _);
  492. _doOrigin.SetValue(true, out _);
  493. _dtActionStart = DateTime.Now;
  494. _dtActionStart = DateTime.Now;
  495. return true;
  496. }
  497. protected override bool fMonitorHome(object[] param)
  498. {
  499. IsBusy = false;
  500. if (DateTime.Now - _dtActionStart > TimeSpan.FromSeconds(TimelimitAction))
  501. {
  502. OnError("Home timeout");
  503. _doM1.SetValue(false, out _);
  504. _doM0.SetValue(false, out _);
  505. _doOrigin.SetValue(false, out _);
  506. return false;
  507. }
  508. if (_diOrigin.Value && !_diBusy.Value)
  509. {
  510. _doOrigin.SetValue(false, out _);
  511. EV.PostInfoLog("Flipper", $"{FlipperModuleName} home completed");
  512. _doM1.SetValue(false, out _);
  513. _doM0.SetValue(false, out _);
  514. _doOrigin.SetValue(false, out _);
  515. return true;
  516. }
  517. return false;
  518. }
  519. protected override bool fStartTurnTo0(object[] param)
  520. {
  521. _doM0.SetValue(true, out _);
  522. _doM1.SetValue(false, out _);
  523. _dtActionStart = DateTime.Now;
  524. var wafer = WaferManager.Instance.GetWafer(ModuleName.TurnOverStation, 0);
  525. if (!wafer.IsEmpty)
  526. {
  527. var dvid = new SerializableDictionary<string, string>()
  528. {
  529. {"LOT_ID", wafer.LotId},
  530. {"WAFER_ID", wafer.WaferID},
  531. {"ARRIVE_POS_NAME", FlipperModuleName.ToString()}
  532. };
  533. EV.Notify(EventWaferTurnOverStart, dvid);
  534. }
  535. return true;
  536. }
  537. protected override bool fMonitorTurnTo0(object[] param)
  538. {
  539. IsBusy = false;
  540. if (DateTime.Now - _dtActionStart > TimeSpan.FromSeconds(TimelimitAction))
  541. {
  542. OnError("Turn to 0 timeout");
  543. _doM1.SetValue(false, out _);
  544. _doM0.SetValue(false, out _);
  545. _doOrigin.SetValue(false, out _);
  546. return false;
  547. }
  548. if (_di0Degree.Value && !_di180Degree.Value && !_diBusy.Value)
  549. {
  550. EV.PostInfoLog("Flipper", $"{FlipperModuleName} turn to 0 degree completed");
  551. var wafer = WaferManager.Instance.GetWafer(ModuleName.TurnOverStation, 0);
  552. if (!wafer.IsEmpty)
  553. {
  554. var dvid = new SerializableDictionary<string, string>()
  555. {
  556. {"LOT_ID", wafer.LotId},
  557. {"WAFER_ID", wafer.WaferID},
  558. {"ARRIVE_POS_NAME", FlipperModuleName.ToString()}
  559. };
  560. EV.Notify(EventWaferTurnOverStart, dvid);
  561. }
  562. _doM1.SetValue(false, out _);
  563. _doM0.SetValue(false, out _);
  564. _doOrigin.SetValue(false, out _);
  565. return true;
  566. }
  567. return false;
  568. }
  569. protected override bool fStartTurnTo180(object[] param)
  570. {
  571. _doM0.SetValue(false, out _);
  572. _doM1.SetValue(true, out _);
  573. _dtActionStart = DateTime.Now;
  574. var wafer = WaferManager.Instance.GetWafer(ModuleName.TurnOverStation, 0);
  575. if (!wafer.IsEmpty)
  576. {
  577. var dvid = new SerializableDictionary<string, string>()
  578. {
  579. {"LOT_ID", wafer.LotId},
  580. {"WAFER_ID", wafer.WaferID},
  581. {"ARRIVE_POS_NAME", "TRN1"}
  582. };
  583. EV.Notify(EventWaferTurnOverStart, dvid);
  584. }
  585. return true;
  586. }
  587. protected override bool fMonitorTurnTo180(object[] param)
  588. {
  589. IsBusy = false;
  590. if (DateTime.Now - _dtActionStart > TimeSpan.FromSeconds(TimelimitAction))
  591. {
  592. OnError("Turn to 180 timeout");
  593. _doM1.SetValue(false, out _);
  594. _doM0.SetValue(false, out _);
  595. _doOrigin.SetValue(false, out _);
  596. return false;
  597. }
  598. if (!_di0Degree.Value && _di180Degree.Value && !_diBusy.Value)
  599. {
  600. EV.PostInfoLog("Flipper", $"{FlipperModuleName} turn to 180 degree completed");
  601. var wafer = WaferManager.Instance.GetWafer(ModuleName.TurnOverStation, 0);
  602. if (!wafer.IsEmpty)
  603. {
  604. var dvid = new SerializableDictionary<string, string>()
  605. {
  606. {"LOT_ID", wafer.LotId},
  607. {"WAFER_ID", wafer.WaferID},
  608. {"ARRIVE_POS_NAME", FlipperModuleName.ToString()}
  609. };
  610. EV.Notify(EventWaferTurnOverStart, dvid);
  611. }
  612. _doM1.SetValue(false, out _);
  613. _doM0.SetValue(false, out _);
  614. _doOrigin.SetValue(false, out _);
  615. return true;
  616. }
  617. return false;
  618. }
  619. protected override bool fStartAbort(object[] param)
  620. {
  621. _doStop.SetValue(true, out _);
  622. _doResetError.SetValue(false, out _);
  623. _doM0.SetValue(false, out _);
  624. _doM1.SetValue(false, out _);
  625. IsBusy = false;
  626. return true;
  627. }
  628. protected override bool fStartReset(object[] param)
  629. {
  630. _doM0.SetValue(false, out _);
  631. _doM1.SetValue(false, out _);
  632. _doOrigin.SetValue(false, out _);
  633. _doStop.SetValue(false, out _);
  634. _doResetError.SetValue(true, out _);
  635. _dtActionStart = DateTime.Now;
  636. return true;
  637. }
  638. protected override bool fMonitorReset(object[] param)
  639. {
  640. IsBusy = false;
  641. if (DateTime.Now - _dtActionStart > TimeSpan.FromSeconds(TimelimitAction))
  642. {
  643. OnError("Reset timeout");
  644. _doResetError.SetValue(false, out _);
  645. return false;
  646. }
  647. if (_diAlarm != null && !_diAlarm.Value)
  648. return false;
  649. EV.PostInfoLog("Flipper", $"{FlipperModuleName} reset completed");
  650. _doResetError.SetValue(false, out _);
  651. return true;
  652. }
  653. }
  654. public enum TurnOverState
  655. {
  656. Idle,
  657. OnHoming,
  658. OnTurningTo0,
  659. OnTurningTo180,
  660. OnGripping,
  661. OnUnGripping,
  662. Error,
  663. OnErrorCleaning,
  664. Stopping,
  665. Stop
  666. }
  667. }