ReservoirRunRecipeRoutine.cs 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125
  1. using Aitex.Core.RT.Device;
  2. using Aitex.Core.RT.Log;
  3. using Aitex.Core.RT.Routine;
  4. using Aitex.Core.RT.SCCore;
  5. using Aitex.Core.Util;
  6. using CyberX8_Core;
  7. using CyberX8_RT.Devices.Facilities;
  8. using CyberX8_RT.Devices.Metal;
  9. using CyberX8_RT.Devices.PowerSupplier;
  10. using CyberX8_RT.Devices.Reservoir;
  11. using CyberX8_RT.Devices.Temperature;
  12. using CyberX8_RT.Modules.Metal;
  13. using CyberX8_RT.Modules;
  14. using MECF.Framework.Common.Alarm;
  15. using MECF.Framework.Common.CommonData;
  16. using MECF.Framework.Common.CommonData.Metal;
  17. using MECF.Framework.Common.CommonData.PowerSupplier;
  18. using MECF.Framework.Common.Persistent.Reservoirs;
  19. using MECF.Framework.Common.RecipeCenter;
  20. using MECF.Framework.Common.Routine;
  21. using MECF.Framework.Common.ToolLayout;
  22. using System;
  23. using System.Collections.Generic;
  24. using System.Diagnostics;
  25. namespace CyberX8_RT.Modules.Metal
  26. {
  27. public class ReservoirRunRecipeRoutine : RoutineBase, IRoutine
  28. {
  29. #region 常量
  30. private const int LOTTRACK_TIME = 1000;
  31. private const string CDA_1_PRESSURE_VALUE = "CDA1Pressure";
  32. private const string CDA_2_PRESSURE_VALUE = "CDA2Pressure";
  33. private const string STRATUS = "Stratus";
  34. #endregion
  35. private enum RecipeStep
  36. {
  37. PlatingDelay,
  38. PlatingDelayCheck,
  39. HotPlating,
  40. WaitPlatingDelay,
  41. RunPowerStep,
  42. RunPowerStepWait,
  43. LoopStart,
  44. LoopCheckRun,
  45. LoopEnd,
  46. StopLinmot,
  47. StopPowerSuppliers,
  48. SwitchToNormal,
  49. WaferHolderUnclampOn,
  50. End
  51. }
  52. #region 常量
  53. private const string SIDE_A = "SideA";
  54. private const string SIDE_B = "SideB";
  55. #endregion
  56. #region 内部变量
  57. /// <summary>
  58. /// recipe
  59. /// </summary>
  60. private DepRecipe _recipe;
  61. /// <summary>
  62. /// Plate Delay时间
  63. /// </summary>
  64. private DateTime _platingDelayTime = DateTime.Now;
  65. /// <summary>
  66. /// 启动步骤时间
  67. /// </summary>
  68. private DateTime _startStepTime = DateTime.Now;
  69. /// <summary>
  70. /// 电量步骤计数
  71. /// </summary>
  72. private Stopwatch _stepWatch = new Stopwatch();
  73. /// <summary>
  74. /// Power 集合
  75. /// </summary>
  76. List<PowerSupplierStepPeriodData> _powerSupplierStepPeriodDatas = new List<PowerSupplierStepPeriodData>();
  77. /// <summary>
  78. /// 单面
  79. /// </summary>
  80. private string _side;
  81. /// <summary>
  82. /// 步骤索引
  83. /// </summary>
  84. private int _stepIndex = 0;
  85. /// <summary>
  86. /// 设备
  87. /// </summary>
  88. private MetalCellDevice _device;
  89. /// <summary>
  90. /// 设备Entity
  91. /// </summary>
  92. private MetalEntity _metalEntity;
  93. /// <summary>
  94. /// A面电量
  95. /// </summary>
  96. private double _anodeAUsage;
  97. /// <summary>
  98. /// B面电量
  99. /// </summary>
  100. private double _anodeBUsage;
  101. /// <summary>
  102. /// 是否启动recipe步骤
  103. /// </summary>
  104. private bool _startRecipeStep = false;
  105. /// <summary>
  106. /// lock track time
  107. /// </summary>
  108. private DateTime _lotTackTime = DateTime.Now;
  109. /// <summary>
  110. /// LotTrack数据
  111. /// </summary>
  112. private List<MetalLotTrackData> _datas = new List<MetalLotTrackData>();
  113. /// <summary>
  114. /// LotTrack文件头数据
  115. /// </summary>
  116. private LotTrackFileHeaderCommonData _header = new LotTrackFileHeaderCommonData();
  117. /// <summary>
  118. /// Facilities
  119. /// </summary>
  120. private SystemFacilities _facilities;
  121. /// <summary>
  122. /// StandardHot Reservoir Device
  123. /// </summary>
  124. private StandardHotReservoirDevice _standardHotReservoirDevice;
  125. /// <summary>
  126. /// StandardHot Metal Device
  127. /// </summary>
  128. private StandardHotMetalDevice _standardHotMetalDevice;
  129. /// <summary>
  130. /// CompactMembran Reservoir Device
  131. /// </summary>
  132. private CompactMembranReservoirDevice _compactMembranReservoirDevice;
  133. /// <summary>
  134. /// CompactMembran Reservoir Metal
  135. /// </summary>
  136. private CompactMembranMetalDevice _compactMembranMetalDevice;
  137. /// <summary>
  138. /// MetalType
  139. /// </summary>
  140. private string _metalType;
  141. /// <summary>
  142. /// TC device
  143. /// </summary>
  144. private TemperatureController _temperatureController;
  145. /// <summary>
  146. /// Persistent value
  147. /// </summary>
  148. private MetalPersistentValue _persistentValue;
  149. /// <summary>
  150. /// PlatingDelay计时
  151. /// </summary>
  152. private DateTime _hotPlatingRunTime;
  153. /// <summary>
  154. /// 是否处于warning状态
  155. /// </summary>
  156. private bool _isVotlageWarningA = false;
  157. private bool _isVotlageWarningB = false;
  158. private bool _isCurrentWarningA = false;
  159. private bool _isCurrentWarningB = false;
  160. #endregion
  161. #region 属性
  162. /// <summary>
  163. /// A面电量
  164. /// </summary>
  165. public double AnodeAUsage { get { return _anodeAUsage; } }
  166. /// <summary>
  167. /// B面电量
  168. /// </summary>
  169. public double AnodeBUsage { get { return _anodeBUsage; } }
  170. /// <summary>
  171. /// LotTrack数据
  172. /// </summary>
  173. public List<MetalLotTrackData> MetalLotTrackDatas { get { return _datas; } }
  174. /// <summary>
  175. /// LotTrack文件头数据
  176. /// </summary>
  177. public LotTrackFileHeaderCommonData MetalLotTrackHeaderDatas { get { return _header; } }
  178. #endregion
  179. /// <summary>
  180. /// 构造函数
  181. /// </summary>
  182. public ReservoirRunRecipeRoutine(string moduleName) : base(moduleName)
  183. {
  184. }
  185. /// <summary>
  186. /// 中止
  187. /// </summary>
  188. public void Abort()
  189. {
  190. if (_device != null)
  191. {
  192. _device.SideAPowerSupplier.DisableOperation("", null);
  193. _device.SideBPowerSupplier.DisableOperation("", null);
  194. _device.SideAPowerSupplier.SwitchPowerRunModel((int)PowerRunModelEnum.Normal);
  195. _device.SideBPowerSupplier.SwitchPowerRunModel((int)PowerRunModelEnum.Normal);
  196. if (_device.IsLinmotMotorOn)
  197. {
  198. _device.StopLinmot();
  199. }
  200. }
  201. Runner.Stop("Manual Abort");
  202. }
  203. /// <summary>
  204. /// 监控
  205. /// </summary>
  206. /// <returns></returns>
  207. public RState Monitor()
  208. {
  209. LottrackRecord();
  210. Runner.Run(RecipeStep.PlatingDelay, PlatingDelay, _delay_1ms)
  211. .WaitWithStopCondition(RecipeStep.PlatingDelayCheck, () => { return _device.CheckLinmotRoutineEnd(); }, () => { return _device.CheckLinmotRoutineError(); })
  212. .RunIf(RecipeStep.HotPlating, _recipe.HotPlatingCurrentOn, HotPlating, _delay_1ms)
  213. .RunIf(RecipeStep.WaitPlatingDelay, !_recipe.HotPlatingCurrentOn, NullFun, WaitPlatingDelay, _recipe.PlatingDelaySeconds * 1000 + 10000)
  214. .RunIf(RecipeStep.RunPowerStep, !_recipe.HotPlatingCurrentOn, StartPowerStep, _delay_1ms)
  215. .WaitWithStopCondition(RecipeStep.RunPowerStepWait, CheckRecipeStepEndStatus, CheckRecipeStepStopStatus, _delay_5s)
  216. .LoopStart(RecipeStep.LoopStart, "Loop update linmot speed", _powerSupplierStepPeriodDatas.Count, NullFun, _delay_1ms)
  217. .LoopRunWithStopStatus(RecipeStep.LoopCheckRun, CheckStepComplete, () => { return false; }, 24 * 60 * 60 * 1000)
  218. .LoopEnd(RecipeStep.LoopEnd, NullFun, _delay_1ms)
  219. .Run(RecipeStep.StopLinmot, StopLinmot, _delay_1ms)
  220. .Run(RecipeStep.StopPowerSuppliers, StopPowerSupplier, _delay_1ms)
  221. .Run(RecipeStep.SwitchToNormal, SwitchToNormal, _delay_1ms)
  222. .End(RecipeStep.End, NullFun, _delay_1ms);
  223. return Runner.Status;
  224. }
  225. /// <summary>
  226. /// 记录Lottrack
  227. /// </summary>
  228. private void LottrackRecord()
  229. {
  230. //记录Lottrack
  231. if (DateTime.Now.Subtract(_lotTackTime).TotalMilliseconds >= LOTTRACK_TIME)
  232. {
  233. AddLotTrackData();
  234. _lotTackTime = DateTime.Now;
  235. }
  236. }
  237. /// <summary>
  238. /// 获取Lot Track数据
  239. /// </summary>
  240. /// <returns></returns>
  241. public void AddLotTrackData()
  242. {
  243. MetalLotTrackData data = new MetalLotTrackData();
  244. if (_metalType == STRATUS)
  245. {
  246. data.Flow = _standardHotMetalDevice.MetalDeviceData.CellFlow;
  247. data.ANLevel = 0;
  248. data.CALevel = _standardHotReservoirDevice.ReservoirData.Level;
  249. data.CAPumpSpeed = 0;
  250. }
  251. else
  252. {
  253. data.Flow = _compactMembranMetalDevice.MetalDeviceData.CellFlow;
  254. data.ANLevel = _compactMembranReservoirDevice.ReservoirData.ANLevel;
  255. data.CALevel = _compactMembranReservoirDevice.ReservoirData.CALevel;
  256. data.CAPumpSpeed = _compactMembranReservoirDevice.ReservoirData.CAPumpSpeed;
  257. }
  258. data.RunTime = 0;
  259. data.ClampCycleEngaged = _recipe.CycleClampsEnable;
  260. data.Temperature = _temperatureController.TemperatureData.ReserviorTemperature;
  261. data.TimeStamp = DateTime.Now;
  262. data.PowerSupplyA = _device.SideAPowerSupplier.Name;
  263. data.PowerSupplyB = _device.SideBPowerSupplier.Name;
  264. data.PosVoltageA = _device.SideAPowerSupplier.PowerSupplierData.Voltage;
  265. data.PosCurrentA = _device.SideAPowerSupplier.PowerSupplierData.Current;
  266. data.PosVoltageB = _device.SideBPowerSupplier.PowerSupplierData.Voltage;
  267. data.PosCurrentB = _device.SideBPowerSupplier.PowerSupplierData.Current;
  268. data.CDA_1_Pressure = _facilities.GetCommonLimitDataByName(CDA_1_PRESSURE_VALUE).Value;
  269. data.CDA_2_Pressure = _facilities.GetCommonLimitDataByName(CDA_2_PRESSURE_VALUE).Value;
  270. int maxStep = _powerSupplierStepPeriodDatas.Count;
  271. if (_stepIndex < maxStep)
  272. {
  273. data.StepNum = _stepIndex + 1;
  274. int length = _powerSupplierStepPeriodDatas[_stepIndex].Hour * 3600 + _powerSupplierStepPeriodDatas[_stepIndex].Minute * 60 +
  275. _powerSupplierStepPeriodDatas[_stepIndex].Second;
  276. data.DurationRef = length;
  277. data.ShearPlateSpeed = _recipe.CurrentRampProfileSteps[_stepIndex].ShearPlateSpeed;
  278. data.CurrentSP = _recipe.CurrentRampProfileSteps[_stepIndex].ForwardAmps;
  279. }
  280. else
  281. {
  282. data.StepNum = maxStep;
  283. int length = _powerSupplierStepPeriodDatas[maxStep - 1].Hour * 3600 + _powerSupplierStepPeriodDatas[maxStep - 1].Minute * 60 +
  284. _powerSupplierStepPeriodDatas[maxStep - 1].Second;
  285. data.DurationRef = length;
  286. data.ShearPlateSpeed = _recipe.CurrentRampProfileSteps[maxStep - 1].ShearPlateSpeed;
  287. data.CurrentSP = _recipe.CurrentRampProfileSteps[maxStep - 1].ForwardAmps;
  288. }
  289. RecipeStep step = (RecipeStep)Runner.CurrentStep;
  290. if (step <= RecipeStep.WaitPlatingDelay)
  291. {
  292. if (!_recipe.HotPlatingCurrentOn)
  293. {
  294. data.RunTime = DateTime.Now.Subtract(_hotPlatingRunTime).TotalSeconds;
  295. data.DurationRef = _recipe.PlatingDelaySeconds;
  296. data.StepNum = 0;
  297. }
  298. else
  299. {
  300. data.RunTime = 0;
  301. data.DurationRef = _recipe.PlatingDelaySeconds;
  302. data.StepNum = 0;
  303. }
  304. }
  305. else
  306. {
  307. if (_recipe.HotPlatingCurrentOn)
  308. {
  309. if (DateTime.Now.Subtract(_hotPlatingRunTime).TotalSeconds <= _recipe.PlatingDelaySeconds)
  310. {
  311. data.RunTime = DateTime.Now.Subtract(_hotPlatingRunTime).TotalSeconds;
  312. data.DurationRef = _recipe.PlatingDelaySeconds;
  313. data.StepNum = 0;
  314. }
  315. else
  316. {
  317. if (data.StepNum == 1) data.DurationRef -= _recipe.PlatingDelaySeconds;
  318. data.RunTime = (data.StepNum == 1) ? (DateTime.Now.Subtract(_startStepTime).TotalSeconds - _recipe.PlatingDelaySeconds) : DateTime.Now.Subtract(_startStepTime).TotalSeconds;
  319. }
  320. }
  321. else
  322. {
  323. data.RunTime = DateTime.Now.Subtract(_startStepTime).TotalSeconds;
  324. }
  325. }
  326. _datas.Add(data);
  327. }
  328. /// <summary>
  329. /// Plate Delay
  330. /// </summary>
  331. /// <returns></returns>
  332. private bool PlatingDelay()
  333. {
  334. double speed = _recipe.CurrentRampProfileSteps[0].ShearPlateSpeed;
  335. bool result = _device.StartCurveMotion((int)speed);
  336. if (result)
  337. {
  338. _platingDelayTime = DateTime.Now;
  339. if (!_recipe.HotPlatingCurrentOn) _hotPlatingRunTime = DateTime.Now;
  340. }
  341. return result;
  342. }
  343. /// <summary>
  344. /// Hot Plating
  345. /// </summary>
  346. /// <returns></returns>
  347. private bool HotPlating()
  348. {
  349. UpdateHotPlatingStepDatas();
  350. return StartPowerStep();
  351. }
  352. /// <summary>
  353. /// 启动PowerSupplier
  354. /// </summary>
  355. /// <returns></returns>
  356. private bool StartPowerStep()
  357. {
  358. if (string.IsNullOrEmpty(_side))
  359. {
  360. bool result = StartPowerStep(_device.SideAPowerSupplier);
  361. if (result)
  362. {
  363. result = StartPowerStep(_device.SideBPowerSupplier);
  364. if (!result)
  365. {
  366. _device.SideAPowerSupplier.DisableOperation("", null);
  367. _device.SideBPowerSupplier.DisableOperation("", null);
  368. return false;
  369. }
  370. else
  371. {
  372. _startStepTime = DateTime.Now;
  373. _hotPlatingRunTime = DateTime.Now;
  374. _stepWatch.Restart();
  375. _startRecipeStep = true;
  376. return true;
  377. }
  378. }
  379. else
  380. {
  381. _device.SideAPowerSupplier.DisableOperation("", null);
  382. return false;
  383. }
  384. }
  385. else
  386. {
  387. CellPowerSupplier cellPowerSupplier = GetSidePowerSupplier();
  388. bool result = StartPowerStep(cellPowerSupplier);
  389. if (!result)
  390. {
  391. cellPowerSupplier.DisableOperation("", null);
  392. _stepWatch.Restart();
  393. return false;
  394. }
  395. _startStepTime = DateTime.Now;
  396. _hotPlatingRunTime = DateTime.Now;
  397. _startRecipeStep = true;
  398. return true;
  399. }
  400. }
  401. /// <summary>
  402. /// 检验Powerstep是否启动完成
  403. /// </summary>
  404. /// <returns></returns>
  405. private bool CheckRecipeStepEndStatus()
  406. {
  407. if (_startRecipeStep)
  408. {
  409. if (string.IsNullOrEmpty(_side))
  410. {
  411. bool resultA = _device.SideAPowerSupplier.Status == RState.End;
  412. bool resultB = _device.SideBPowerSupplier.Status == RState.End;
  413. return resultA && resultB;
  414. }
  415. else
  416. {
  417. CellPowerSupplier cellPowerSupplier = GetSidePowerSupplier();
  418. return cellPowerSupplier.Status == RState.End;
  419. }
  420. }
  421. return true;
  422. }
  423. /// <summary>
  424. /// 检验Powerstep是否启动完成
  425. /// </summary>
  426. /// <returns></returns>
  427. private bool CheckRecipeStepStopStatus()
  428. {
  429. if (_startRecipeStep)
  430. {
  431. if (string.IsNullOrEmpty(_side))
  432. {
  433. bool resultA = _device.SideAPowerSupplier.Status == RState.Failed || _device.SideAPowerSupplier.Status == RState.Timeout;
  434. bool resultB = _device.SideBPowerSupplier.Status == RState.Failed || _device.SideBPowerSupplier.Status == RState.Timeout;
  435. return resultA && resultB;
  436. }
  437. else
  438. {
  439. CellPowerSupplier cellPowerSupplier = GetSidePowerSupplier();
  440. return cellPowerSupplier.Status == RState.Failed || cellPowerSupplier.Status == RState.Timeout;
  441. }
  442. }
  443. return false;
  444. }
  445. /// <summary>
  446. /// 获取单面PowerSupplier
  447. /// </summary>
  448. /// <returns></returns>
  449. private CellPowerSupplier GetSidePowerSupplier()
  450. {
  451. if (_side == SIDE_A)
  452. {
  453. return _device.SideAPowerSupplier;
  454. }
  455. else
  456. {
  457. return _device.SideBPowerSupplier;
  458. }
  459. }
  460. /// <summary>
  461. /// 启动
  462. /// </summary>
  463. /// <returns></returns>
  464. private bool StartPowerStep(CellPowerSupplier cellPowerSupplier)
  465. {
  466. bool result = cellPowerSupplier.StartSetStepPeriodNoWaitEnd(_powerSupplierStepPeriodDatas);
  467. if (!result)
  468. {
  469. cellPowerSupplier.DisableOperation("", null);
  470. return false;
  471. }
  472. return true;
  473. }
  474. /// <summary>
  475. /// 更新HotPlating step数据
  476. /// </summary>
  477. private void UpdateHotPlatingStepDatas()
  478. {
  479. ushort second = _powerSupplierStepPeriodDatas[0].Second;
  480. ushort minute = _powerSupplierStepPeriodDatas[0].Minute;
  481. ushort hour = _powerSupplierStepPeriodDatas[0].Hour;
  482. if (second + _recipe.PlatingDelaySeconds >= 60)
  483. {
  484. if (minute + 1 < 60)
  485. {
  486. _powerSupplierStepPeriodDatas[0].Minute = (ushort)(minute + 1);
  487. }
  488. else
  489. {
  490. _powerSupplierStepPeriodDatas[0].Minute = 0;
  491. _powerSupplierStepPeriodDatas[0].Hour = (ushort)(hour + 1);
  492. }
  493. _powerSupplierStepPeriodDatas[0].Second = (ushort)(second + _recipe.PlatingDelaySeconds - 60);
  494. }
  495. else
  496. {
  497. _powerSupplierStepPeriodDatas[0].Second = (ushort)(second + _recipe.PlatingDelaySeconds);
  498. }
  499. }
  500. /// <summary>
  501. /// 更新Power step步骤
  502. /// </summary>
  503. private void UpdatePowerStepDatas()
  504. {
  505. _powerSupplierStepPeriodDatas.Clear();
  506. foreach (var item in _recipe.CurrentRampProfileSteps)
  507. {
  508. PowerSupplierStepPeriodData step = new PowerSupplierStepPeriodData();
  509. step.Current = item.ForwardAmps;
  510. step.Hour = (ushort)(item.CurrentRampDurartionSeconds / 3600);
  511. step.Minute = (ushort)((item.CurrentRampDurartionSeconds - step.Hour * 3600) / 60);
  512. step.Second = (ushort)(item.CurrentRampDurartionSeconds % 60);
  513. step.Microsecond = 0;
  514. step.Voltage = _recipe.VoltageWarningLevel;
  515. _powerSupplierStepPeriodDatas.Add(step);
  516. }
  517. }
  518. /// <summary>
  519. /// 等待Plating Delay结束
  520. /// </summary>
  521. /// <returns></returns>
  522. private bool WaitPlatingDelay()
  523. {
  524. if (DateTime.Now.Subtract(_platingDelayTime).TotalSeconds >= _recipe.PlatingDelaySeconds)
  525. {
  526. return true;
  527. }
  528. return false;
  529. }
  530. /// <summary>
  531. /// 检验步骤是否完成
  532. /// </summary>
  533. /// <returns></returns>
  534. private bool CheckStepComplete()
  535. {
  536. if (_stepIndex >= _powerSupplierStepPeriodDatas.Count)
  537. {
  538. _stepWatch.Stop();
  539. LOG.WriteLog(eEvent.INFO_METAL, Module, $"step {_stepIndex} is over step count {_powerSupplierStepPeriodDatas.Count}");
  540. return true;
  541. }
  542. int firstDelay = 2000;
  543. if (_stepIndex == 0)
  544. {
  545. firstDelay = SC.GetValue<int>("Metal.CurrentCheckDelay") * 1000;
  546. }
  547. if (DateTime.Now.Subtract(_startStepTime).TotalMilliseconds >= firstDelay)
  548. {
  549. bool abnormal = CheckMetalDisable();
  550. if (abnormal)
  551. {
  552. return false;
  553. }
  554. }
  555. int length = _powerSupplierStepPeriodDatas[_stepIndex].Hour * 3600 + _powerSupplierStepPeriodDatas[_stepIndex].Minute * 60 +
  556. _powerSupplierStepPeriodDatas[_stepIndex].Second;
  557. if (DateTime.Now.Subtract(_startStepTime).TotalSeconds >= length)
  558. {
  559. _stepIndex++;
  560. if (_stepIndex >= _powerSupplierStepPeriodDatas.Count)
  561. {
  562. _stepWatch.Stop();
  563. LOG.WriteLog(eEvent.INFO_METAL, Module, $"step {_stepIndex} is over step count {_powerSupplierStepPeriodDatas.Count}");
  564. return true;
  565. }
  566. bool result = _device.ChangeCurveSpeedMotion((int)_recipe.CurrentRampProfileSteps[_stepIndex].ShearPlateSpeed);
  567. if (result)
  568. {
  569. LOG.WriteLog(eEvent.INFO_METAL, Module, $"step {_stepIndex} complete");
  570. _startStepTime = DateTime.Now;
  571. }
  572. return result;
  573. }
  574. double second = (double)_stepWatch.ElapsedMilliseconds / 1000;
  575. if (string.IsNullOrEmpty(_side))
  576. {
  577. _anodeAUsage += _device.SideAPowerSupplier.PowerSupplierData.Current * second / 3600;
  578. _anodeBUsage += _device.SideBPowerSupplier.PowerSupplierData.Current * second / 3600;
  579. }
  580. else if (_side == SIDE_A)
  581. {
  582. _anodeAUsage += _device.SideAPowerSupplier.PowerSupplierData.Current * second / 3600;
  583. }
  584. else
  585. {
  586. _anodeBUsage += _device.SideBPowerSupplier.PowerSupplierData.Current * second / 3600;
  587. }
  588. _stepWatch.Restart();
  589. return false;
  590. }
  591. /// <summary>
  592. /// 检验Power是否Disable
  593. /// </summary>
  594. /// <returns></returns>
  595. private bool CheckMetalDisable()
  596. {
  597. if (string.IsNullOrEmpty(_side))
  598. {
  599. if (!_device.SideAPowerSupplier.PowerSupplierData.Enabled)
  600. {
  601. LOG.WriteLog(eEvent.ERR_METAL, Module, "PowerA disable");
  602. Abort();
  603. return true;
  604. }
  605. if (!_device.SideBPowerSupplier.PowerSupplierData.Enabled)
  606. {
  607. LOG.WriteLog(eEvent.ERR_METAL, Module, "PowerB disable");
  608. Abort();
  609. return true;
  610. }
  611. }
  612. else
  613. {
  614. if (_side == SIDE_A && !_device.SideAPowerSupplier.PowerSupplierData.Enabled)
  615. {
  616. LOG.WriteLog(eEvent.ERR_METAL, Module, "PowerA disable");
  617. Abort();
  618. return true;
  619. }
  620. if (_side == SIDE_B && !_device.SideBPowerSupplier.PowerSupplierData.Enabled)
  621. {
  622. LOG.WriteLog(eEvent.ERR_METAL, Module, "PowerB disable");
  623. Abort();
  624. return true;
  625. }
  626. }
  627. if (!_device.IsLinmotMotorOn)
  628. {
  629. LOG.WriteLog(eEvent.ERR_METAL, Module, "Linmot is not motor on");
  630. Abort();
  631. return true;
  632. }
  633. //CheckVotlageAndCurrent();
  634. if (!CheckVoltageAndCurrentValid())
  635. {
  636. Abort();
  637. return true;
  638. }
  639. return false;
  640. }
  641. /// <summary>
  642. /// 检验电压电流的合理性
  643. /// </summary>
  644. /// <returns></returns>
  645. private bool CheckVoltageAndCurrentValid()
  646. {
  647. double sideACurrent = _device.SideAPowerSupplier.PowerSupplierData.Current;
  648. double sideAVoltage = _device.SideAPowerSupplier.PowerSupplierData.Voltage;
  649. double sideBCurrent = _device.SideBPowerSupplier.PowerSupplierData.Current;
  650. double sideBVoltage = _device.SideBPowerSupplier.PowerSupplierData.Voltage;
  651. if (string.IsNullOrEmpty(_side))
  652. {
  653. bool sideAValid = CheckSidePowerInvalid(sideACurrent, sideAVoltage, SIDE_A);
  654. if (sideAValid)
  655. {
  656. return false;
  657. }
  658. bool sideBValid = CheckSidePowerInvalid(sideBCurrent, sideBVoltage, SIDE_B);
  659. if (sideBValid)
  660. {
  661. return false;
  662. }
  663. }
  664. else
  665. {
  666. if (_side == SIDE_A)
  667. {
  668. bool sideAValid = CheckSidePowerInvalid(sideACurrent, sideAVoltage, SIDE_A);
  669. if (sideAValid)
  670. {
  671. return false;
  672. }
  673. }
  674. else
  675. {
  676. bool sideBValid = CheckSidePowerInvalid(sideBCurrent, sideBVoltage, SIDE_B);
  677. if (sideBValid)
  678. {
  679. return false;
  680. }
  681. }
  682. }
  683. return true;
  684. }
  685. /// <summary>
  686. /// 监控电流和电压
  687. /// </summary>
  688. private void CheckVotlageAndCurrent()
  689. {
  690. if (string.IsNullOrEmpty(_side))
  691. {
  692. //监控电压A面
  693. MetalEntity metalEntity = Singleton<RouteManager>.Instance.GetModule<MetalEntity>(Module);
  694. if (_device.SideAPowerSupplier.PowerSupplierData.Voltage > _recipe.VoltageWarningLevel && _device.SideAPowerSupplier.PowerSupplierData.Voltage < _recipe.VolatageLimitMax && !_isVotlageWarningA)
  695. {
  696. _isVotlageWarningA = true;
  697. LOG.WriteLog(eEvent.WARN_METAL, Module, $"Current SideA Votlage {_device.SideAPowerSupplier.PowerSupplierData.Voltage} is large than recipe VolatageWarningLevel {_recipe.VoltageWarningLevel}");
  698. }
  699. if (_device.SideAPowerSupplier.PowerSupplierData.Voltage < _recipe.VolatageLimitMin)
  700. {
  701. if (metalEntity != null)
  702. {
  703. metalEntity.PostMsg(MetalMsg.Error);
  704. }
  705. Abort();
  706. LOG.WriteLog(eEvent.ERR_METAL, Module, $"Current SideA Votlage {_device.SideAPowerSupplier.PowerSupplierData.Voltage} is lower than recipe VolatageLimitMin {_recipe.VolatageLimitMin}");
  707. }
  708. if (_device.SideAPowerSupplier.PowerSupplierData.Voltage > _recipe.VolatageLimitMax)
  709. {
  710. if (metalEntity != null)
  711. {
  712. metalEntity.PostMsg(MetalMsg.Error);
  713. }
  714. Abort();
  715. LOG.WriteLog(eEvent.ERR_METAL, Module, $"Current SideA Votlage {_device.SideAPowerSupplier.PowerSupplierData.Voltage} is large than recipe VolatageLimitMin {_recipe.VolatageLimitMax}");
  716. }
  717. //监控电流A面
  718. double currentWarningFault = _powerSupplierStepPeriodDatas[_stepIndex].Current * _recipe.CurrentWarningLevel * 0.01;
  719. double currentErrorFault = _powerSupplierStepPeriodDatas[_stepIndex].Current * _recipe.FaultPercent * 0.01;
  720. if (_device.SideAPowerSupplier.PowerSupplierData.Current > _powerSupplierStepPeriodDatas[_stepIndex].Current + currentErrorFault
  721. || _device.SideAPowerSupplier.PowerSupplierData.Current < _powerSupplierStepPeriodDatas[_stepIndex].Current - currentErrorFault)
  722. {
  723. if (metalEntity != null)
  724. {
  725. metalEntity.PostMsg(MetalMsg.Error);
  726. }
  727. Abort();
  728. LOG.WriteLog(eEvent.ERR_METAL, Module, $"Current SideA Current {_device.SideAPowerSupplier.PowerSupplierData.Current} is not in " +
  729. $"recipe Range {_powerSupplierStepPeriodDatas[_stepIndex].Current - currentErrorFault} ~ {_powerSupplierStepPeriodDatas[_stepIndex].Current + currentErrorFault}");
  730. }
  731. if (!_isCurrentWarningA && ((_device.SideAPowerSupplier.PowerSupplierData.Current > _powerSupplierStepPeriodDatas[_stepIndex].Current + currentWarningFault && _device.SideAPowerSupplier.PowerSupplierData.Current < _powerSupplierStepPeriodDatas[_stepIndex].Current + currentErrorFault)
  732. || (_device.SideAPowerSupplier.PowerSupplierData.Current < _powerSupplierStepPeriodDatas[_stepIndex].Current - currentWarningFault && _device.SideAPowerSupplier.PowerSupplierData.Current > _powerSupplierStepPeriodDatas[_stepIndex].Current - currentErrorFault)))
  733. {
  734. _isCurrentWarningA = true;
  735. LOG.WriteLog(eEvent.WARN_METAL, Module, $"Current SideA Current {_device.SideAPowerSupplier.PowerSupplierData.Current} is not in " +
  736. $"recipe Range {_powerSupplierStepPeriodDatas[_stepIndex].Current - currentWarningFault} ~ {_powerSupplierStepPeriodDatas[_stepIndex].Current + currentWarningFault}");
  737. }
  738. //监控电压B面
  739. if (_device.SideBPowerSupplier.PowerSupplierData.Voltage > _recipe.VoltageWarningLevel && _device.SideBPowerSupplier.PowerSupplierData.Voltage < _recipe.VolatageLimitMax && !_isVotlageWarningB)
  740. {
  741. _isVotlageWarningB = true;
  742. LOG.WriteLog(eEvent.WARN_METAL, Module, $"Current SideB Votlage {_device.SideBPowerSupplier.PowerSupplierData.Voltage} is large than recipe VolatageWarningLevel {_recipe.VoltageWarningLevel}");
  743. }
  744. if (_device.SideBPowerSupplier.PowerSupplierData.Voltage < _recipe.VolatageLimitMin)
  745. {
  746. if (metalEntity != null)
  747. {
  748. metalEntity.PostMsg(MetalMsg.Error);
  749. }
  750. Abort();
  751. LOG.WriteLog(eEvent.ERR_METAL, Module, $"Current SideB Votlage {_device.SideBPowerSupplier.PowerSupplierData.Voltage} is lower than recipe VolatageLimitMin {_recipe.VolatageLimitMin}");
  752. }
  753. if (_device.SideBPowerSupplier.PowerSupplierData.Voltage > _recipe.VolatageLimitMax)
  754. {
  755. if (metalEntity != null)
  756. {
  757. metalEntity.PostMsg(MetalMsg.Error);
  758. }
  759. Abort();
  760. LOG.WriteLog(eEvent.ERR_METAL, Module, $"Current SideB Votlage {_device.SideBPowerSupplier.PowerSupplierData.Voltage} is large than recipe VolatageLimitMin{_recipe.VolatageLimitMax}");
  761. }
  762. //监控电流B面
  763. if (_device.SideBPowerSupplier.PowerSupplierData.Current > _powerSupplierStepPeriodDatas[_stepIndex].Current + currentErrorFault
  764. || _device.SideBPowerSupplier.PowerSupplierData.Current < _powerSupplierStepPeriodDatas[_stepIndex].Current - currentErrorFault)
  765. {
  766. if (metalEntity != null)
  767. {
  768. metalEntity.PostMsg(MetalMsg.Error);
  769. }
  770. Abort();
  771. LOG.WriteLog(eEvent.ERR_METAL, Module, $"Current SideB Current {_device.SideBPowerSupplier.PowerSupplierData.Current} is not in " +
  772. $"recipe Range {_powerSupplierStepPeriodDatas[_stepIndex].Current - currentErrorFault} ~ {_powerSupplierStepPeriodDatas[_stepIndex].Current + currentErrorFault}");
  773. }
  774. if (!_isCurrentWarningB && ((_device.SideBPowerSupplier.PowerSupplierData.Current > _powerSupplierStepPeriodDatas[_stepIndex].Current + currentWarningFault && _device.SideBPowerSupplier.PowerSupplierData.Current < _powerSupplierStepPeriodDatas[_stepIndex].Current + currentErrorFault)
  775. || (_device.SideBPowerSupplier.PowerSupplierData.Current < _powerSupplierStepPeriodDatas[_stepIndex].Current - currentWarningFault && _device.SideBPowerSupplier.PowerSupplierData.Current > _powerSupplierStepPeriodDatas[_stepIndex].Current - currentErrorFault)))
  776. {
  777. _isCurrentWarningB = true;
  778. LOG.WriteLog(eEvent.WARN_METAL, Module, $"Current SideB Current {_device.SideBPowerSupplier.PowerSupplierData.Current} is not in " +
  779. $"recipe Range {_powerSupplierStepPeriodDatas[_stepIndex].Current - currentWarningFault} ~ {_powerSupplierStepPeriodDatas[_stepIndex].Current + currentWarningFault}");
  780. }
  781. }
  782. else
  783. {
  784. if (_side == SIDE_A)
  785. {
  786. //监控电压A面
  787. MetalEntity metalEntity = Singleton<RouteManager>.Instance.GetModule<MetalEntity>(Module);
  788. if (_device.SideAPowerSupplier.PowerSupplierData.Voltage > _recipe.VoltageWarningLevel && _device.SideAPowerSupplier.PowerSupplierData.Voltage < _recipe.VolatageLimitMax && !_isVotlageWarningA)
  789. {
  790. _isVotlageWarningA = true;
  791. LOG.WriteLog(eEvent.WARN_METAL, Module, $"Current SideA Votlage {_device.SideAPowerSupplier.PowerSupplierData.Voltage} is large than recipe VolatageWarningLevel {_recipe.VoltageWarningLevel}");
  792. }
  793. if (_device.SideAPowerSupplier.PowerSupplierData.Voltage < _recipe.VolatageLimitMin)
  794. {
  795. if (metalEntity != null)
  796. {
  797. metalEntity.PostMsg(MetalMsg.Error);
  798. }
  799. Abort();
  800. LOG.WriteLog(eEvent.ERR_METAL, Module, $"Current SideA Votlage {_device.SideAPowerSupplier.PowerSupplierData.Voltage} is lower than recipe VolatageLimitMin {_recipe.VolatageLimitMin}");
  801. }
  802. if (_device.SideAPowerSupplier.PowerSupplierData.Voltage > _recipe.VolatageLimitMax)
  803. {
  804. if (metalEntity != null)
  805. {
  806. metalEntity.PostMsg(MetalMsg.Error);
  807. }
  808. Abort();
  809. LOG.WriteLog(eEvent.ERR_METAL, Module, $"Current SideA Votlage {_device.SideAPowerSupplier.PowerSupplierData.Voltage} is large than recipe VolatageLimitMin {_recipe.VolatageLimitMax}");
  810. }
  811. //监控电流A面
  812. double currentWarningFault = _powerSupplierStepPeriodDatas[_stepIndex].Current * _recipe.CurrentWarningLevel * 0.01;
  813. double currentErrorFault = _powerSupplierStepPeriodDatas[_stepIndex].Current * _recipe.FaultPercent * 0.01;
  814. if (_device.SideAPowerSupplier.PowerSupplierData.Current > _powerSupplierStepPeriodDatas[_stepIndex].Current + currentErrorFault
  815. || _device.SideAPowerSupplier.PowerSupplierData.Current < _powerSupplierStepPeriodDatas[_stepIndex].Current - currentErrorFault)
  816. {
  817. if (metalEntity != null)
  818. {
  819. metalEntity.PostMsg(MetalMsg.Error);
  820. }
  821. Abort();
  822. LOG.WriteLog(eEvent.ERR_METAL, Module, $"Current SideA Current {_device.SideAPowerSupplier.PowerSupplierData.Current} is not in " +
  823. $"recipe Range {_powerSupplierStepPeriodDatas[_stepIndex].Current - currentErrorFault} ~ {_powerSupplierStepPeriodDatas[_stepIndex].Current + currentErrorFault}");
  824. }
  825. if (!_isCurrentWarningA && ((_device.SideAPowerSupplier.PowerSupplierData.Current > _powerSupplierStepPeriodDatas[_stepIndex].Current + currentWarningFault && _device.SideAPowerSupplier.PowerSupplierData.Current < _powerSupplierStepPeriodDatas[_stepIndex].Current + currentErrorFault)
  826. || (_device.SideAPowerSupplier.PowerSupplierData.Current < _powerSupplierStepPeriodDatas[_stepIndex].Current - currentWarningFault && _device.SideAPowerSupplier.PowerSupplierData.Current > _powerSupplierStepPeriodDatas[_stepIndex].Current - currentErrorFault)))
  827. {
  828. _isCurrentWarningA = true;
  829. LOG.WriteLog(eEvent.WARN_METAL, Module, $"Current SideA Current {_device.SideAPowerSupplier.PowerSupplierData.Current} is not in " +
  830. $"recipe Range{_powerSupplierStepPeriodDatas[_stepIndex].Current - currentWarningFault} ~ {_powerSupplierStepPeriodDatas[_stepIndex].Current + currentWarningFault}");
  831. }
  832. }
  833. else
  834. {
  835. //监控电压B面
  836. MetalEntity metalEntity = Singleton<RouteManager>.Instance.GetModule<MetalEntity>(Module);
  837. if (!_isVotlageWarningB && _device.SideBPowerSupplier.PowerSupplierData.Voltage > _recipe.VoltageWarningLevel && _device.SideBPowerSupplier.PowerSupplierData.Voltage < _recipe.VolatageLimitMax)
  838. {
  839. _isVotlageWarningB = true;
  840. LOG.WriteLog(eEvent.WARN_METAL, Module, $"Current SideB Votlage {_device.SideBPowerSupplier.PowerSupplierData.Voltage} is large than recipe VolatageWarningLevel {_recipe.VoltageWarningLevel}");
  841. }
  842. if (_device.SideBPowerSupplier.PowerSupplierData.Voltage < _recipe.VolatageLimitMin)
  843. {
  844. if (metalEntity != null)
  845. {
  846. metalEntity.PostMsg(MetalMsg.Error);
  847. }
  848. Abort();
  849. LOG.WriteLog(eEvent.ERR_METAL, Module, $"Current SideB Votlage {_device.SideBPowerSupplier.PowerSupplierData.Voltage} is lower than recipe VolatageLimitMin {_recipe.VolatageLimitMin}");
  850. }
  851. if (_device.SideBPowerSupplier.PowerSupplierData.Voltage > _recipe.VolatageLimitMax)
  852. {
  853. if (metalEntity != null)
  854. {
  855. metalEntity.PostMsg(MetalMsg.Error);
  856. }
  857. Abort();
  858. LOG.WriteLog(eEvent.ERR_METAL, Module, $"Current SideB Votlage {_device.SideBPowerSupplier.PowerSupplierData.Voltage} is large than recipe VolatageLimitMin {_recipe.VolatageLimitMax}");
  859. }
  860. //监控电流B面
  861. double currentWarningFault = _powerSupplierStepPeriodDatas[_stepIndex].Current * _recipe.CurrentWarningLevel * 0.01;
  862. double currentErrorFault = _powerSupplierStepPeriodDatas[_stepIndex].Current * _recipe.FaultPercent * 0.01;
  863. if (_device.SideBPowerSupplier.PowerSupplierData.Current > _powerSupplierStepPeriodDatas[_stepIndex].Current + currentErrorFault
  864. || _device.SideBPowerSupplier.PowerSupplierData.Current < _powerSupplierStepPeriodDatas[_stepIndex].Current - currentErrorFault)
  865. {
  866. if (metalEntity != null)
  867. {
  868. metalEntity.PostMsg(MetalMsg.Error);
  869. }
  870. Abort();
  871. LOG.WriteLog(eEvent.ERR_METAL, Module, $"Current SideB Current {_device.SideBPowerSupplier.PowerSupplierData.Current} is not in " +
  872. $"recipe Range{_powerSupplierStepPeriodDatas[_stepIndex].Current - currentErrorFault} ~ {_powerSupplierStepPeriodDatas[_stepIndex].Current + currentErrorFault}");
  873. }
  874. if (!_isCurrentWarningB && ((_device.SideBPowerSupplier.PowerSupplierData.Current > _powerSupplierStepPeriodDatas[_stepIndex].Current + currentWarningFault && _device.SideBPowerSupplier.PowerSupplierData.Current < _powerSupplierStepPeriodDatas[_stepIndex].Current + currentErrorFault)
  875. || (_device.SideBPowerSupplier.PowerSupplierData.Current < _powerSupplierStepPeriodDatas[_stepIndex].Current - currentWarningFault && _device.SideBPowerSupplier.PowerSupplierData.Current > _powerSupplierStepPeriodDatas[_stepIndex].Current - currentErrorFault)))
  876. {
  877. _isCurrentWarningB = true;
  878. LOG.WriteLog(eEvent.WARN_METAL, Module, $"Current SideB Current {_device.SideBPowerSupplier.PowerSupplierData.Current} is not in " +
  879. $"recipe Range {_powerSupplierStepPeriodDatas[_stepIndex].Current - currentWarningFault} ~ {_powerSupplierStepPeriodDatas[_stepIndex].Current + currentWarningFault}");
  880. }
  881. }
  882. }
  883. }
  884. /// <summary>
  885. /// 检验电流和电压合理性
  886. /// </summary>
  887. /// <param name="current"></param>
  888. /// <param name="voltage"></param>
  889. /// <param name="side"></param>
  890. /// <returns></returns>
  891. private bool CheckSidePowerInvalid(double current, double voltage, string side)
  892. {
  893. double maxVoltage = _recipe.VolatageLimitMax;
  894. double warnVoltage = _recipe.VoltageWarningLevel;
  895. double minVoltage = _recipe.VolatageLimitMin;
  896. if (voltage > maxVoltage)
  897. {
  898. LOG.WriteLog(eEvent.ERR_METAL, Module, $"{side} voltage {voltage} is large than recipe max voltage {maxVoltage}");
  899. return true;
  900. }
  901. if (voltage < minVoltage)
  902. {
  903. LOG.WriteLog(eEvent.ERR_METAL, Module, $"{side} voltage {voltage} is less than recipe min voltage {minVoltage}");
  904. return true;
  905. }
  906. if (voltage > warnVoltage)
  907. {
  908. string str = $"{side} voltage is {voltage} in warning";
  909. if (AlarmListManager.Instance.AddWarn(Module, $"{side} voltage", str))
  910. {
  911. LOG.WriteLog(eEvent.WARN_PREWET, Module, str);
  912. }
  913. }
  914. double maxErrorCurrent = _powerSupplierStepPeriodDatas[_stepIndex].Current * (double)(1 + _recipe.FaultPercent * 0.01);
  915. double minErrorCurrent = _powerSupplierStepPeriodDatas[_stepIndex].Current * (double)(1 - _recipe.FaultPercent * 0.01);
  916. double maxWarnCurrent = _powerSupplierStepPeriodDatas[_stepIndex].Current * (double)(1 + _recipe.CurrentWarningLevel * 0.01);
  917. double minWarnCurrent = _powerSupplierStepPeriodDatas[_stepIndex].Current * (double)(1 - _recipe.CurrentWarningLevel * 0.01);
  918. if (current > maxErrorCurrent)
  919. {
  920. LOG.WriteLog(eEvent.ERR_METAL, Module, $"{side} current {current} is large than recipe max current {maxErrorCurrent}");
  921. return true;
  922. }
  923. if (current < minErrorCurrent)
  924. {
  925. LOG.WriteLog(eEvent.ERR_METAL, Module, $"{side} current {current} is less than recipe min current {minErrorCurrent}");
  926. return true;
  927. }
  928. if ((current <= maxErrorCurrent && current >= maxWarnCurrent) || (current >= minErrorCurrent && current <= minWarnCurrent))
  929. {
  930. string str = $"{side} current {current} is in warning";
  931. if (AlarmListManager.Instance.AddWarn(Module, $"{side} current", str))
  932. {
  933. LOG.WriteLog(eEvent.WARN_PREWET, Module, str);
  934. }
  935. }
  936. return false;
  937. }
  938. /// <summary>
  939. /// 停止Linmot
  940. /// </summary>
  941. /// <returns></returns>
  942. private bool StopLinmot()
  943. {
  944. return _device.StopLinmot();
  945. }
  946. /// <summary>
  947. /// 停止电源
  948. /// </summary>
  949. /// <returns></returns>
  950. private bool StopPowerSupplier()
  951. {
  952. if (string.IsNullOrEmpty(_side))
  953. {
  954. _device.SideAPowerSupplier.DisableOperation("", null);
  955. _device.SideBPowerSupplier.DisableOperation("", null);
  956. }
  957. else
  958. {
  959. CellPowerSupplier cellPowerSupplier = GetSidePowerSupplier();
  960. cellPowerSupplier.DisableOperation("", null);
  961. }
  962. return true;
  963. }
  964. /// <summary>
  965. /// 切换成正常模式
  966. /// </summary>
  967. /// <returns></returns>
  968. private bool SwitchToNormal()
  969. {
  970. if (string.IsNullOrEmpty(_side))
  971. {
  972. _device.SideAPowerSupplier.SwitchPowerRunModel((int)PowerRunModelEnum.Normal);
  973. _device.SideBPowerSupplier.SwitchPowerRunModel((int)PowerRunModelEnum.Normal);
  974. }
  975. else
  976. {
  977. CellPowerSupplier cellPowerSupplier = GetSidePowerSupplier();
  978. cellPowerSupplier.SwitchPowerRunModel((int)PowerRunModelEnum.Normal);
  979. }
  980. return true;
  981. }
  982. /// <summary>
  983. /// 启动
  984. /// </summary>
  985. /// <param name="objs"></param>
  986. /// <returns></returns>
  987. public RState Start(params object[] objs)
  988. {
  989. _isVotlageWarningA = false;
  990. _isVotlageWarningB = false;
  991. _isCurrentWarningA = false;
  992. _isCurrentWarningB = false;
  993. _recipe = objs[0] as DepRecipe;
  994. if (_recipe == null)
  995. {
  996. LOG.WriteLog(eEvent.ERR_METAL, Module, "recipe is null");
  997. return RState.Failed;
  998. }
  999. if (objs.Length > 1)
  1000. {
  1001. _side = objs[1].ToString();
  1002. }
  1003. _startRecipeStep = false;
  1004. _anodeAUsage = 0;
  1005. _anodeBUsage = 0;
  1006. _device = DEVICE.GetDevice<MetalCellDevice>(Module);
  1007. _metalEntity = Singleton<RouteManager>.Instance.GetModule<MetalEntity>(Module);
  1008. UpdatePowerStepDatas();
  1009. _stepIndex = 0;
  1010. _header.SoftWareVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
  1011. _header.Recipe = $"{_recipe.Ppid}.dep.rcp";
  1012. if (SC.ContainsItem("System.ToolID")) _header.ToolID = SC.GetStringValue("System.ToolID");
  1013. //lotTract记录SequenceRecipe
  1014. MetalEntity metalEntity = Singleton<RouteManager>.Instance.GetModule<MetalEntity>(Module);
  1015. if (metalEntity.WaferHolderInfo != null && metalEntity.WaferHolderInfo.SequenceRecipe != null && !String.IsNullOrEmpty(metalEntity.WaferHolderInfo.SequenceRecipe.Ppid.ToString()))
  1016. {
  1017. _header.SequenceRecipe = metalEntity.WaferHolderInfo.SequenceRecipe.Ppid.ToString();
  1018. _header.ProcessTransferList = new List<string>();
  1019. _header.ProcessTransferList.AddRange(metalEntity.WaferHolderInfo.SchedulerModules);
  1020. metalEntity.WaferHolderInfo.SchedulerModules.Clear();
  1021. }
  1022. _facilities = DEVICE.GetDevice<SystemFacilities>("System.Facilities");
  1023. if (_facilities == null)
  1024. {
  1025. LOG.WriteLog(eEvent.ERR_METAL, Module, "Facility is null");
  1026. return RState.Failed;
  1027. }
  1028. string reservoirName = ReservoirItemManager.Instance.GetReservoirByMetal(Module);
  1029. MetalItem metalItem = MetalItemManager.Instance.GetMetalItem(Module);
  1030. _metalType = metalItem.SubType;
  1031. if (_metalType == STRATUS)
  1032. {
  1033. _standardHotReservoirDevice = DEVICE.GetDevice<StandardHotReservoirDevice>(reservoirName);
  1034. _standardHotMetalDevice = DEVICE.GetDevice<StandardHotMetalDevice>(Module);
  1035. if (_standardHotReservoirDevice == null || _standardHotMetalDevice == null)
  1036. {
  1037. LOG.WriteLog(eEvent.ERR_METAL, Module, $"metal or reservoir device is null");
  1038. return RState.Failed;
  1039. }
  1040. if (_standardHotMetalDevice.MetalDeviceData.CellFlow <= 0) //检查cell flow
  1041. {
  1042. LOG.WriteLog(eEvent.ERR_METAL, Module, $"reservoir metal cell flow is 0");
  1043. return RState.Failed;
  1044. }
  1045. }
  1046. else
  1047. {
  1048. _compactMembranReservoirDevice = DEVICE.GetDevice<CompactMembranReservoirDevice>(reservoirName);
  1049. _compactMembranMetalDevice = DEVICE.GetDevice<CompactMembranMetalDevice>(Module);
  1050. if (_compactMembranMetalDevice == null || _compactMembranReservoirDevice == null)
  1051. {
  1052. LOG.WriteLog(eEvent.ERR_METAL, Module, $"metal or reservoir device is null");
  1053. return RState.Failed;
  1054. }
  1055. if (_compactMembranMetalDevice.MetalDeviceData.CellFlow <= 0) //检查cell flow
  1056. {
  1057. LOG.WriteLog(eEvent.ERR_METAL, Module, $"reservoir metal cell flow is 0");
  1058. return RState.Failed;
  1059. }
  1060. if (_compactMembranMetalDevice.ANACellFlow.CounterValue <= 0) //检查hold flow
  1061. {
  1062. LOG.WriteLog(eEvent.ERR_METAL, Module, $"reservoir metal AnodeA flow is 0");
  1063. return RState.Failed;
  1064. }
  1065. if (_compactMembranMetalDevice.ANBCellFlow.CounterValue <= 0)
  1066. {
  1067. LOG.WriteLog(eEvent.ERR_METAL, Module, $"reservoir metal AnodeB flow is 0");
  1068. return RState.Failed;
  1069. }
  1070. }
  1071. ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(reservoirName);
  1072. _temperatureController = DEVICE.GetDevice<TemperatureController>(reservoirItem.TCID);
  1073. if (_temperatureController == null)
  1074. {
  1075. LOG.WriteLog(eEvent.ERR_METAL, Module, $"Temperature controller is null");
  1076. return RState.Failed;
  1077. }
  1078. _persistentValue = MetalPersistentManager.Instance.GetMetalPersistentValue(Module);
  1079. if (_persistentValue == null)
  1080. {
  1081. LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} Persistent Value Object is not exist");
  1082. return RState.Failed;
  1083. }
  1084. _lotTackTime = DateTime.Now;
  1085. return Runner.Start(Module, "Metal run recipe");
  1086. }
  1087. public void clearLotTrack()
  1088. {
  1089. _datas.Clear();
  1090. }
  1091. public void resetMetalUsage()
  1092. {
  1093. _anodeAUsage = 0;
  1094. _anodeBUsage = 0;
  1095. }
  1096. }
  1097. }