RinseEntity.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  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 (!CheckSafety())
  395. {
  396. return false;
  397. }
  398. if (!_rinseDevice.IOInitialized)
  399. {
  400. return false;
  401. }
  402. return _rinseDevice.IOInitialized;
  403. }
  404. /// <summary>
  405. /// 检验Safety
  406. /// </summary>
  407. /// <returns></returns>
  408. private bool CheckSafety()
  409. {
  410. SafetyDevice safetyDevice = DEVICE.GetDevice<SafetyDevice>("Safety");
  411. if (safetyDevice != null)
  412. {
  413. bool result= safetyDevice.SafetyData.TwincatState == 8;
  414. if (!result)
  415. {
  416. LOG.WriteLog(eEvent.ERR_RINSE, Module.ToString(), "Twincat Status is not OP status");
  417. return false;
  418. }
  419. }
  420. return true;
  421. }
  422. #endregion
  423. private bool ErrorSolution(object[] param)
  424. {
  425. bool result = _rinseDevice.FillValveOff();
  426. if (!result)
  427. {
  428. LOG.WriteLog(eEvent.ERR_RINSE, "Close Fill Valve error");
  429. }
  430. result = _rinseDevice.N2ValveOff();
  431. if (!result)
  432. {
  433. LOG.WriteLog(eEvent.ERR_RINSE, "Close N2 Valve error");
  434. }
  435. return true;
  436. }
  437. #region RunRecipe
  438. /// <summary>
  439. /// Run Recipe
  440. /// </summary>
  441. /// <param name="param"></param>
  442. /// <returns></returns>
  443. private bool RunRecipeProcess(object[] param)
  444. {
  445. _concurrentFillTimeSeconds = SC.GetValue<int>("QDR.ConcurrentFillTimeSeconds");
  446. _fillingStartedDelta = SC.GetValue<double>("QDR.FillingStartedDelta");
  447. _sensorReadingFull = SC.GetValue<int>("QDR.SensorReadingFull");
  448. _sensorReadingEmpty = SC.GetValue<int>("QDR.SensorReadingEmpty");
  449. _normalDrainTimeSeconds = SC.GetValue<int>("QDR.NominalDrainTimeSeconds");
  450. _checkIsFillingTimeSeconds = SC.GetValue<int>("QDR.NominalCheckFillWaterTimeSeconds");
  451. _checkIsFullTimeSeconds = SC.GetValue<int>("QDR.NominalCheckFillFullTimeSeconds");
  452. _numberClampCyclesToComplete = SC.GetValue<int>("QDR.NumberClampCyclesToComplete");
  453. _clampCycleTimeSeconds = SC.GetValue<double>("QDR.ClampCycleTimeSeconds");
  454. _cycle = (int)param[1];
  455. QdrRecipe recipe = param[0] as QdrRecipe;
  456. bool result = _cycleManualProcessRoutine.Start(param) == RState.Running;
  457. _runrecipeElapsedTime = 0;
  458. if (result)
  459. {
  460. //_recipeTime = 0;
  461. _isRetry = false;
  462. _recipeTime = CalculateRunRecipeTime(recipe, _cycle);
  463. _currentRecipe = recipe;
  464. _runRecipeStartTime = DateTime.Now;
  465. if (WaferHolderInfo != null && _currentRecipe != null)
  466. {
  467. FaModuleNotifier.Instance.NotifyWaferShuttleRecipeStart(WaferHolderInfo, _currentRecipe.Ppid);
  468. }
  469. }
  470. return result;
  471. }
  472. private int CalculateRunRecipeTime(QdrRecipe _recipe, int cycle)
  473. {
  474. int totaltime = 0;
  475. Dictionary<string, int> processTimeDic = new Dictionary<string, int>();
  476. processTimeDic.Add("RinseFirstStep.WaitDrianEmpty", _recipe.DumpTimeSeconds);
  477. if (_recipe.Step1N2BubbleOn)
  478. {
  479. processTimeDic.Add("RinseFirstStep.N2BubbleOnDelay", _recipe.N2ChargeTimeSeconds);
  480. }
  481. processTimeDic.Add("RinseFirstStep.Recipe_FirstRinseCycleWaitEndFillTime", _concurrentFillTimeSeconds * _recipe.Step1NumberOfRinse);
  482. processTimeDic.Add("RinseFirstStep.Recipe_FirstRinseCycleWaitDwell", _recipe.Step1DwellTimeSeconds * _recipe.Step1NumberOfRinse);
  483. processTimeDic.Add("RinseFirstStep.Recipe_FirstRinseCycleWaitDrainExtraTime", _recipe.DumpTimeSeconds * _recipe.Step1NumberOfRinse);
  484. if (!_recipe.FinalRinseDry) //没有第三步rinse
  485. {
  486. processTimeDic.Add("RinseSecondStep.Recipe_SecondRinseCycleWaitEndFillTime", _concurrentFillTimeSeconds * _recipe.Step2NumberOfRinse);
  487. processTimeDic.Add("RinseSecondStep.Recipe_SecondRinseCycleWaitDwell", _recipe.Step2DwellTimeSeconds * (_recipe.Step2NumberOfRinse - 1));
  488. processTimeDic.Add("RinseSecondStep.Recipe_SecondRinseCycleWaitDrainExtraTime", _recipe.DumpTimeSeconds * _recipe.Step2NumberOfRinse);
  489. processTimeDic.Add("RinseSecondStep.Recipe_SecondRinseCycleWaitResistivityStart", _recipe.ResistivityStartTimeSeconds);
  490. processTimeDic.Add("RinseSecondStep.Recipe_SecondRinseCycleResistivityAveraging", _recipe.ResistivityDurationSeconds);
  491. }
  492. else //有第三步rinse
  493. {
  494. processTimeDic.Add("RinseSecondStep.Recipe_SecondRinseCycleWaitEndFillTime", _concurrentFillTimeSeconds * _recipe.Step2NumberOfRinse);
  495. processTimeDic.Add("RinseSecondStep.Recipe_SecondRinseCycleWaitDwell", _recipe.Step2DwellTimeSeconds * _recipe.Step2NumberOfRinse);
  496. processTimeDic.Add("RinseSecondStep.Recipe_SecondRinseCycleWaitDrainExtraTime", _recipe.DumpTimeSeconds * _recipe.Step2NumberOfRinse);
  497. processTimeDic.Add("RinseThirdStep.Recipe_ThirdRinseWaitEndFillTime", _concurrentFillTimeSeconds);
  498. processTimeDic.Add("RinseThirdStep.Recipe_ThirdRinseWaitClampTime", _recipe.FinalRinsePulseClampTime);
  499. processTimeDic.Add("RinseThirdStep.Recipe_ThirdRinseCycleWaitSlowDrainTime", _recipe.FinalRinseSlowDrainTime);
  500. processTimeDic.Add("RinseThirdStep.Recipe_ThirdRinseCycleWaitDrainExtraTime", _recipe.DumpTimeSeconds);
  501. }
  502. totaltime = processTimeDic.Sum(x => x.Value);
  503. return totaltime * cycle;
  504. }
  505. /// <summary>
  506. /// Retry RunRecipe
  507. /// </summary>
  508. /// <param name="param"></param>
  509. /// <returns></returns>
  510. private bool RetryRunRecipe(object[] param)
  511. {
  512. int stepIndex = (int)param[0];
  513. bool result = _cycleManualProcessRoutine.Retry(stepIndex) == RState.Running;
  514. if (result)
  515. {
  516. _isRetry = true;
  517. if (_currentRecipe != null)
  518. {
  519. _recipeTime = CalculateRunRecipeTime(_currentRecipe, _cycle);
  520. }
  521. }
  522. return result;
  523. }
  524. /// <summary>
  525. /// 监控
  526. /// </summary>
  527. /// <param name="param"></param>
  528. /// <returns></returns>
  529. private bool RunRecipeMonitor(object[] param)
  530. {
  531. RState state = _cycleManualProcessRoutine.Monitor();
  532. if (Singleton<RouteManager>.Instance.IsAutoRunning&&_runrecipeElapsedTime!=TimeToReady)
  533. {
  534. _runrecipeElapsedTime =TimeToReady;
  535. LOG.WriteLog(eEvent.INFO_RINSE, Module.ToString(), $"{WaferHolderInfo?.Id} {Module} RunRecipe TimeToReady {_recipeTime-fsm.ElapsedTime/1000}s.");
  536. }
  537. if (state == RState.Failed || state == RState.Timeout)
  538. {
  539. if (Singleton<RouteManager>.Instance.IsAutoRunning)
  540. {
  541. //不存在其他可用的Rinse
  542. if (!CheckOtherRinseAvaible())
  543. {
  544. AlarmList alarmList = new AlarmList(Module.ToString(), ((RinseState)fsm.State).ToString(), (int)RinseMsg.RunRecipe,
  545. _cycleManualProcessRoutine.ErrorMsg, _cycleManualProcessRoutine.ErrorStep, (int)AlarmType.Error);
  546. AlarmListManager.Instance.AddAlarm(alarmList);
  547. }
  548. }
  549. PostMsg(RinseMsg.Error);
  550. _rinseDevice.UpdateStateMachine("Error");
  551. _rinseDevice.UpdateStatus("Error");
  552. _runrecipeElapsedTime = 0;
  553. //记录LotTrack
  554. _runRecipeCompleteTime = DateTime.Now;
  555. _cycleManualProcessRoutine.RinseLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2");
  556. RinseLotTrackUtil.ExportRinseLotTrack(Module.ToString(), _cycleManualProcessRoutine.RinseLotTrackDatas,
  557. _cycleManualProcessRoutine.RinseLotTrackHeaderDatas, IsAuto, _isRetry);
  558. if (WaferHolderInfo != null && _currentRecipe != null)
  559. {
  560. FaModuleNotifier.Instance.NotifyWaferShuttleRecipeFailed(WaferHolderInfo, _currentRecipe.Ppid);
  561. }
  562. return false;
  563. }
  564. _achievedCycle = _cycleManualProcessRoutine.GetAchievedCycle();
  565. bool result = state == RState.End;
  566. if (result)
  567. {
  568. _runrecipeElapsedTime = 0;
  569. if (Singleton<RouteManager>.Instance.IsAutoRunning)
  570. {
  571. AlarmListManager.Instance.CheckModuleAlamAndRemove(Module.ToString(), RinseState.RunReciping.ToString());
  572. }
  573. //记录LotTrack
  574. _runRecipeCompleteTime = DateTime.Now;
  575. int timeLength = (int)(_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds;
  576. _cycleManualProcessRoutine.RinseLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2");
  577. RinseLotTrackUtil.ExportRinseLotTrack(Module.ToString(), _cycleManualProcessRoutine.RinseLotTrackDatas,
  578. _cycleManualProcessRoutine.RinseLotTrackHeaderDatas, IsAuto, _isRetry);
  579. if (WaferHolderInfo != null && _currentRecipe != null)
  580. {
  581. FaModuleNotifier.Instance.NotifyWaferShuttleRecipeEnd(WaferHolderInfo, _currentRecipe.Ppid, timeLength);
  582. }
  583. }
  584. return result;
  585. }
  586. /// <summary>
  587. /// 校验其他rinse是否可用
  588. /// </summary>
  589. /// <returns></returns>
  590. private bool CheckOtherRinseAvaible()
  591. {
  592. ModuleName metalName = WaferHolderInfo.MetalModuleName;
  593. if (metalName!=ModuleName.Unknown)
  594. {
  595. return SchedulerSequenceManager.Instance.GetAvaibleModuleCell(_persistentValue.RecipeOperatingMode,ModuleType.Rinse, metalName)!=ModuleName.Unknown;
  596. }
  597. else
  598. {
  599. return false;
  600. }
  601. }
  602. private bool RunRecipeAbort(object[] param)
  603. {
  604. _cycleManualProcessRoutine.Abort();
  605. _rinseDevice.UpdateStateMachine("Abort");
  606. _rinseDevice.UpdateStatus("Abort");
  607. //记录LotTrack
  608. _runRecipeCompleteTime = DateTime.Now;
  609. _cycleManualProcessRoutine.RinseLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2");
  610. RinseLotTrackUtil.ExportRinseLotTrack(Module.ToString(), _cycleManualProcessRoutine.RinseLotTrackDatas,
  611. _cycleManualProcessRoutine.RinseLotTrackHeaderDatas, IsAuto, _isRetry);
  612. return true;
  613. }
  614. #endregion
  615. #region Keepwet
  616. /// <summary>
  617. /// keepwet
  618. /// </summary>
  619. /// <param name="param"></param>
  620. /// <returns></returns>
  621. private bool Keepwet(object[] param)
  622. {
  623. return _keepwetRoutine.Start(param) == RState.Running;
  624. }
  625. /// <summary>
  626. /// 停止Keepwet
  627. /// </summary>
  628. /// <param name="param"></param>
  629. /// <returns></returns>
  630. private bool KeepwetingComplete(object[] param)
  631. {
  632. // _keepwetRoutine.Abort();
  633. return true;
  634. }
  635. /// <summary>
  636. /// keepwet
  637. /// </summary>
  638. /// <param name="param"></param>
  639. /// <returns></returns>
  640. private bool KeepwetMonitor(object[] param)
  641. {
  642. RState ret = _keepwetRoutine.Monitor();
  643. if (ret == RState.End)
  644. {
  645. return true;
  646. }
  647. if (ret == RState.Failed || ret == RState.Timeout)
  648. {
  649. PostMsg(RinseMsg.Error);
  650. }
  651. return false;
  652. }
  653. #endregion
  654. #region RinseRetry
  655. /// <summary>
  656. /// Retry
  657. /// </summary>
  658. /// <param name="param"></param>
  659. /// <returns></returns>
  660. private bool RinseRetry(object[] param)
  661. {
  662. AlarmList alarmList = AlarmListManager.Instance.GetAlarmListByModule(Module.ToString());
  663. if (alarmList != null)
  664. {
  665. CheckToPostMessage<RinseState, RinseMsg>(eEvent.WARN_RINSE, Module.ToString(), alarmList.ModuleCmd,
  666. alarmList.ModuleStep);
  667. }
  668. return false;
  669. }
  670. #endregion
  671. public bool Check(int msg, out string reason, params object[] args)
  672. {
  673. reason = "";
  674. return true;
  675. }
  676. public bool CheckAcked(int msg)
  677. {
  678. return true;
  679. }
  680. public int Invoke(string function, params object[] args)
  681. {
  682. switch (function)
  683. {
  684. case "HomeAll":
  685. if (IsIdle)
  686. {
  687. return (int)FSM_MSG.NONE;
  688. }
  689. if (CheckToPostMessage<RinseState, RinseMsg>(eEvent.ERR_RINSE, Module.ToString(), (int)RinseMsg.Initialize))
  690. {
  691. return (int)RinseMsg.Initialize;
  692. }
  693. else
  694. {
  695. return (int)FSM_MSG.NONE;
  696. }
  697. case "Retry":
  698. if (CheckToPostMessage<RinseState, RinseMsg>(eEvent.ERR_RINSE, Module.ToString(), (int)RinseMsg.Retry))
  699. {
  700. return (int)RinseMsg.Retry;
  701. }
  702. else
  703. {
  704. return (int)FSM_MSG.NONE;
  705. }
  706. }
  707. return (int)FSM_MSG.NONE;
  708. }
  709. }
  710. public enum RinseMsg
  711. {
  712. Error,
  713. Initialize,
  714. ResumeError,
  715. CycleProcessRecipe,
  716. RunRecipe,
  717. Abort,
  718. Keepwet,
  719. RecipeComplete,
  720. Init,
  721. Retry
  722. }
  723. }