PlatingCellRunRecipeRoutine.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. using Aitex.Core.RT.Device;
  2. using Aitex.Core.RT.Log;
  3. using Aitex.Core.RT.Routine;
  4. using Aitex.Core.Util;
  5. using MECF.Framework.Common.Beckhoff.AxisProvider;
  6. using MECF.Framework.Common.Beckhoff.Station;
  7. using MECF.Framework.Common.CommonData.PowerSupplier;
  8. using MECF.Framework.Common.RecipeCenter;
  9. using MECF.Framework.Common.Routine;
  10. using MECF.Framework.Common.SubstrateTrackings;
  11. using MECF.Framework.Common.ToolLayout;
  12. using MECF.Framework.Common.Utilities;
  13. using PunkHPX8_Core;
  14. using PunkHPX8_RT.Devices.AXIS;
  15. using PunkHPX8_RT.Devices.Facilities;
  16. using PunkHPX8_RT.Devices.PlatingCell;
  17. using PunkHPX8_RT.Devices.PowerSupplier;
  18. using PunkHPX8_RT.Modules.Reservoir;
  19. using SecsGem.Core.ItemModel;
  20. using System;
  21. using System.Collections.Generic;
  22. using System.Diagnostics;
  23. using System.Linq;
  24. using System.Text;
  25. using System.Threading.Tasks;
  26. using System.Windows.Navigation;
  27. using static Mono.Security.X509.X520;
  28. namespace PunkHPX8_RT.Modules.PlatingCell
  29. {
  30. public class PlatingCellRunRecipeRoutine : RoutineBase, IRoutine
  31. {
  32. private enum RunRecipeStep
  33. {
  34. WaitMatchPlatingCellStart,
  35. LoopStart,
  36. InterRinse,
  37. CheckInterRinse,
  38. Entry,
  39. CheckEntry,
  40. Deposition,
  41. CheckDeposition,
  42. Reclaim,
  43. CheckReclaim,
  44. Rinse,
  45. CheckRinse,
  46. Dry,
  47. CheckDry,
  48. LoopEnd,
  49. End
  50. }
  51. #region 常量
  52. private const int ALL_DAY_MILLOSECONDS = 24 * 60 * 60 * 1000;
  53. /// <summary>
  54. /// ROTATION电机转速比例
  55. /// </summary>
  56. private const int SPEED_RATIO = 1;
  57. /// <summary>
  58. /// 电机以500rmp 运行12个小时的位置
  59. /// </summary>
  60. private const int LARGETARGETPOSITION = 12 * 60 * 60 * 500 * 6;
  61. #endregion
  62. #region 内部变量
  63. /// <summary>
  64. /// recipe
  65. /// </summary>
  66. private DepRecipe _recipe;
  67. /// <summary>
  68. /// Platingcell device
  69. /// </summary>
  70. private PlatingCellDevice _device;
  71. /// <summary>
  72. /// Rotation axis
  73. /// </summary>
  74. private JetAxisBase _rotationAxis;
  75. /// <summary>
  76. ///rotation Provider对象
  77. /// </summary>
  78. private BeckhoffProviderAxis _rotationProviderAxis;
  79. ///是否选中dummy load
  80. /// </summary>
  81. private bool _isDummyLoad;
  82. /// cycle次数
  83. /// </summary>
  84. private int _cycle;
  85. /// <summary>
  86. /// 当前完成的Cycle次数
  87. /// </summary>
  88. private int _currentCycle;
  89. /// <summary>
  90. /// platingcell entity
  91. /// </summary>
  92. private PlatingCellEntity _platingCellEntity;
  93. /// <summary>
  94. /// 另一边的platingcell entity
  95. /// </summary>
  96. private PlatingCellEntity _matchPlatingCellEntity;
  97. /// <summary>
  98. /// 对应reservoir entity
  99. /// </summary>
  100. private ReservoirEntity _reservoirEntity;
  101. /// <summary>
  102. /// vertical axis entity
  103. /// </summary>
  104. private PlatingCellVerticalEntity _verticalEntity;
  105. /// <summary>
  106. /// vertical 轴的位置数据
  107. /// </summary>
  108. private BeckhoffStationAxis _verticalBeckhoffStation;
  109. /// <summary>
  110. /// recipe中是否存在电机反转
  111. /// </summary>
  112. private bool _isRecipeContainsRevserseRotation = false;
  113. /// <summary>
  114. /// run recipe 过程中电机会停的位置(需要根据recipe计算出来)
  115. /// </summary>
  116. #region 电镀通电相关
  117. /// <summary>
  118. /// 不通电
  119. /// </summary>
  120. private bool _isZeroCurrent = false;
  121. /// <summary>
  122. /// Power step集合
  123. /// </summary>
  124. List<PowerSupplierStepPeriodData> _powerSupplierStepPeriodDatas = new List<PowerSupplierStepPeriodData>();
  125. /// <summary>
  126. /// 记录dep recipe中出现的最大电流,用于启动电源前切换挡位
  127. /// </summary>
  128. private double _maxCurrent = 0;
  129. /// <summary>
  130. /// 通电总时长
  131. /// </summary>
  132. private int _totalMicrosecond = 0;
  133. /// <summary>
  134. /// Plating启动时间
  135. /// </summary>
  136. private DateTime _platingStartTime;
  137. #endregion
  138. #region routine
  139. /// <summary>
  140. /// interbal rinse routien
  141. /// </summary>
  142. private PlatingCellInterRinseRoutine _interRinseRoutine;
  143. /// <summary>
  144. /// entry routien
  145. /// </summary>
  146. private PlatingCellEntryRoutine _entryRoutine;
  147. /// <summary>
  148. /// entry routien
  149. /// </summary>
  150. private PlatingCellDepositionRoutine _depositionRoutine;
  151. /// <summary>
  152. /// reclaim routien
  153. /// </summary>
  154. private PlatingCellReclaimRoutine _reclaimRoutine;
  155. /// <summary>
  156. /// Rinse routien
  157. /// </summary>
  158. private PlatingCellRinseRoutine _rinseRoutine;
  159. /// <summary>
  160. /// Dry routien
  161. /// </summary>
  162. private PlatingCellDryRoutine _dryRoutine;
  163. #endregion
  164. #region 属性
  165. #endregion
  166. #endregion
  167. /// <summary>
  168. /// 构造函数
  169. /// </summary>
  170. /// <param name="module"></param>
  171. public PlatingCellRunRecipeRoutine(string module) : base(module)
  172. {
  173. _interRinseRoutine = new PlatingCellInterRinseRoutine(module);
  174. _entryRoutine = new PlatingCellEntryRoutine(module);
  175. _depositionRoutine = new PlatingCellDepositionRoutine(module);
  176. _reclaimRoutine = new PlatingCellReclaimRoutine(module);
  177. _rinseRoutine = new PlatingCellRinseRoutine(module);
  178. _dryRoutine = new PlatingCellDryRoutine(module);
  179. }
  180. /// <summary>
  181. /// 中止
  182. /// </summary>
  183. public void Abort()
  184. {
  185. Runner.Stop("Manual Abort");
  186. }
  187. /// <summary>
  188. /// 监控
  189. /// </summary>
  190. /// <returns></returns>
  191. public RState Monitor()
  192. {
  193. Runner.WaitWithStopCondition(RunRecipeStep.WaitMatchPlatingCellStart,() => { return _matchPlatingCellEntity.IsInRecipe; },() => { return false; }, false,ALL_DAY_MILLOSECONDS)
  194. .LoopStart(RunRecipeStep.LoopStart, "Loop Start Cycle Run Platingcell Recipe Routine", _cycle, NullFun, _delay_1ms)
  195. //interval rinse
  196. .LoopRunIf(RunRecipeStep.InterRinse, _recipe.RinseBeforeEntryEnable, () => { return _interRinseRoutine.Start(_recipe, LARGETARGETPOSITION) == RState.Running; })
  197. .LoopRunIfWithStopStatus(RunRecipeStep.CheckInterRinse, _recipe.RinseBeforeEntryEnable, CheckInterRinseEndStatus,
  198. () => CommonFunction.CheckRoutineStopState(_interRinseRoutine))
  199. //entry
  200. .LoopRun(RunRecipeStep.Entry, () => { return _entryRoutine.Start(_recipe, LARGETARGETPOSITION, _powerSupplierStepPeriodDatas) == RState.Running; })
  201. .LoopRunWithStopStatus(RunRecipeStep.CheckEntry, CheckEntryEndStatus, () => CommonFunction.CheckRoutineStopState(_entryRoutine))
  202. //Deposition
  203. .LoopRun(RunRecipeStep.Deposition, () => { return _depositionRoutine.Start(_recipe, _isZeroCurrent,_powerSupplierStepPeriodDatas) == RState.Running; })
  204. .LoopRunWithStopStatus(RunRecipeStep.CheckDeposition, CheckDepositionEndStatus,() => CommonFunction.CheckRoutineStopState(_depositionRoutine))
  205. //Reclaim
  206. .LoopRun(RunRecipeStep.Reclaim, () => { return _reclaimRoutine.Start(_recipe, _isZeroCurrent,_device.PowerSupplier) == RState.Running; })
  207. .LoopRunWithStopStatus(RunRecipeStep.CheckReclaim, CheckReclaimEndStatus, () => CommonFunction.CheckRoutineStopState(_reclaimRoutine))
  208. //Rinse
  209. .LoopRun(RunRecipeStep.Rinse, () => { return _rinseRoutine.Start(_recipe) == RState.Running; })
  210. .LoopRunWithStopStatus(RunRecipeStep.CheckRinse, CheckRinseEndStatus,
  211. () => CommonFunction.CheckRoutineStopState(_rinseRoutine))
  212. //Dry
  213. .LoopRun(RunRecipeStep.Dry, () => { return _dryRoutine.Start(_recipe) == RState.Running; })
  214. .LoopRunWithStopStatus(RunRecipeStep.CheckDry, CheckDryEndStatus, () => CommonFunction.CheckRoutineStopState(_dryRoutine))
  215. .LoopEnd(RunRecipeStep.LoopEnd, UpdateCycleCount, _delay_1ms)
  216. .End(RunRecipeStep.End, NullFun);
  217. return Runner.Status;
  218. }
  219. /// 统计完成的Cycle次数
  220. /// </summary>
  221. /// <returns></returns>
  222. private bool UpdateCycleCount()
  223. {
  224. _currentCycle += 1;
  225. return true;
  226. }
  227. /// <summary>
  228. /// 获取当前Cycle次数
  229. /// </summary>
  230. /// <returns></returns>
  231. public int GetCurrentCycle()
  232. {
  233. return _currentCycle;
  234. }
  235. /// <summary>
  236. /// 检查interval rinse是否完成
  237. /// </summary>
  238. /// <returns></returns>
  239. private bool CheckInterRinseEndStatus()
  240. {
  241. bool result = CommonFunction.CheckRoutineEndState(_interRinseRoutine);
  242. SubRoutineStep = _interRinseRoutine.CurrentStep;
  243. return result;
  244. }
  245. /// <summary>
  246. /// 检查entry是否完成
  247. /// </summary>
  248. /// <returns></returns>
  249. private bool CheckEntryEndStatus()
  250. {
  251. bool result = CommonFunction.CheckRoutineEndState(_entryRoutine);
  252. SubRoutineStep = _entryRoutine.CurrentStep;
  253. return result;
  254. }
  255. /// <summary>
  256. /// 检查Deposition是否完成
  257. /// </summary>
  258. /// <returns></returns>
  259. private bool CheckDepositionEndStatus()
  260. {
  261. bool result = CommonFunction.CheckRoutineEndState(_depositionRoutine);
  262. SubRoutineStep = _depositionRoutine.CurrentStep;
  263. return result;
  264. }
  265. /// <summary>
  266. /// 检查Reclaim是否完成
  267. /// </summary>
  268. /// <returns></returns>
  269. private bool CheckReclaimEndStatus()
  270. {
  271. bool result = CommonFunction.CheckRoutineEndState(_reclaimRoutine);
  272. SubRoutineStep = _reclaimRoutine.CurrentStep;
  273. return result;
  274. }
  275. /// <summary>
  276. /// 检查Rinse是否完成
  277. /// </summary>
  278. /// <returns></returns>
  279. private bool CheckRinseEndStatus()
  280. {
  281. bool result = CommonFunction.CheckRoutineEndState(_rinseRoutine);
  282. SubRoutineStep = _rinseRoutine.CurrentStep;
  283. return result;
  284. }
  285. /// <summary>
  286. /// 检查Dry是否完成
  287. /// </summary>
  288. /// <returns></returns>
  289. private bool CheckDryEndStatus()
  290. {
  291. bool result = CommonFunction.CheckRoutineEndState(_dryRoutine);
  292. SubRoutineStep = _dryRoutine.CurrentStep;
  293. return result;
  294. }
  295. /// <summary>
  296. /// 启动
  297. /// </summary>
  298. /// <param name="objs"></param>
  299. /// <returns></returns>
  300. public RState Start(params object[] objs)
  301. {
  302. _recipe = objs[0] as DepRecipe;
  303. if (_recipe == null)
  304. {
  305. LOG.WriteLog(eEvent.ERR_METAL, Module, "recipe is null");
  306. return RState.Failed;
  307. }
  308. if (objs.Length > 1)
  309. {
  310. _isDummyLoad = (bool)objs[1];
  311. }
  312. if (objs.Length > 2)
  313. {
  314. _cycle = (int)objs[2];
  315. }
  316. _device = DEVICE.GetDevice<PlatingCellDevice>(Module);
  317. _rotationAxis = DEVICE.GetDevice<JetAxisBase>($"{Module}.Rotation");
  318. _rotationProviderAxis = BeckhoffAxisProviderManager.Instance.GetAxisProvider($"{Module}.Rotation");
  319. if (_rotationProviderAxis == null)
  320. {
  321. NotifyError(eEvent.ERR_PLATINGCELL, $"{Module}.Rotation Provider is not exist", 0);
  322. return RState.Failed;
  323. }
  324. //获取vertical entity
  325. string vertical = ModuleMatcherManager.Instance.GetPlatingVerticalByCell(Module);
  326. _verticalEntity = Singleton<RouteManager>.Instance.GetModule<PlatingCellVerticalEntity>(vertical);
  327. //获取platingcell eneity
  328. _platingCellEntity = Singleton<RouteManager>.Instance.GetModule<PlatingCellEntity>(Module);
  329. //获取对应reservoir eneity
  330. string reservoir = ReservoirItemManager.Instance.GetReservoirByPlatingCell(Module);
  331. _reservoirEntity = Singleton<RouteManager>.Instance.GetModule<ReservoirEntity>(reservoir);
  332. //获取vertical station信息对象
  333. _verticalBeckhoffStation = BeckhoffStationLocationManager.Instance.GetStationAxis($"{_verticalEntity.Module}", "Vertical");
  334. //获取另一边platingcell的entity
  335. string MatchModule = ModuleMatcherManager.Instance.GetMatcherByModule(Module);
  336. _matchPlatingCellEntity = Singleton<RouteManager>.Instance.GetModule<PlatingCellEntity>(MatchModule);
  337. if (!CheckPreCondition())
  338. {
  339. return RState.Failed;
  340. }
  341. CalculatVerticalPosition(_recipe);
  342. if (!UpdatePowerStepDatas())
  343. {
  344. NotifyError(eEvent.ERR_PLATINGCELL, $"Update Power StepDatas Failed!", 0);
  345. return RState.Failed;
  346. }
  347. _currentCycle = 0;
  348. return Runner.Start(Module, "PlatingCell Run Recipe");
  349. }
  350. /// <summary>
  351. /// 初始化Power step步骤
  352. /// </summary>
  353. private bool UpdatePowerStepDatas()
  354. {
  355. _isZeroCurrent = false;
  356. _isRecipeContainsRevserseRotation = false;
  357. double current = 0;
  358. _totalMicrosecond = 0;
  359. _powerSupplierStepPeriodDatas.Clear();
  360. if (!_recipe.IsEntryTypeCold)//如果entry带上电保护,那么把上电保护的部分加到步阶电流的第一步
  361. {
  362. PowerSupplierStepPeriodData step = new PowerSupplierStepPeriodData(); //上电保护时间(提前上电时间+延迟时间)
  363. step.Hour = 0;
  364. step.Minute = (ushort)((_recipe.PlatingDelay) / 60);
  365. step.Second = (ushort)(_recipe.PlatingDelay % 60);
  366. step.Microsecond = 110; //到达entry位置提前100ms上电,提前一丢丢
  367. step.Voltage = _recipe.DepMaxVoltageWarning;
  368. step.Current = _recipe.EntryCurrent * 0.001; //recipe的entry current单位是毫安
  369. _powerSupplierStepPeriodDatas.Add(step);
  370. }
  371. foreach (var item in _recipe.DepSteps)
  372. {
  373. PowerSupplierStepPeriodData step = new PowerSupplierStepPeriodData();
  374. step.Current = item.CurrentValue;
  375. if(item.CurrentValue > _maxCurrent)
  376. {
  377. _maxCurrent = item.CurrentValue;
  378. }
  379. step.Hour = (ushort)(item.DurartionSeconds / 3600);
  380. step.Minute = (ushort)((item.DurartionSeconds - step.Hour * 3600) / 60);
  381. step.Second = (ushort)(item.DurartionSeconds % 60);
  382. step.Microsecond = 0;
  383. step.Voltage = _recipe.DepMaxVoltageWarning;
  384. _powerSupplierStepPeriodDatas.Add(step);
  385. current += step.Current;
  386. _totalMicrosecond += item.DurartionSeconds * 1000;
  387. }
  388. if (current == 0)
  389. {
  390. _isZeroCurrent = true;
  391. }
  392. if(_maxCurrent < _recipe.EntryCurrent)//最大电流要考虑entry current
  393. {
  394. _maxCurrent = _recipe.EntryCurrent;
  395. }
  396. if(_maxCurrent > 0.6) //设置电源挡位,有超过0.6A的电流则用高档,否则用中挡
  397. {
  398. return _device.PowerSupplier.SetPowerGrade("set power grade high", new object[] { (byte)2 });
  399. }
  400. else
  401. {
  402. return _device.PowerSupplier.SetPowerGrade("set power grade middle", new object[] { (byte)1 });
  403. }
  404. }
  405. /// <summary>
  406. /// 根据dep recipe计算出整个电镀过程中Rotation profile position可能去到的位置
  407. /// </summary>
  408. private void CalculatVerticalPosition(DepRecipe recipe)
  409. {
  410. foreach(var item in recipe.DepSteps)
  411. {
  412. if (item.BiDireaction)
  413. {
  414. _isRecipeContainsRevserseRotation = true;
  415. }
  416. else
  417. {
  418. continue;
  419. }
  420. }
  421. }
  422. /// <summary>
  423. /// 检验前置条件
  424. /// </summary>
  425. /// <returns></returns>
  426. private bool CheckPreCondition()
  427. {
  428. if (_recipe == null)
  429. {
  430. LOG.WriteLog(eEvent.ERR_PLATINGCELL, Module, "Recipe is null");
  431. return false;
  432. }
  433. //if (_recipe.DepSteps.Count == 0)
  434. //{
  435. // LOG.WriteLog(eEvent.ERR_PLATINGCELL, Module, "Recipe DepSteps count is 0");
  436. // return false;
  437. //}
  438. if (!CheckAxisHome())
  439. {
  440. NotifyError(eEvent.ERR_PLATINGCELL, "Check Axis home error",0);
  441. return false;
  442. }
  443. if (!CheckFacility())
  444. {
  445. NotifyError(eEvent.ERR_PLATINGCELL, "Check facility error", 0);
  446. return false;
  447. }
  448. if (!CheckModuleAndReservoir())
  449. {
  450. NotifyError(eEvent.ERR_PLATINGCELL, "Check ModuleAndReservoir error", 0);
  451. return false;
  452. }
  453. return true;
  454. }
  455. private bool CheckModuleAndReservoir()
  456. {
  457. if (!_platingCellEntity.IsIdle)
  458. {
  459. LOG.WriteLog(eEvent.ERR_PLATINGCELL, Module, $"{Module} is not initialized");
  460. return false;
  461. }
  462. if (!_reservoirEntity.IsIdle)
  463. {
  464. LOG.WriteLog(eEvent.ERR_PLATINGCELL, Module, $"Releated reseroivr is not initialized");
  465. return false;
  466. }
  467. if (!_reservoirEntity.TemperatureReached)
  468. {
  469. LOG.WriteLog(eEvent.ERR_PLATINGCELL, Module, $"Releated reseroivr temperature is not reached");
  470. return false;
  471. }
  472. if ("Manual".Equals(_reservoirEntity.PersistentValue.OperatingMode) && !WaferManager.Instance.CheckHasWafer(Module, 0))
  473. {
  474. LOG.WriteLog(eEvent.ERR_PLATINGCELL, Module, $"Run recipe in manual must has wafer!");
  475. return false;
  476. }
  477. return true;
  478. }
  479. /// <summary>
  480. /// 检查马达是否上电且home
  481. /// </summary>
  482. /// <returns></returns>
  483. private bool CheckAxisHome()
  484. {
  485. if (!_rotationAxis.IsSwitchOn)
  486. {
  487. LOG.WriteLog(eEvent.ERR_PLATINGCELL, Module, "Rotation Axis is off");
  488. return false;
  489. }
  490. if (!_rotationAxis.IsHomed)
  491. {
  492. LOG.WriteLog(eEvent.ERR_PLATINGCELL, Module, "Rotation Axis is not home");
  493. return false;
  494. }
  495. if (!_verticalEntity.AxisIsHome)
  496. {
  497. LOG.WriteLog(eEvent.ERR_PLATINGCELL, Module, "Vertical Axis is not home");
  498. return false;
  499. }
  500. return true;
  501. }
  502. /// <summary>
  503. /// 检查facility
  504. /// </summary>
  505. /// <returns></returns>
  506. private bool CheckFacility()
  507. {
  508. SystemFacilities systemFacilities = DEVICE.GetDevice<SystemFacilities>("System.Facilities");
  509. if (systemFacilities == null)
  510. {
  511. LOG.WriteLog(eEvent.ERR_PLATINGCELL, Module, "Facility is null");
  512. return false;
  513. }
  514. if (!systemFacilities.CDAEnable)
  515. {
  516. LOG.WriteLog(eEvent.ERR_PLATINGCELL, Module, "Facility CDA is off");
  517. return false;
  518. }
  519. if (!systemFacilities.N2Enable)
  520. {
  521. LOG.WriteLog(eEvent.ERR_PLATINGCELL, Module, "Facility N2 is off");
  522. return false;
  523. }
  524. if (!systemFacilities.DIFillEnable)
  525. {
  526. LOG.WriteLog(eEvent.ERR_PLATINGCELL, Module, "Facility DIW is off");
  527. return false;
  528. }
  529. if (systemFacilities.FacilitiesDataDic["CDA1Pressure"].IsError || systemFacilities.FacilitiesDataDic["CDA2Pressure"].IsError)
  530. {
  531. LOG.WriteLog(eEvent.ERR_PLATINGCELL, Module, "Facility CDA Data is in error range");
  532. return false;
  533. }
  534. if (systemFacilities.FacilitiesDataDic["Nitrogen1APressure"].IsError ||
  535. systemFacilities.FacilitiesDataDic["Nitrogen1BPressure"].IsError ||
  536. systemFacilities.FacilitiesDataDic["Nitrogen2APressure"].IsError ||
  537. systemFacilities.FacilitiesDataDic["Nitrogen2BPressure"].IsError)
  538. {
  539. LOG.WriteLog(eEvent.ERR_PLATINGCELL, Module, "Facility N2 Data is in error range");
  540. return false;
  541. }
  542. if (systemFacilities.FacilitiesDataDic["DiWaterPressure"].IsError)
  543. {
  544. LOG.WriteLog(eEvent.ERR_PLATINGCELL, Module, "Facility Diw Pressure value is in error range");
  545. return false;
  546. }
  547. return true;
  548. }
  549. }
  550. }