PMModuleRecipeExecutor.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. using Aitex.Core.RT.Device;
  2. using Aitex.Core.RT.Device.Unit;
  3. using Aitex.Core.RT.Event;
  4. using Aitex.Core.RT.Log;
  5. using Aitex.Core.RT.ParameterCenter;
  6. using Aitex.Core.Util;
  7. using FurnaceRT.Devices;
  8. using FurnaceRT.Equipments.Boats;
  9. using FurnaceRT.Equipments.PMs.RecipeExecutions;
  10. using FurnaceRT.Equipments.Systems;
  11. using MECF.Framework.Common.Equipment;
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Diagnostics;
  15. using System.IO;
  16. using System.Linq;
  17. using System.Xml;
  18. namespace FurnaceRT.Equipments.PMs
  19. {
  20. public partial class PMModule
  21. {
  22. public bool IsMainRecipeComplete { get; set; }
  23. public bool IsHeaterProfile { get; set; }
  24. public bool IsHeaterProfileSuccess { get; set; }
  25. public bool IsBoatMoveToLoadPosition { get; private set; }
  26. public bool IsWaitBoatMoveComplete { get; private set; }
  27. private string _boatTargetPosition;
  28. private R_TRIG _profileTrig = new R_TRIG();
  29. public RecipeRunningInfo RecipeRunningInfo
  30. {
  31. get
  32. {
  33. return _recipeRunningInfo;
  34. }
  35. }
  36. public bool IsPaused { get; set; }//按了hold按键
  37. public bool IsHolded { get; set; }//按了hold按键之后,当前step执行完了
  38. public bool IsWait { get; set; }//等待wait条件的结束
  39. public void ResetToleranceChecker()
  40. {
  41. }
  42. public void OnProcessStart(string v1, string recipeName, bool v2)
  43. {
  44. }
  45. public void PauseRecipe(out string reason)
  46. {
  47. reason = string.Empty;
  48. }
  49. public bool CheckEndPoint()
  50. {
  51. return true;
  52. }
  53. public bool CheckAllDevicesStable(float v1, float v2, float v3, float v4, float v5, float v6, float v7, float v8, float v9)
  54. {
  55. return true;
  56. }
  57. public bool CheckEnableRunProcess(out string reason)
  58. {
  59. reason = string.Empty;
  60. return true;
  61. }
  62. public void AbortRunProcess(out string reason)
  63. {
  64. //GasSticks.ForEach(x => x.SetFlow(out _, 0, 0));
  65. reason = string.Empty;
  66. }
  67. private bool SetBoatManualMotion(object[] param)
  68. {
  69. if (param == null || param.Length < 1)
  70. {
  71. return false;
  72. }
  73. var paramArray = param[0].ToString().Split(';');
  74. var loaderCommand = paramArray[0].ToString();
  75. switch (loaderCommand.ToLower().Replace(" ", ""))
  76. {
  77. case "boatload":
  78. if (paramArray.Length > 3)
  79. {
  80. var boat = Singleton<EquipmentManager>.Instance.Modules[ModuleName.Boat] as BoatModule;
  81. if (!boat.CheckPrepareMove(out string reason))
  82. {
  83. boat.BoatZAxisMoveFailedForInterlock.Set(reason);
  84. return false;
  85. }
  86. float.TryParse(paramArray[1], out float speed1);
  87. float.TryParse(paramArray[2], out float speed2);
  88. float.TryParse(paramArray[3], out float speed3);
  89. ZAxisDevice.SetServoMoveTo("Position2", out _, speed1);
  90. }
  91. break;
  92. case "boatunload":
  93. if (paramArray.Length > 3)
  94. {
  95. var boat = Singleton<EquipmentManager>.Instance.Modules[ModuleName.Boat] as BoatModule;
  96. if (!boat.CheckPrepareMove(out string reason))
  97. {
  98. boat.BoatZAxisMoveFailedForInterlock.Set(reason);
  99. return false;
  100. }
  101. float.TryParse(paramArray[1], out float speed1);
  102. float.TryParse(paramArray[2], out float speed2);
  103. float.TryParse(paramArray[3], out float speed3);
  104. ZAxisDevice.SetServoMoveTo("Position3", out _, speed1);
  105. }
  106. break;
  107. case "boatloaderhome":
  108. {
  109. var boat = Singleton<EquipmentManager>.Instance.Modules[ModuleName.Boat] as BoatModule;
  110. if (!boat.CheckPrepareMove(out string reason))
  111. {
  112. boat.BoatZAxisMoveFailedForInterlock.Set(reason);
  113. return false;
  114. }
  115. }
  116. ZAxisDevice.SetServoMoveTo("HomePosition", out _);
  117. break;
  118. case "boatcap2":
  119. if (paramArray.Length > 1)
  120. {
  121. var boat = Singleton<EquipmentManager>.Instance.Modules[ModuleName.Boat] as BoatModule;
  122. if (!boat.CheckPrepareMove(out string reason))
  123. {
  124. boat.BoatZAxisMoveFailedForInterlock.Set(reason);
  125. return false;
  126. }
  127. float.TryParse(paramArray[1], out float speed);
  128. ZAxisDevice.SetServoMoveTo("CapPosition", out _, speed);
  129. }
  130. break;
  131. case "boatrotate":
  132. if (paramArray.Length > 1)
  133. {
  134. float.TryParse(paramArray[1], out float speed);
  135. RAxisDevice.SetServoMoveTo("CCW", out _, speed);
  136. }
  137. break;
  138. case "boatrotatestop"://r home
  139. RAxisDevice.ServoStop();
  140. RAxisDevice.SetServoHome();
  141. break;
  142. case "stop(includer-axis)":
  143. RAxisDevice.ServoStop();
  144. break;
  145. }
  146. return true;
  147. }
  148. private bool SetValves(object[] param)
  149. {
  150. var stopwatch = new Stopwatch();
  151. stopwatch.Start();
  152. if (param == null || param.Length < 1)
  153. {
  154. return false;
  155. }
  156. var paramArray = param[0].ToString().Split(';');
  157. for (int i = 0; i < paramArray.Length; i++)
  158. {
  159. var item = paramArray[i];
  160. if (string.IsNullOrEmpty(item))
  161. continue;
  162. var valveDatas = item.Split(',');
  163. if (valveDatas != null && valveDatas.Length > 1)
  164. {
  165. var valveName = valveDatas[0];
  166. var valveSet = valveDatas[1];
  167. if (valveSet == "Continue")
  168. continue;
  169. bool.TryParse(valveSet, out bool set);
  170. switch (valveName.ToUpper())
  171. {
  172. case "F2CLN":
  173. IsF2ClnOn = set;
  174. break;
  175. case "HFCLN":
  176. IsHFClnOn = set;
  177. break;
  178. case "HTR1":
  179. //_HTR1Group.ForEach(x => x.SetEnable(set));
  180. SetHTR1Enable(new object[1] { set });
  181. break;
  182. case "HTR2":
  183. //_HTR2Group.ForEach(x => x.SetEnable(set));
  184. SetHTR2Enable(new object[1] { set });
  185. break;
  186. case "HTR3":
  187. SetHTR3Enable(new object[1] { set });
  188. break;
  189. case "DPR":
  190. valveName = "ValveAV91";
  191. if (_valves.Any(x => x.Name == valveName))
  192. {
  193. var valve = _valves.Find(x => x.Name == valveName);
  194. if (valve != null)
  195. valve.TurnValve(set, out _);
  196. }
  197. break;
  198. case "AGV":
  199. valveName = "AGVPump";
  200. if (_valves.Any(x => x.Name == valveName))
  201. {
  202. var valve = _valves.Find(x => x.Name == valveName);
  203. if (valve != null)
  204. valve.TurnValve(set, out _);
  205. }
  206. break;
  207. case "MBP":
  208. case "DP":
  209. valveName = "BothPump";
  210. if (_valves.Any(x => x.Name == valveName))
  211. {
  212. var valve = _valves.Find(x => x.Name == valveName);
  213. if (valve != null)
  214. valve.TurnValve(set, out _);
  215. }
  216. break;
  217. case "BWR":
  218. valveName = "ValveBlowerPowerOn";
  219. if (_valves.Any(x => x.Name == valveName))
  220. {
  221. var valve = _valves.Find(x => x.Name == valveName);
  222. if (valve != null)
  223. valve.TurnValve(set, out _);
  224. }
  225. break;
  226. case "CEXH":
  227. SetCEXHEnable(new object[1] { set });
  228. break;
  229. case "DEPO":
  230. SetDEPOEnable(new object[1] { set });
  231. break;
  232. case "CMNT":
  233. SetCMNTEnable(new object[1] { set });
  234. break;
  235. case "CZERO":
  236. SetCZEROEnable(new object[1] { set });
  237. break;
  238. case "HREF":
  239. SetHREFEnable(new object[1] { set });
  240. break;
  241. case "XXCLN":
  242. SetXXClnEnable(new object[1] { set });
  243. break;
  244. case "NDIR":
  245. SetNDIREnable(new object[1] { set });
  246. break;
  247. default:
  248. if (_valves.Any(x => x.Name == valveName))
  249. {
  250. var valve = _valves.Find(x => x.Name == valveName);
  251. if (valve != null)
  252. valve.TurnValve(set, out _);
  253. }
  254. break;
  255. }
  256. }
  257. }
  258. LOG.Write($"SetValves exec time {stopwatch.ElapsedMilliseconds}");
  259. return true;
  260. }
  261. private bool SetBoatMotion(object[] param)
  262. {
  263. var boatModule = Singleton<EquipmentManager>.Instance.Modules[ModuleName.Boat] as BoatModule;
  264. if (param == null || param.Length < 1 || boatModule == null)
  265. {
  266. return false;
  267. }
  268. var paramArray = param[0].ToString().Split(';');
  269. var loaderCommand = paramArray[0].ToString();
  270. IsWaitBoatMoveComplete = false;
  271. IsBoatMoveToLoadPosition = false;
  272. switch (loaderCommand.ToLower().Replace(" ", ""))
  273. {
  274. case "boatload":
  275. if (paramArray.Length > 3)
  276. {
  277. float.TryParse(paramArray[1], out float speed1);
  278. float.TryParse(paramArray[2], out float speed2);
  279. float.TryParse(paramArray[3], out float speed3);
  280. IsWaitBoatMoveComplete = true;
  281. IsBoatMoveToLoadPosition = true;
  282. _boatTargetPosition = "Position2";
  283. //ZAxisDevice.SetServoMoveTo(_boatTargetPosition, out _, speed1);
  284. boatModule.BoatMove("boatload", _boatTargetPosition, speed1);
  285. }
  286. break;
  287. case "boatunload":
  288. if (paramArray.Length > 3)
  289. {
  290. float.TryParse(paramArray[1], out float speed1);
  291. float.TryParse(paramArray[2], out float speed2);
  292. float.TryParse(paramArray[3], out float speed3);
  293. IsWaitBoatMoveComplete = true;
  294. _boatTargetPosition = "Position3";
  295. //ZAxisDevice.SetServoMoveTo(_boatTargetPosition, out _, speed1);
  296. boatModule.BoatMove("boatunload", _boatTargetPosition, speed1);
  297. }
  298. break;
  299. case "boatloaderhome":
  300. IsWaitBoatMoveComplete = true;
  301. _boatTargetPosition = "HomePosition";
  302. //ZAxisDevice.SetServoMoveTo(_boatTargetPosition, out _);
  303. boatModule.BoatMove("boatloaderhome", _boatTargetPosition, 0);
  304. break;
  305. case "boatcap2":
  306. if (paramArray.Length > 1)
  307. {
  308. float.TryParse(paramArray[1], out float speed);
  309. IsWaitBoatMoveComplete = true;
  310. _boatTargetPosition = "CapPosition";
  311. //ZAxisDevice.SetServoMoveTo(_boatTargetPosition, out _, speed);
  312. boatModule.BoatMove("boatcap2", _boatTargetPosition, speed);
  313. }
  314. break;
  315. case "boatrotate":
  316. if (paramArray.Length > 4)
  317. {
  318. float.TryParse(paramArray[4], out float speed);
  319. //RAxisDevice.SetServoMoveTo("CCW", out _, speed);
  320. //boatModule.BoatMove("boatrotate", "CCW", speed);
  321. boatModule.RAxisDevice.SetServoMoveTo("CCW", out string reason, speed);//旋转直接发
  322. }
  323. break;
  324. case "boatrotatestop"://r home
  325. IsWaitBoatMoveComplete = true;
  326. _boatTargetPosition = "RotateHome";
  327. //RAxisDevice.ServoStop();
  328. //RAxisDevice.SetServoHome();
  329. boatModule.BoatMove("boatrotatestop", _boatTargetPosition, 0);
  330. break;
  331. case "stop(includer-axis)":
  332. //RAxisDevice.ServoStop();
  333. boatModule.BoatMove("stop(includer-axis)", "", 0);
  334. break;
  335. }
  336. return true;
  337. }
  338. public bool CheckBoatWaitCondition(out string reason)
  339. {
  340. reason = "";
  341. if (!IsWaitBoatMoveComplete)
  342. return true;
  343. if (_boatTargetPosition == "RotateHome")
  344. {
  345. if (!RAxisDevice.IsHomeDone)
  346. {
  347. reason = "rotate not home done";
  348. return false;
  349. }
  350. return (Singleton<EquipmentManager>.Instance.Modules[ModuleName.Boat] as BoatModule).IsReady;
  351. }
  352. else
  353. {
  354. if (!ZAxisDevice.CheckServoAtPosition(_boatTargetPosition))
  355. {
  356. reason = $"elevator not at {_boatTargetPosition}";
  357. return false;
  358. }
  359. return (Singleton<EquipmentManager>.Instance.Modules[ModuleName.Boat] as BoatModule).IsReady;
  360. }
  361. }
  362. public bool CheckAPCWaitCondition(out string reason)
  363. {
  364. return APCDevice.CheckWaitCondition(out reason);
  365. }
  366. public bool CheckMFCWaitCondition(out string reason)
  367. {
  368. reason = "";
  369. var ret = true;
  370. foreach (var mfc in _processMFCs)
  371. {
  372. if (!mfc.CheckWaitCondition(out string info))
  373. {
  374. reason += $"{info} \n";
  375. ret = false;
  376. }
  377. }
  378. return ret;
  379. }
  380. public bool CheckHeaterWaitCondition(out string reason)
  381. {
  382. reason = "";
  383. var ret = true;
  384. foreach (var heater in _heaters)
  385. {
  386. if (!heater.CheckWaitCondition(out string info))
  387. {
  388. reason += $"{info} \n";
  389. ret = false;
  390. }
  391. }
  392. return ret;
  393. }
  394. public void AbortRecipe()
  395. {
  396. _processMFCs.ForEach(x => x.Terminate());
  397. _heaters.ForEach(x => x.Terminate());
  398. _valves.ForEach(x => x.Terminate());
  399. ZAxisDevice.ServoStop();
  400. RAxisDevice.ServoStop();
  401. APC.Terminate();
  402. AbortLeakCheck();
  403. IsWait = false;
  404. }
  405. public void HeaterEnable(bool isEnable)
  406. {
  407. _heaters.ForEach(x => x.SetEnable(isEnable));
  408. }
  409. public bool CheckHeaterProfileFinish(out string reason)
  410. {
  411. reason = "";
  412. if (_heaters.Any(x => x.IsProfileMode))
  413. {
  414. IsHeaterProfile = true;
  415. var ret = true;
  416. foreach (var heater in _heaters)
  417. {
  418. if (!heater.CheckProfileFinish(out string info))
  419. {
  420. reason += $"{info} \n";
  421. ret = false;
  422. }
  423. }
  424. if (!ret)
  425. {
  426. foreach (var heater in _heaters)
  427. {
  428. heater.IsProfileSuccess = false;//有任何一个没结束,所有都要接着判断
  429. }
  430. _profileTrig.CLK = false;
  431. return false;//有任何一个没结束
  432. }
  433. if (HeaterU.IsProfileSuccess &&
  434. HeaterCU.IsProfileSuccess &&
  435. HeaterC.IsProfileSuccess &&
  436. HeaterCL.IsProfileSuccess &&
  437. HeaterL.IsProfileSuccess)
  438. {
  439. IsHeaterProfileSuccess = true;
  440. _profileTrig.CLK = true;
  441. _heaters.ForEach(x => x.DeviceData.ProfileStatus = "Normal End");
  442. _heaters.ForEach(x => x.ProfileFinish());
  443. if (_profileTrig.Q)
  444. SaveHeaterProflieToCorrectTable(_heaters[0].CurrentCorrectFileName, _heaters[0].CurrentCorrectIndex);//更新profile table
  445. }
  446. return true;
  447. }
  448. else
  449. {
  450. _heaters.ForEach(x => x.ProfileFinish());
  451. return true;//不处于profile模式
  452. }
  453. }
  454. private void SaveHeaterProflieToCorrectTable(string correctFileName, int tableIndex)
  455. {
  456. var content = ParameterFileManager.Instance.LoadParameter("Parameter\\TempCorrection", correctFileName, false);
  457. if (string.IsNullOrEmpty(content))
  458. {
  459. EV.PostWarningLog(Module, $"{correctFileName} heater temperature correct file is empty");
  460. return;
  461. }
  462. var doc = new XmlDocument();
  463. doc.LoadXml(content);
  464. XmlNodeList nodeSteps = doc.SelectNodes($"Aitex/TableParameterData/Module[@Name='']/Step");
  465. if (nodeSteps == null)
  466. nodeSteps = doc.SelectNodes($"Aitex/TableParameterData/Step");
  467. if (nodeSteps == null)
  468. {
  469. EV.PostWarningLog(Module, $"Invalid heater temperature correct file {correctFileName}");
  470. return;
  471. }
  472. if (tableIndex < 1 || nodeSteps.Count < tableIndex)
  473. {
  474. EV.PostWarningLog(Module, $"{correctFileName} heater temperature correct file table id={tableIndex} is invalid");
  475. return;
  476. }
  477. XmlElement targetStepNode = nodeSteps[tableIndex - 1] as XmlElement;
  478. if (targetStepNode != null)
  479. {
  480. var correctionDataString = targetStepNode.GetAttribute("CorrectionData");
  481. if (string.IsNullOrEmpty(correctionDataString))
  482. {
  483. EV.PostWarningLog(Module, $"Heater temperature correct file is empty");
  484. return;
  485. }
  486. var correctionDatas = correctionDataString.Split('|');
  487. if (correctionDatas.Length < 5)
  488. {
  489. EV.PostWarningLog(Module, $"Heater temperature correct file data length is invalid");
  490. return;
  491. }
  492. List<string> newCorrectionDatas = new List<string>();
  493. for (int i = 0; i < correctionDatas.Length; i++)
  494. {
  495. var datas = correctionDatas[i];
  496. var dataArry = datas.Split(';');
  497. if (dataArry.Length < 6)
  498. {
  499. EV.PostWarningLog(Module, $"Heater temperature correct file data length is invalid");
  500. return;
  501. }
  502. var correctParameter = new CorrectParameter();
  503. foreach (var item in dataArry)
  504. {
  505. var itemArry = item.Split(':');
  506. if (itemArry.Length < 2)
  507. {
  508. EV.PostWarningLog(Module, $"Heater temperature correct file data length is invalid");
  509. return;
  510. }
  511. switch (itemArry[0].ToLower())
  512. {
  513. case "index":
  514. int.TryParse(itemArry[1], out int no);
  515. correctParameter.No = no;
  516. break;
  517. case "name":
  518. correctParameter.Name = itemArry[1];
  519. break;
  520. case "profiletemp":
  521. float.TryParse(itemArry[1], out float profiletemp);
  522. correctParameter.ProfileTemp = profiletemp;
  523. break;
  524. case "profilecorrect":
  525. float.TryParse(itemArry[1], out float profilecorrect);
  526. correctParameter.ProfileCorrect = profilecorrect;
  527. break;
  528. case "cascadetccorrect":
  529. float.TryParse(itemArry[1], out float cascadetccorrect);
  530. correctParameter.CascadeTCCorrect = cascadetccorrect;
  531. break;
  532. case "profiletccalib":
  533. float.TryParse(itemArry[1], out float profiletccalib);
  534. correctParameter.ProfileTCCalib = profiletccalib;
  535. break;
  536. }
  537. }
  538. FurnaceRT.Devices.IoHeater heater = null;
  539. if (_heaters.Count > i)
  540. {
  541. heater = _heaters[i];
  542. }
  543. if (heater != null)
  544. {
  545. newCorrectionDatas.Add($"Index:{correctParameter.No};Name:{correctParameter.Name};ProfileTemp:{heater.TempSetPoint};ProfileCorrect:{(heater.DeviceData.HeaterPV - heater.DeviceData.CascadePV).ToString("f1")};CascadeTCCorrect:{correctParameter.CascadeTCCorrect};ProfileTCCalib:{correctParameter.ProfileTCCalib}");
  546. heater.DeviceData.ProfileResult = correctParameter.ProfileCorrect;
  547. }
  548. }
  549. if (newCorrectionDatas.Count == correctionDatas.Length)
  550. targetStepNode.SetAttribute("CorrectionData", string.Join("|", newCorrectionDatas.ToArray()));
  551. LOG.Write($"Profile result {correctFileName}:{tableIndex} CorrectionData={string.Join("|", newCorrectionDatas.ToArray())}");
  552. //FileStream fileStream = new FileStream(ParameterFileManager.Instance.GenerateParameterFilePath("Parameter\\TempCorrection", correctFileName), FileMode.Create);
  553. //doc.Save(fileStream);
  554. using (FileStream fileStream = new FileStream(ParameterFileManager.Instance.GenerateParameterFilePath("Parameter\\TempCorrection", correctFileName), FileMode.Create))
  555. {
  556. doc.Save(fileStream);
  557. }
  558. }
  559. }
  560. private bool SetAlarmConditionTable(object[] param)
  561. {
  562. if (param == null || param.Length < 1)
  563. {
  564. return false;
  565. }
  566. var array = param[0].ToString().Split(':');
  567. int.TryParse(array[0], out int index);
  568. lock (_alarmConditionLocker)
  569. {
  570. SetAlarmConditionTableIndex(index);
  571. }
  572. return true;
  573. }
  574. }
  575. }