RinseEntity.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. using Aitex.Core.RT.DataCenter;
  2. using Aitex.Core.RT.Device;
  3. using Aitex.Core.RT.Fsm;
  4. using Aitex.Core.RT.Log;
  5. using Aitex.Core.RT.OperationCenter;
  6. using Aitex.Core.Util;
  7. using Aitex.Core.Utilities;
  8. using MECF.Framework.Common.Equipment;
  9. using MECF.Framework.Common.SubstrateTrackings;
  10. using MECF.Framework.Common.WaferHolder;
  11. using CyberX8_Core;
  12. using CyberX8_RT.Devices.Rinse;
  13. using System;
  14. using System.Collections.Generic;
  15. using System.Linq;
  16. using MECF.Framework.Common.Persistent.Rinse;
  17. using MECF.Framework.Common.RecipeCenter;
  18. using Aitex.Core.RT.RecipeCenter;
  19. using CyberX8_RT.Devices.Safety;
  20. using Aitex.Core.RT.SCCore;
  21. using MECF.Framework.Common.Alarm;
  22. using MECF.Framework.Common.CommonData;
  23. using CyberX8_RT.Schedulers;
  24. using CyberX8_RT.Modules.Dryer;
  25. using MECF.Framework.Common.ProcessCell;
  26. namespace CyberX8_RT.Modules.Rinse
  27. {
  28. public class RinseEntity : Entity, IEntity, IModuleEntity
  29. {
  30. #region 常量
  31. private const string AUTO = "Auto";
  32. private const string MANUAL = "Manual";
  33. private const string DISABLED = "Disabled";
  34. private const string ENGINEERING = "Engineering";
  35. private const string PRODUCTION = "Production";
  36. #endregion
  37. #region 内部变量
  38. /// <summary>
  39. /// Rinse设备
  40. /// </summary>
  41. private RinseDevice _rinseDevice;
  42. /// <summary>
  43. /// Cycle次数
  44. /// </summary>
  45. private int _cycle = 0;
  46. /// <summary>
  47. /// 已经完成的Cycle次数
  48. /// </summary>
  49. private int _achievedCycle = 0;
  50. /// <summary>
  51. /// Manual模式下Cycle run
  52. /// </summary>
  53. private RinseCycleManualProcessRecipeRoutine _cycleManualProcessRoutine;
  54. /// <summary>
  55. /// Keepwet Routine
  56. /// </summary>
  57. private RinseKeepwetRoutine _keepwetRoutine;
  58. /// <summary>
  59. /// Recipe时长
  60. /// </summary>
  61. private Dictionary<string, int> _dictRecipeTime = new Dictionary<string, int>();
  62. /// <summary>
  63. /// 持久性对象
  64. /// </summary>
  65. private RinsePersistentValue _persistentValue;
  66. /// <summary>
  67. /// 当前Recipe
  68. /// </summary>
  69. private QdrRecipe _currentRecipe;
  70. /// <summary>
  71. /// Recipe时长
  72. /// </summary>
  73. private int _recipeTime;
  74. /// <summary>
  75. /// Runrecipe已经运行的时间
  76. /// </summary>
  77. private int _runrecipeElapsedTime = 0;
  78. /// <summary>
  79. /// run recipe start time
  80. /// </summary>
  81. private DateTime _runRecipeStartTime;
  82. /// <summary>
  83. /// run recipe complete time
  84. /// </summary>
  85. private DateTime _runRecipeCompleteTime;
  86. /// <summary>
  87. /// 是否Retry
  88. /// </summary>
  89. private bool _isRetry = false;
  90. #region 计算recipe运行时间相关的配置文件参数
  91. /// <summary>
  92. /// Concurrent Fill Time Seconds
  93. /// </summary>
  94. private int _concurrentFillTimeSeconds;
  95. /// <summary>
  96. /// 开始注水的偏差
  97. /// </summary>
  98. private double _fillingStartedDelta;
  99. /// <summary>
  100. /// 注满数值
  101. /// </summary>
  102. private int _sensorReadingFull;
  103. /// <summary>
  104. /// 液位为空数值
  105. /// </summary>
  106. private int _sensorReadingEmpty;
  107. /// <summary>
  108. /// 从开始排水到检测是否排空的间隔时间
  109. /// </summary>
  110. private int _normalDrainTimeSeconds;
  111. /// <summary>
  112. /// 开始注水后检测是否正常注水间隔
  113. /// </summary>
  114. private int _checkIsFillingTimeSeconds;
  115. /// <summary>
  116. /// 开始注水后检测是否注满间隔
  117. /// </summary>
  118. private int _checkIsFullTimeSeconds;
  119. /// <summary>
  120. /// Clamp Cycle开关次数
  121. /// </summary>
  122. private int _numberClampCyclesToComplete;
  123. /// <summary>
  124. /// Clamp开关等待时间
  125. /// </summary>
  126. private double _clampCycleTimeSeconds;
  127. #endregion
  128. #endregion
  129. #region 属性
  130. /// <summary>
  131. /// 模块名称
  132. /// </summary>
  133. public ModuleName Module { get; private set; }
  134. /// <summary>
  135. /// 初始化状态
  136. /// </summary>
  137. public bool IsInit
  138. {
  139. get { return fsm.State == (int)RinseState.Init; }
  140. }
  141. /// <summary>
  142. /// 是否完成初始化
  143. /// </summary>
  144. public bool IsInitialized
  145. {
  146. get { return fsm.State >= (int)RinseState.Initialized; }
  147. }
  148. /// <summary>
  149. /// 空闲状态
  150. /// </summary>
  151. public bool IsIdle
  152. {
  153. get
  154. {
  155. return fsm.State == (int)RinseState.Idle;
  156. }
  157. }
  158. /// <summary>
  159. /// 是否发生错误
  160. /// </summary>
  161. public bool IsError
  162. {
  163. get { return fsm.State == (int)RinseState.Error; }
  164. }
  165. /// <summary>
  166. /// 是否正在作业
  167. /// </summary>
  168. public bool IsBusy { get { return fsm.State > (int)RinseState.Idle; } }
  169. /// <summary>
  170. /// WaferHolder信息
  171. /// </summary>
  172. public WaferHolderInfo WaferHolderInfo { get { return WaferHolderManager.Instance.GetWaferHolder(Module.ToString()); } }
  173. /// <summary>
  174. /// 已完成的RunRecipeCycle次数
  175. /// </summary>
  176. public int AchievedCycle { get { return _achievedCycle; } }
  177. /// <summary>
  178. /// 当前状态机状态
  179. /// </summary>
  180. public int State { get { return fsm.State; } }
  181. /// <summary>
  182. /// Recipe时长
  183. /// </summary>
  184. public int RecipeTime
  185. {
  186. get { return _recipeTime; }
  187. }
  188. /// <summary>
  189. /// 剩余时间
  190. /// </summary>
  191. public override int TimeToReady
  192. {
  193. get
  194. {
  195. if (_currentRecipe == null)
  196. {
  197. return base.TimeToReady;
  198. }
  199. switch (fsm.State)
  200. {
  201. case (int)RinseState.RunReciping:
  202. return Math.Max(_recipeTime - fsm.ElapsedTime / 1000, 0);
  203. default:
  204. return base.TimeToReady;
  205. }
  206. }
  207. }
  208. /// <summary>
  209. /// 是否禁用
  210. /// </summary>
  211. public bool IsDisable { get { return _persistentValue == null || _persistentValue.OperatingMode == DISABLED; } }
  212. /// <summary>
  213. /// 自动模式
  214. /// </summary>
  215. public bool IsAuto { get { return _persistentValue != null && _persistentValue.OperatingMode == AUTO; } }
  216. /// <summary>
  217. /// 自动模式
  218. /// </summary>
  219. public bool IsManual { get { return _persistentValue != null && _persistentValue.OperatingMode == MANUAL; } }
  220. /// <summary>
  221. /// 是否为工程模式
  222. /// </summary>
  223. public bool IsEngineering { get { return _persistentValue != null && _persistentValue.RecipeOperatingMode == ENGINEERING; } }
  224. /// <summary>
  225. /// 是否为产品模式
  226. /// </summary>
  227. public bool IsProduction { get { return _persistentValue != null && _persistentValue.RecipeOperatingMode == PRODUCTION; } }
  228. #endregion
  229. /// <summary>
  230. /// 构造函数
  231. /// </summary>
  232. /// <param name="module"></param>
  233. public RinseEntity(ModuleName module)
  234. {
  235. Module = module;
  236. _rinseDevice=DEVICE.GetDevice<RinseDevice>(Module.ToString());
  237. WaferManager.Instance.SubscribeLocation(Module, 2);
  238. //相关配置文件
  239. InitialFsm();
  240. }
  241. /// <summary>
  242. /// 初始化
  243. /// </summary>
  244. /// <returns></returns>
  245. protected override bool Init()
  246. {
  247. InitializeParameter();
  248. InitializeDATA();
  249. InitializeRoutine();
  250. InitializeOperation();
  251. InitializeRoutine();
  252. return true;
  253. }
  254. /// <summary>
  255. /// 初始化状态机
  256. /// </summary>
  257. private void InitialFsm()
  258. {
  259. fsm = new StateMachine<RinseEntity>(Module.ToString(), (int)RinseState.Init, 20);
  260. fsm.EnableRepeatedMsg(true);
  261. AnyStateTransition(RinseMsg.Error, ErrorSolution, RinseState.Error);
  262. Transition(RinseState.Error, RinseMsg.ResumeError, (param) => { return true; }, RinseState.Init);
  263. //Initialized
  264. AnyStateTransition(RinseMsg.Initialize, InitializeAll, RinseState.Initialized);
  265. //直接进入Idle
  266. Transition(RinseState.Initialized, FSM_MSG.TIMER, NullFunc, RinseState.Idle);
  267. //CycleRunRecipe
  268. Transition(RinseState.Idle, RinseMsg.CycleProcessRecipe, RunRecipeProcess, RinseState.CycleManualProcessing);
  269. Transition(RinseState.CycleManualProcessing, FSM_MSG.TIMER, RunRecipeMonitor, RinseState.Idle);
  270. Transition(RinseState.CycleManualProcessing,RinseMsg.Abort,RunRecipeAbort, RinseState.Idle);
  271. //RunRecipe
  272. Transition(RinseState.Idle, RinseMsg.RunRecipe, RunRecipeProcess, RinseState.RunReciping);
  273. Transition(RinseState.RunReciping, FSM_MSG.TIMER, RunRecipeMonitor, RinseState.RunRecipeComplete);
  274. Transition(RinseState.RunRecipeComplete, RinseMsg.RecipeComplete, NullFunc, RinseState.Idle);
  275. Transition(RinseState.RunReciping, RinseMsg.Abort, RunRecipeAbort, RinseState.Abort);
  276. //KeepWet
  277. Transition(RinseState.RunRecipeComplete, RinseMsg.Keepwet, Keepwet, RinseState.KeepWeting);
  278. Transition(RinseState.KeepWetComplete, RinseMsg.Keepwet, Keepwet, RinseState.KeepWeting);
  279. Transition(RinseState.KeepWeting, FSM_MSG.TIMER, KeepwetMonitor, RinseState.KeepWetComplete);
  280. Transition(RinseState.KeepWeting, RinseMsg.RecipeComplete, KeepwetingComplete, RinseState.Idle);
  281. //Enter Init
  282. Transition(RinseState.Idle, RinseMsg.Init, NullFunc, RinseState.Init);
  283. //Retry
  284. Transition(RinseState.Error, RinseMsg.Retry, NullFunc, RinseState.Retrying);
  285. Transition(RinseState.Retrying, FSM_MSG.TIMER, RinseRetry, RinseState.Retrying);
  286. Transition(RinseState.Retrying, RinseMsg.RunRecipe, RetryRunRecipe, RinseState.RunReciping);
  287. EnumLoop<RinseState>.ForEach((item) => { fsm.MapState((int)item, item.ToString()); });
  288. EnumLoop<RinseMsg>.ForEach((item) => { fsm.MapMessage((int)item, item.ToString()); });
  289. }
  290. /// <summary>
  291. /// 初始化参数
  292. /// </summary>
  293. private void InitializeParameter()
  294. {
  295. _persistentValue = RinsePersistentManager.Instance.GetRinsePersistentValue(Module.ToString());
  296. if (_persistentValue == null)
  297. {
  298. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module.ToString(), "Persistent Value Object is not exist");
  299. }
  300. }
  301. /// <summary>
  302. /// 初始化DATA
  303. /// </summary>
  304. private void InitializeDATA()
  305. {
  306. InitializeSvid();
  307. DATA.Subscribe($"{Module}.FsmState", () => ((RinseState)fsm.State).ToString(), SubscriptionAttribute.FLAG.IgnoreSaveDB);
  308. DATA.Subscribe($"{Module}.WaferHolder", () => WaferHolderInfo, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  309. DATA.Subscribe($"{Module}.IsInit", () => IsInit, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  310. DATA.Subscribe($"{Module}.IsIdle", () => IsIdle, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  311. DATA.Subscribe($"{Module}.IsError", () => IsError, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  312. DATA.Subscribe($"{Module}.IsBusy", () => IsBusy, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  313. DATA.Subscribe($"{Module}.IsDisable", () => IsDisable, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  314. DATA.Subscribe($"{Module}.AchievedCycle", () => AchievedCycle, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  315. DATA.Subscribe($"{Module}.CurrentRecipe", () => _currentRecipe != null ? _currentRecipe.Ppid : "", SubscriptionAttribute.FLAG.IgnoreSaveDB);
  316. }
  317. /// <summary>
  318. /// 初始化SVID
  319. /// </summary>
  320. private void InitializeSvid()
  321. {
  322. DATA.Subscribe($"{Module}.State", () => ((RinseState)fsm.State).ToString(), SubscriptionAttribute.FLAG.IgnoreSaveDB);
  323. DATA.Subscribe($"{Module}.LotID", () => (WaferHolderInfo!=null?WaferHolderInfo.LotId:""), SubscriptionAttribute.FLAG.IgnoreSaveDB);
  324. DATA.Subscribe($"{Module}.WSID", () => (WaferHolderInfo != null ? WaferHolderInfo.Id : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB);
  325. DATA.Subscribe($"{Module}.LSAID", () => (WaferHolderInfo != null ? WaferHolderInfo.CrsAId : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB);
  326. DATA.Subscribe($"{Module}.LSBID", () => (WaferHolderInfo != null ? WaferHolderInfo.CrsBId : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB);
  327. DATA.Subscribe($"{Module}.ModuleRecipe", () => (_currentRecipe != null ? _currentRecipe.Ppid : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB);
  328. DATA.Subscribe($"{Module}.SequenceRecipe", () => (WaferHolderInfo != null ? WaferHolderInfo.SequenceId : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB);
  329. DATA.Subscribe($"{Module}.WaferAID", () => (WaferHolderInfo != null ? WaferHolderInfo.WaferAId : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB);
  330. DATA.Subscribe($"{Module}.WaferBID", () => (WaferHolderInfo != null ? WaferHolderInfo.WaferBId : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB);
  331. DATA.Subscribe($"{Module}.TotalTime", () => _recipeTime, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  332. DATA.Subscribe($"{Module}.TimeRemain", () => _recipeTime != 0 ? (_recipeTime - Math.Round((double)_cycleManualProcessRoutine.ElapsedMilliseconds / 1000, 0)) : 0, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  333. DATA.Subscribe($"{Module}.Task", () => WaferHolderInfo != null ? WaferHolderInfo.CurrentControlJobId : "", SubscriptionAttribute.FLAG.IgnoreSaveDB);
  334. DATA.Subscribe($"{Module}.OperatingMode", () => _persistentValue != null ? _persistentValue.OperatingMode : "None", SubscriptionAttribute.FLAG.IgnoreSaveDB);
  335. }
  336. /// <summary>
  337. /// 初始化Routine
  338. /// </summary>
  339. private void InitializeRoutine()
  340. {
  341. _cycleManualProcessRoutine = new RinseCycleManualProcessRecipeRoutine(Module.ToString());
  342. _keepwetRoutine = new RinseKeepwetRoutine(Module.ToString());
  343. }
  344. /// <summary>
  345. /// 初始化操作
  346. /// </summary>
  347. private void InitializeOperation()
  348. {
  349. OP.Subscribe($"{Module}.InitializeAll", (cmd, args) => { return CheckToPostMessage<RinseState, RinseMsg>(eEvent.ERR_RINSE, Module.ToString(), (int)RinseMsg.Initialize); });
  350. OP.Subscribe($"{Module}.CycleManualProcessRecipe", (cmd, args) =>
  351. {
  352. QdrRecipe recipe = RecipeFileManager.Instance.LoadGenericityRecipe<QdrRecipe>(args[0].ToString());
  353. if (recipe == null)
  354. {
  355. LOG.WriteLog(eEvent.ERR_RINSE, Module.ToString(), $"{args[0]} recipe is null");
  356. return false;
  357. }
  358. object[] objects = new object[args.Length];
  359. objects[0] = recipe;
  360. for (int i = 1; i < args.Length; i++)
  361. {
  362. objects[i] = args[i];
  363. }
  364. return CheckToPostMessage<RinseState, RinseMsg>(eEvent.ERR_RINSE, Module.ToString(), (int)RinseMsg.CycleProcessRecipe, objects);
  365. });
  366. OP.Subscribe($"{Module}.Abort", (cmd, args) => { return CheckToPostMessage<RinseState, RinseMsg>(Aitex.Core.RT.Log.eEvent.ERR_RINSE, Module.ToString(), (int)RinseMsg.Abort); });
  367. }
  368. /// <summary>
  369. /// EnterInit
  370. /// </summary>
  371. public void EnterInit()
  372. {
  373. if ((RinseState)fsm.State != RinseState.Idle) return;
  374. else
  375. {
  376. CheckToPostMessage<RinseState, RinseMsg>(eEvent.ERR_RINSE, Module.ToString(), (int)RinseMsg.Init);
  377. }
  378. }
  379. #region Initialized
  380. /// <summary>
  381. /// Initialize
  382. /// </summary>
  383. /// <param name="param"></param>
  384. /// <returns></returns>
  385. private bool InitializeAll(object[] param)
  386. {
  387. if (fsm.State == (int)RinseState.Initializing)
  388. {
  389. LOG.WriteLog(eEvent.WARN_RINSE, Module.ToString(), "state is Initializing,cannot do initialize");
  390. return false;
  391. }
  392. _rinseDevice.UpdateStateMachine("Idle");
  393. _rinseDevice.UpdateStatus("Idle");
  394. if (!_rinseDevice.IOInitialized)
  395. {
  396. return false;
  397. }
  398. return _rinseDevice.IOInitialized;
  399. }
  400. #endregion
  401. private bool ErrorSolution(object[] param)
  402. {
  403. bool result = _rinseDevice.FillValveOff();
  404. if (!result)
  405. {
  406. LOG.WriteLog(eEvent.ERR_RINSE, "Close Fill Valve error");
  407. }
  408. result = _rinseDevice.N2ValveOff();
  409. if (!result)
  410. {
  411. LOG.WriteLog(eEvent.ERR_RINSE, "Close N2 Valve error");
  412. }
  413. return true;
  414. }
  415. #region RunRecipe
  416. /// <summary>
  417. /// Run Recipe
  418. /// </summary>
  419. /// <param name="param"></param>
  420. /// <returns></returns>
  421. private bool RunRecipeProcess(object[] param)
  422. {
  423. _concurrentFillTimeSeconds = SC.GetValue<int>("QDR.ConcurrentFillTimeSeconds");
  424. _fillingStartedDelta = SC.GetValue<double>("QDR.FillingStartedDelta");
  425. _sensorReadingFull = SC.GetValue<int>("QDR.SensorReadingFull");
  426. _sensorReadingEmpty = SC.GetValue<int>("QDR.SensorReadingEmpty");
  427. _normalDrainTimeSeconds = SC.GetValue<int>("QDR.NominalDrainTimeSeconds");
  428. _checkIsFillingTimeSeconds = SC.GetValue<int>("QDR.NominalCheckFillWaterTimeSeconds");
  429. _checkIsFullTimeSeconds = SC.GetValue<int>("QDR.NominalCheckFillFullTimeSeconds");
  430. _numberClampCyclesToComplete = SC.GetValue<int>("QDR.NumberClampCyclesToComplete");
  431. _clampCycleTimeSeconds = SC.GetValue<double>("QDR.ClampCycleTimeSeconds");
  432. _cycle = (int)param[1];
  433. QdrRecipe recipe = param[0] as QdrRecipe;
  434. bool result = _cycleManualProcessRoutine.Start(param) == RState.Running;
  435. _runrecipeElapsedTime = 0;
  436. if (result)
  437. {
  438. //_recipeTime = 0;
  439. _isRetry = false;
  440. _recipeTime = CalculateRunRecipeTime(recipe, _cycle);
  441. _currentRecipe = recipe;
  442. _runRecipeStartTime = DateTime.Now;
  443. if (WaferHolderInfo != null && _currentRecipe != null)
  444. {
  445. FaModuleNotifier.Instance.NotifyWaferShuttleRecipeStart(WaferHolderInfo, _currentRecipe.Ppid);
  446. }
  447. }
  448. return result;
  449. }
  450. private int CalculateRunRecipeTime(QdrRecipe _recipe, int cycle)
  451. {
  452. int totaltime = 0;
  453. Dictionary<string, int> processTimeDic = new Dictionary<string, int>();
  454. processTimeDic.Add("RinseFirstStep.WaitDrianEmpty", _recipe.DumpTimeSeconds);
  455. if (_recipe.Step1N2BubbleOn)
  456. {
  457. processTimeDic.Add("RinseFirstStep.N2BubbleOnDelay", _recipe.N2ChargeTimeSeconds);
  458. }
  459. processTimeDic.Add("RinseFirstStep.Recipe_FirstRinseCycleWaitEndFillTime", _concurrentFillTimeSeconds * _recipe.Step1NumberOfRinse);
  460. processTimeDic.Add("RinseFirstStep.Recipe_FirstRinseCycleWaitDwell", _recipe.Step1DwellTimeSeconds * _recipe.Step1NumberOfRinse);
  461. processTimeDic.Add("RinseFirstStep.Recipe_FirstRinseCycleWaitDrainExtraTime", _recipe.DumpTimeSeconds * _recipe.Step1NumberOfRinse);
  462. if (!_recipe.FinalRinseDry) //没有第三步rinse
  463. {
  464. processTimeDic.Add("RinseSecondStep.Recipe_SecondRinseCycleWaitEndFillTime", _concurrentFillTimeSeconds * _recipe.Step2NumberOfRinse);
  465. processTimeDic.Add("RinseSecondStep.Recipe_SecondRinseCycleWaitDwell", _recipe.Step2DwellTimeSeconds * (_recipe.Step2NumberOfRinse - 1));
  466. processTimeDic.Add("RinseSecondStep.Recipe_SecondRinseCycleWaitDrainExtraTime", _recipe.DumpTimeSeconds * _recipe.Step2NumberOfRinse);
  467. processTimeDic.Add("RinseSecondStep.Recipe_SecondRinseCycleWaitResistivityStart", _recipe.ResistivityStartTimeSeconds);
  468. processTimeDic.Add("RinseSecondStep.Recipe_SecondRinseCycleResistivityAveraging", _recipe.ResistivityDurationSeconds);
  469. }
  470. else //有第三步rinse
  471. {
  472. processTimeDic.Add("RinseSecondStep.Recipe_SecondRinseCycleWaitEndFillTime", _concurrentFillTimeSeconds * _recipe.Step2NumberOfRinse);
  473. processTimeDic.Add("RinseSecondStep.Recipe_SecondRinseCycleWaitDwell", _recipe.Step2DwellTimeSeconds * _recipe.Step2NumberOfRinse);
  474. processTimeDic.Add("RinseSecondStep.Recipe_SecondRinseCycleWaitDrainExtraTime", _recipe.DumpTimeSeconds * _recipe.Step2NumberOfRinse);
  475. processTimeDic.Add("RinseThirdStep.Recipe_ThirdRinseWaitEndFillTime", _concurrentFillTimeSeconds);
  476. processTimeDic.Add("RinseThirdStep.Recipe_ThirdRinseCycleWaitSlowDrainTime", _recipe.FinalRinseSlowDrainTime);
  477. processTimeDic.Add("RinseThirdStep.Recipe_ThirdRinseCycleWaitDrainExtraTime", _recipe.DumpTimeSeconds);
  478. }
  479. totaltime = processTimeDic.Sum(x => x.Value);
  480. return totaltime * cycle;
  481. }
  482. /// <summary>
  483. /// Retry RunRecipe
  484. /// </summary>
  485. /// <param name="param"></param>
  486. /// <returns></returns>
  487. private bool RetryRunRecipe(object[] param)
  488. {
  489. int stepIndex = (int)param[0];
  490. bool result = _cycleManualProcessRoutine.Retry(stepIndex) == RState.Running;
  491. if (result)
  492. {
  493. _isRetry = true;
  494. if (_currentRecipe != null)
  495. {
  496. _recipeTime = CalculateRunRecipeTime(_currentRecipe, _cycle);
  497. }
  498. }
  499. return result;
  500. }
  501. /// <summary>
  502. /// 监控
  503. /// </summary>
  504. /// <param name="param"></param>
  505. /// <returns></returns>
  506. private bool RunRecipeMonitor(object[] param)
  507. {
  508. RState state = _cycleManualProcessRoutine.Monitor();
  509. if (Singleton<RouteManager>.Instance.IsAutoRunning&&_runrecipeElapsedTime!=TimeToReady)
  510. {
  511. _runrecipeElapsedTime =TimeToReady;
  512. LOG.WriteLog(eEvent.INFO_RINSE, Module.ToString(), $"{WaferHolderInfo?.Id} {Module} RunRecipe TimeToReady {_recipeTime-fsm.ElapsedTime/1000}s.");
  513. }
  514. if (state == RState.Failed || state == RState.Timeout)
  515. {
  516. if (Singleton<RouteManager>.Instance.IsAutoRunning)
  517. {
  518. //不存在其他可用的Rinse
  519. if (!CheckOtherRinseAvaible())
  520. {
  521. AlarmList alarmList = new AlarmList(Module.ToString(), ((RinseState)fsm.State).ToString(), (int)RinseMsg.RunRecipe,
  522. _cycleManualProcessRoutine.ErrorMsg, _cycleManualProcessRoutine.ErrorStep, (int)AlarmType.Error);
  523. AlarmListManager.Instance.AddAlarm(alarmList);
  524. }
  525. }
  526. PostMsg(RinseMsg.Error);
  527. _rinseDevice.UpdateStateMachine("Error");
  528. _rinseDevice.UpdateStatus("Error");
  529. _runrecipeElapsedTime = 0;
  530. //记录LotTrack
  531. _runRecipeCompleteTime = DateTime.Now;
  532. _cycleManualProcessRoutine.RinseLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2");
  533. RinseLotTrackUtil.ExportRinseLotTrack(Module.ToString(), _cycleManualProcessRoutine.RinseLotTrackDatas,
  534. _cycleManualProcessRoutine.RinseLotTrackHeaderDatas, IsAuto, _isRetry);
  535. if (WaferHolderInfo != null && _currentRecipe != null)
  536. {
  537. FaModuleNotifier.Instance.NotifyWaferShuttleRecipeFailed(WaferHolderInfo, _currentRecipe.Ppid);
  538. }
  539. return false;
  540. }
  541. _achievedCycle = _cycleManualProcessRoutine.GetAchievedCycle();
  542. bool result = state == RState.End;
  543. if (result)
  544. {
  545. _runrecipeElapsedTime = 0;
  546. if (Singleton<RouteManager>.Instance.IsAutoRunning)
  547. {
  548. AlarmListManager.Instance.CheckModuleAlamAndRemove(Module.ToString(), RinseState.RunReciping.ToString());
  549. }
  550. //记录LotTrack
  551. _runRecipeCompleteTime = DateTime.Now;
  552. int timeLength = (int)(_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds;
  553. _cycleManualProcessRoutine.RinseLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2");
  554. RinseLotTrackUtil.ExportRinseLotTrack(Module.ToString(), _cycleManualProcessRoutine.RinseLotTrackDatas,
  555. _cycleManualProcessRoutine.RinseLotTrackHeaderDatas, IsAuto, _isRetry);
  556. if (WaferHolderInfo != null && _currentRecipe != null)
  557. {
  558. FaModuleNotifier.Instance.NotifyWaferShuttleRecipeEnd(WaferHolderInfo, _currentRecipe.Ppid, timeLength);
  559. }
  560. }
  561. return result;
  562. }
  563. /// <summary>
  564. /// 校验其他rinse是否可用
  565. /// </summary>
  566. /// <returns></returns>
  567. private bool CheckOtherRinseAvaible()
  568. {
  569. ModuleName metalName = WaferHolderInfo.MetalModuleName;
  570. if (metalName!=ModuleName.Unknown)
  571. {
  572. return SchedulerSequenceManager.Instance.GetAvaibleModuleCell(_persistentValue.RecipeOperatingMode,ModuleType.Rinse, metalName)!=ModuleName.Unknown;
  573. }
  574. else
  575. {
  576. return false;
  577. }
  578. }
  579. private bool RunRecipeAbort(object[] param)
  580. {
  581. _cycleManualProcessRoutine.Abort();
  582. _rinseDevice.UpdateStateMachine("Abort");
  583. _rinseDevice.UpdateStatus("Abort");
  584. //记录LotTrack
  585. _runRecipeCompleteTime = DateTime.Now;
  586. _cycleManualProcessRoutine.RinseLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2");
  587. RinseLotTrackUtil.ExportRinseLotTrack(Module.ToString(), _cycleManualProcessRoutine.RinseLotTrackDatas,
  588. _cycleManualProcessRoutine.RinseLotTrackHeaderDatas, IsAuto, _isRetry);
  589. return true;
  590. }
  591. #endregion
  592. #region Keepwet
  593. /// <summary>
  594. /// keepwet
  595. /// </summary>
  596. /// <param name="param"></param>
  597. /// <returns></returns>
  598. private bool Keepwet(object[] param)
  599. {
  600. return _keepwetRoutine.Start(param) == RState.Running;
  601. }
  602. /// <summary>
  603. /// 停止Keepwet
  604. /// </summary>
  605. /// <param name="param"></param>
  606. /// <returns></returns>
  607. private bool KeepwetingComplete(object[] param)
  608. {
  609. // _keepwetRoutine.Abort();
  610. return true;
  611. }
  612. /// <summary>
  613. /// keepwet
  614. /// </summary>
  615. /// <param name="param"></param>
  616. /// <returns></returns>
  617. private bool KeepwetMonitor(object[] param)
  618. {
  619. RState ret = _keepwetRoutine.Monitor();
  620. if (ret == RState.End)
  621. {
  622. return true;
  623. }
  624. if (ret == RState.Failed || ret == RState.Timeout)
  625. {
  626. PostMsg(RinseMsg.Error);
  627. }
  628. return false;
  629. }
  630. #endregion
  631. #region RinseRetry
  632. /// <summary>
  633. /// Retry
  634. /// </summary>
  635. /// <param name="param"></param>
  636. /// <returns></returns>
  637. private bool RinseRetry(object[] param)
  638. {
  639. AlarmList alarmList = AlarmListManager.Instance.GetAlarmListByModule(Module.ToString());
  640. if (alarmList != null)
  641. {
  642. CheckToPostMessage<RinseState, RinseMsg>(eEvent.WARN_RINSE, Module.ToString(), alarmList.ModuleCmd,
  643. alarmList.ModuleStep);
  644. }
  645. return false;
  646. }
  647. #endregion
  648. public bool Check(int msg, out string reason, params object[] args)
  649. {
  650. reason = "";
  651. return true;
  652. }
  653. public bool CheckAcked(int msg)
  654. {
  655. return true;
  656. }
  657. public int Invoke(string function, params object[] args)
  658. {
  659. switch (function)
  660. {
  661. case "HomeAll":
  662. if (IsIdle)
  663. {
  664. return (int)FSM_MSG.NONE;
  665. }
  666. if (CheckToPostMessage<RinseState, RinseMsg>(eEvent.ERR_RINSE, Module.ToString(), (int)RinseMsg.Initialize))
  667. {
  668. return (int)RinseMsg.Initialize;
  669. }
  670. else
  671. {
  672. return (int)FSM_MSG.NONE;
  673. }
  674. case "Retry":
  675. if (CheckToPostMessage<RinseState, RinseMsg>(eEvent.ERR_RINSE, Module.ToString(), (int)RinseMsg.Retry))
  676. {
  677. return (int)RinseMsg.Retry;
  678. }
  679. else
  680. {
  681. return (int)FSM_MSG.NONE;
  682. }
  683. }
  684. return (int)FSM_MSG.NONE;
  685. }
  686. }
  687. public enum RinseMsg
  688. {
  689. Error,
  690. Initialize,
  691. ResumeError,
  692. CycleProcessRecipe,
  693. RunRecipe,
  694. Abort,
  695. Keepwet,
  696. RecipeComplete,
  697. Init,
  698. Retry
  699. }
  700. }