VpwMainDevice.cs 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069
  1. using Aitex.Core.RT.DataCenter;
  2. using Aitex.Core.RT.Device;
  3. using Aitex.Core.RT.Log;
  4. using Aitex.Core.RT.OperationCenter;
  5. using Aitex.Core.RT.Routine;
  6. using Aitex.Core.RT.SCCore;
  7. using Aitex.Core.Util;
  8. using MECF.Framework.Common.Alarm;
  9. using MECF.Framework.Common.Algorithm;
  10. using MECF.Framework.Common.Beckhoff.ModuleIO;
  11. using MECF.Framework.Common.CommonData.Prewet;
  12. using MECF.Framework.Common.CommonData.Vpw;
  13. using MECF.Framework.Common.Equipment;
  14. using MECF.Framework.Common.IOCore;
  15. using MECF.Framework.Common.Persistent.Prewet;
  16. using MECF.Framework.Common.Persistent.VpwMain;
  17. using MECF.Framework.Common.ToolLayout;
  18. using PunkHPX8_Core;
  19. using PunkHPX8_RT.Devices.VpwCell;
  20. using PunkHPX8_RT.Modules;
  21. using PunkHPX8_RT.Modules.VpwCelMain;
  22. using PunkHPX8_RT.Modules.VpwMain;
  23. using SecsGem.Core.ItemModel;
  24. using System;
  25. using System.Collections.Generic;
  26. using System.Diagnostics;
  27. using System.Linq;
  28. using System.Net.NetworkInformation;
  29. using System.Reflection;
  30. using System.Text;
  31. using System.Threading.Tasks;
  32. using System.Windows.Media.Animation;
  33. namespace PunkHPX8_RT.Devices.VpwMain
  34. {
  35. public class VpwMainDevice : BaseDevice, IDevice
  36. {
  37. #region 常量
  38. private const string COMMON_DATA = "CommonData";
  39. private const string PERSISTENT_VALUE = "PersistentValue";
  40. private const string CHAMBER_CLOSED = "ChamberClosed";
  41. private const string CHAMBER_OPENED = "ChamberOpened";
  42. private const string CHAMBER_CLOSE = "ChamberClose";
  43. private const string LEAK_DETECTED = "LeakDetected";
  44. private const string VACUUM_PUMP_PRESSURE = "VacuumPumpPressure";
  45. private const string VACUUM_PUMP_POWER = "VacuumPumpPower";
  46. private const string VACUUM_PUMP_ENABLE = "VacuumPumpEnable";
  47. private const string VACUUM_PUMP_SPEED_ENABLE = "VacuumPumpSpeedEnable";
  48. private const string VACUUM_PUMP_SPEED = "VacuumPumpSpeed";
  49. private const string BOOSTER_PUMP_SPEED = "BoosterPumpSpeed";
  50. private const string BOOSTER_PUMP_CURRENT = "BoosterPumpCurrent";
  51. private const string BOOSTER_PUMP_ENABLE = "BoosterPumpEnable";
  52. private const string BOOSTER_PUMP_STATUS = "BoosterPumpStatus";
  53. private const string DIW_ENABLE = "DiwEnable";
  54. private const string DIW_PROCESS = "DiwProcess";
  55. private const string DIW_DEGAS = "DiwDegas";
  56. private const string DIW_TOTAL_FLOW = "DiwTotalFlow";
  57. private const string DIW_PRESSURE = "DiwPressure";
  58. private const string DEGAS_ADJUST = "DegasAdjust";
  59. private const string DEGAS_PURGE = "DegasPurge";
  60. private const string DEGAS_PUMP_ENABLE = "DegasPumpEnable";
  61. private const string DEGAS_PUMP_PRESSURE = "DegasPumpPressure";
  62. #endregion
  63. private enum VPWOperation
  64. {
  65. None,
  66. PumpEnable,
  67. PumpDisable,
  68. HomeAllRotation
  69. }
  70. #region 内部变量
  71. /// <summary>
  72. /// 变量是否初始化字典
  73. /// </summary>
  74. private Dictionary<string, bool> _variableInitializeDic = new Dictionary<string, bool>();
  75. /// <summary>
  76. /// 数据
  77. /// </summary>
  78. private VpwMainCommonData _commonData=new VpwMainCommonData();
  79. /// <summary>
  80. /// 持久性数值
  81. /// </summary>
  82. private VpwMainPersistentValue _vpwMainPersistentValue;
  83. /// <summary>
  84. /// Pump Enable routine
  85. /// </summary>
  86. private BoosterPumpEnableRoutine _boosterPumpEnableRoutine;
  87. /// <summary>
  88. /// Pump Disable routine
  89. /// </summary>
  90. private BoosterPumpDisableRoutine _boosterPumpDisableRoutine;
  91. /// <summary>
  92. /// 上一次Booster泵速
  93. /// </summary>
  94. private short _lastBoosterPumpSpeed = 0;
  95. /// <summary>
  96. /// 定时器任务
  97. /// </summary>
  98. private PeriodicJob _periodicJob;
  99. /// <summary>
  100. /// 是否数据完成初台化
  101. /// </summary>
  102. private bool _isDataInitialized;
  103. /// <summary>
  104. /// pdi控制中的p
  105. /// </summary>
  106. private double _pumpKp;
  107. /// <summary>
  108. /// pdi控制中的i
  109. /// </summary>
  110. private double _pumpKi;
  111. /// <summary>
  112. /// pdi控制中的d
  113. /// </summary>
  114. private double _pumpKd;
  115. /// <summary>
  116. /// flow pdi控制中的p
  117. /// </summary>
  118. private double _pumpFlowKp;
  119. /// <summary>
  120. /// flow pdi控制中的i
  121. /// </summary>
  122. private double _pumpFlowKi;
  123. /// <summary>
  124. /// flow pdi控制中的d
  125. /// </summary>
  126. private double _pumpFlowKd;
  127. /// <summary>
  128. /// Boost pump调速的目标类型
  129. /// </summary>
  130. private VPWBoostPumpTarget _boosterBoostPumpTarget;
  131. /// <summary>
  132. /// Boost pump目标流量
  133. /// </summary>
  134. private double _boosterTargetFlow;
  135. /// <summary>
  136. /// Cell Flow数值
  137. /// </summary>
  138. private double _cellFlow;
  139. /// <summary>
  140. /// 操作当前状态
  141. /// </summary>
  142. private RState _status;
  143. /// <summary>
  144. /// 当前操作
  145. /// </summary>
  146. private VPWOperation _currentOperation;
  147. /// <summary>
  148. /// 启动自动调泵速
  149. /// </summary>
  150. private bool _isStartAutoSpeed;
  151. /// <summary>
  152. /// Home 电机
  153. /// </summary>
  154. private VpwSimpleHomeRoutine _simpleHomeRoutine;
  155. /// <summary>
  156. /// 总流量计时器
  157. /// </summary>
  158. private Stopwatch _totalFlowWatch = new Stopwatch();
  159. /// <summary>
  160. /// 总流量上升沿
  161. /// </summary>
  162. private R_TRIG _totalFlowTrig = new R_TRIG();
  163. /// <summary>
  164. /// 检测到total flow 低于设定条件的时间
  165. /// </summary>
  166. private DateTime _totalFlowAbnormalDetectTime;
  167. /// <summary>
  168. /// 检测到cell flow 满足设定条件的时间
  169. /// </summary>
  170. private bool _totalFlowAbnormal;
  171. #endregion
  172. #region 属性
  173. /// <summary>
  174. /// 数据
  175. /// </summary>
  176. public VpwMainCommonData CommonData { get { return _commonData; } }
  177. /// <summary>
  178. /// Boost Pump目标类型
  179. /// </summary>
  180. public VPWBoostPumpTarget VPWBoostPumpTarget { set { _boosterBoostPumpTarget = value; } }
  181. /// <summary>
  182. /// Booster目标流量
  183. /// </summary>
  184. public double BoostTargetFlow { set { _boosterTargetFlow = value; } }
  185. /// <summary>
  186. /// Cell Flow
  187. /// </summary>
  188. public double CellFlow { set { _cellFlow = value; } }
  189. #endregion
  190. /// <summary>
  191. /// 构造函数
  192. /// </summary>
  193. /// <param name="moduleName"></param>
  194. public VpwMainDevice(string moduleName) : base(moduleName, moduleName, moduleName, moduleName)
  195. {
  196. }
  197. #region 初始化
  198. /// <summary>
  199. /// 初始化
  200. /// </summary>
  201. /// <returns></returns>
  202. public bool Initialize()
  203. {
  204. InitializeParameter();
  205. InitializeRoutine();
  206. SubscribeData();
  207. SubscribeValueAction();
  208. InitializeOperation();
  209. return true;
  210. }
  211. /// <summary>
  212. /// 初始化参数
  213. /// </summary>
  214. private void InitializeParameter()
  215. {
  216. _vpwMainPersistentValue = VpwMainPersistentManager.Instance.GetPersistentValue(Module);
  217. if (_vpwMainPersistentValue != null)
  218. {
  219. _lastBoosterPumpSpeed = _vpwMainPersistentValue.Speed;
  220. }
  221. else
  222. {
  223. LOG.WriteLog(eEvent.ERR_PREWET, Module, "Persistent Value Object is not exist");
  224. }
  225. _commonData.BoosterPumpPressureData = new MECF.Framework.Common.CommonData.CommonLimitData();
  226. }
  227. /// <summary>
  228. /// 初始化Routine
  229. /// </summary>
  230. private void InitializeRoutine()
  231. {
  232. _boosterPumpEnableRoutine = new BoosterPumpEnableRoutine(Module, this);
  233. _boosterPumpDisableRoutine = new BoosterPumpDisableRoutine(Module, this);
  234. _simpleHomeRoutine = new VpwSimpleHomeRoutine(Module.ToString());
  235. }
  236. /// <summary>
  237. /// 订阅
  238. /// </summary>
  239. private void SubscribeData()
  240. {
  241. DATA.Subscribe($"{Module}.{PERSISTENT_VALUE}", () => _vpwMainPersistentValue, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  242. DATA.Subscribe($"{Module}.{COMMON_DATA}", () => CommonData, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  243. DATA.Subscribe($"{Module}.DiwEnable", () => CommonData.DiwEnable, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  244. }
  245. /// <summary>
  246. /// 订阅数据
  247. /// </summary>
  248. private void SubscribeValueAction()
  249. {
  250. IoSubscribeUpdateVariable(CHAMBER_CLOSED);
  251. IoSubscribeUpdateVariable(CHAMBER_OPENED);
  252. IoSubscribeUpdateVariable(BOOSTER_PUMP_STATUS);
  253. IoSubscribeUpdateVariable(BOOSTER_PUMP_SPEED);
  254. IoSubscribeUpdateVariable(BOOSTER_PUMP_ENABLE);
  255. IoSubscribeUpdateVariable(BOOSTER_PUMP_CURRENT);
  256. IoSubscribeUpdateVariable(DEGAS_PURGE);
  257. IoSubscribeUpdateVariable(DEGAS_ADJUST);
  258. IoSubscribeUpdateVariable(DEGAS_PUMP_PRESSURE);
  259. IoSubscribeUpdateVariable(DEGAS_PUMP_ENABLE);
  260. IoSubscribeUpdateVariable(DIW_ENABLE);
  261. IoSubscribeUpdateVariable(DIW_PROCESS);
  262. IoSubscribeUpdateVariable(DIW_PRESSURE);
  263. IoSubscribeUpdateVariable(DIW_DEGAS);
  264. IoSubscribeUpdateVariable(DIW_TOTAL_FLOW);
  265. IoSubscribeUpdateVariable(VACUUM_PUMP_ENABLE);
  266. IoSubscribeUpdateVariable(VACUUM_PUMP_POWER);
  267. IoSubscribeUpdateVariable(VACUUM_PUMP_PRESSURE);
  268. IoSubscribeUpdateVariable(VACUUM_PUMP_SPEED);
  269. IoSubscribeUpdateVariable(VACUUM_PUMP_SPEED_ENABLE);
  270. IoSubscribeUpdateVariable(LEAK_DETECTED);
  271. }
  272. /// <summary>
  273. /// 初始化变量
  274. /// </summary>
  275. /// <param name="variable"></param>
  276. private void IoSubscribeUpdateVariable(string variable)
  277. {
  278. _variableInitializeDic[variable] = false;
  279. IOModuleManager.Instance.SubscribeModuleVariable(Module, variable, UpdateVariableValue);
  280. }
  281. /// <summary>
  282. /// 更新变量数值
  283. /// </summary>
  284. /// <param name="variable"></param>
  285. /// <param name="value"></param>
  286. private void UpdateVariableValue(string variable, object value)
  287. {
  288. if (!_commonData.IsDataInitialized)
  289. {
  290. _commonData.IsDataInitialized = true;
  291. _commonData.BoosterPumpModel = "Manual";
  292. }
  293. PropertyInfo property = _commonData.GetType().GetProperty(variable);
  294. if (property != null)
  295. {
  296. property.SetValue(_commonData, value);
  297. }
  298. if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable])
  299. {
  300. _variableInitializeDic[variable] = true;
  301. }
  302. switch (variable)
  303. {
  304. case BOOSTER_PUMP_STATUS:
  305. string statusContent = _commonData.BoosterPumpStatus ? "On" : "Off";
  306. _commonData.BoosterPumpStatusContent = $"{_commonData.BoosterPumpModel}: {statusContent}";
  307. break;
  308. case DIW_PRESSURE:
  309. if (double.TryParse(value.ToString(), out var pressure))
  310. {
  311. _commonData.BoosterPumpPressureData.Value = pressure;
  312. }
  313. break;
  314. }
  315. }
  316. /// <summary>
  317. /// 初始化OP
  318. /// </summary>
  319. private void InitializeOperation()
  320. {
  321. OP.Subscribe($"{Module}.VacuumPumpPowerOn", (cmd,para)=> { return VacuumPumpPowerOn(); });
  322. OP.Subscribe($"{Module}.VacuumPumpPowerOff", (cmd, para) => { return VacuumPumpPowerOff(); });
  323. OP.Subscribe($"{Module}.VacuumPumpEnable", (cmd, para) => { return VacuumPumpEnable(); });
  324. OP.Subscribe($"{Module}.VacuumPumpDisable", (cmd, para) => { return VacuumPumpDisable(); });
  325. OP.Subscribe($"{Module}.VacuumPumpSpeedEnable", (cmd, para) => { return VacuumSpeedEnable(); });
  326. OP.Subscribe($"{Module}.VacuumPumpSpeedDisable", (cmd, para) => { return VacuumSpeedDisable(); });
  327. OP.Subscribe($"{Module}.VacuumPumpSpeed", (cmd, para) => { return WriteVacuumSpeedOperation(cmd, para); });
  328. OP.Subscribe($"{Module}.DegasPumpEnable", (cmd, para) => { return DegasPumpEnable(); });
  329. OP.Subscribe($"{Module}.DegasPumpDisable", (cmd, para) => { return DegasPumpDisable(); });
  330. OP.Subscribe($"{Module}.DegasAdjustOn", (cmd, para) => { return DegasAdjustOn(); });
  331. OP.Subscribe($"{Module}.DegasAdjustOff", (cmd, para) => { return DegasAdjustOff(); });
  332. OP.Subscribe($"{Module}.DegasPurgeOn", (cmd, para) => { return N2PurgeValveOn(); });
  333. OP.Subscribe($"{Module}.DegasPurgeOff", (cmd, para) => { return N2PurgeValveOff(); });
  334. OP.Subscribe($"{Module}.DiwDegasValveOn", (cmd, para) => { return DiwDegasValveOn(); });
  335. OP.Subscribe($"{Module}.DiwDegasValveOff", (cmd, para) => { return DiwDegasValveOff(); });
  336. OP.Subscribe($"{Module}.DiwEnable", (cmd, para) => { return DiwEnable(); });
  337. OP.Subscribe($"{Module}.DiwDisable", (cmd, para) => { return DiwDisable(); });
  338. OP.Subscribe($"{Module}.DiwProcessOn", (cmd, para) => { return DiwProcessOn(); });
  339. OP.Subscribe($"{Module}.DiwProcessOff", (cmd, para) => { return DiwProcessOff(); });
  340. OP.Subscribe($"{Module}.BoosterPumpEnable", BoosterPumpEnableOperation);
  341. OP.Subscribe($"{Module}.BoosterPumpDisable", BoosterPumpDisableOperation);
  342. OP.Subscribe($"{Module}.BoosterPumpSpeed", BoosterPumpSpeedKeyDownOperation);
  343. OP.Subscribe($"{Module}.ChamberUp", (cmd, para) => { return ChamberUp(); });
  344. OP.Subscribe($"{Module}.ChamberDown", (cmd, para) => { return ChamberDown(); });
  345. OP.Subscribe($"{Module}.BoosterPumpSpeedAuto", (cmd, para) => { return BoosterPumpSpeedAutoOperation(); });
  346. OP.Subscribe($"{Module}.BoosterPumpSpeedManual", (cmd, para) => { return BoosterPumpSpeedManualOperation(); });
  347. OP.Subscribe($"{Module}.DisabledAction", DisabledOperation);
  348. OP.Subscribe($"{Module}.ManualAction", ManualOperation);
  349. OP.Subscribe($"{Module}.AutoAction", AutoOperation);
  350. OP.Subscribe($"{Module}.EngineeringModeAction", EngineeringModeOperation);
  351. OP.Subscribe($"{Module}.ProductionModeAction", ProductionModeOperation);
  352. OP.Subscribe($"{Module}.HomeAllRotation", HomeAllRotation);
  353. }
  354. #endregion
  355. #region Action
  356. #region HomeAllRotation
  357. public bool HomeAllRotation(string cmd, object[] param)
  358. {
  359. if (_status == RState.Running)
  360. {
  361. LOG.WriteLog(eEvent.ERR_PREWET, Module.ToString(), $"{Module} current execute {_currentOperation},cannot home all rotation");
  362. return false;
  363. }
  364. _status = _simpleHomeRoutine.Start();
  365. _currentOperation = VPWOperation.HomeAllRotation;
  366. return _status == RState.Running;
  367. }
  368. #endregion
  369. #region Vacum Pump
  370. /// <summary>
  371. /// Pump Power On
  372. /// </summary>
  373. /// <returns></returns>
  374. public bool VacuumPumpPowerOn()
  375. {
  376. return WriteVariableValue(VACUUM_PUMP_POWER, true);
  377. }
  378. /// <summary>
  379. /// Pump Power Off
  380. /// </summary>
  381. /// <returns></returns>
  382. public bool VacuumPumpPowerOff()
  383. {
  384. return WriteVariableValue(VACUUM_PUMP_POWER, false);
  385. }
  386. /// <summary>
  387. /// Pump Enable
  388. /// </summary>
  389. /// <returns></returns>
  390. public bool VacuumPumpEnable()
  391. {
  392. return WriteVariableValue(VACUUM_PUMP_ENABLE, true);
  393. }
  394. /// <summary>
  395. /// Pump Disable
  396. /// </summary>
  397. /// <returns></returns>
  398. public bool VacuumPumpDisable()
  399. {
  400. return WriteVariableValue(VACUUM_PUMP_ENABLE, false);
  401. }
  402. /// <summary>
  403. /// Speed Enable
  404. /// </summary>
  405. /// <returns></returns>
  406. public bool VacuumSpeedEnable()
  407. {
  408. return WriteVariableValue(VACUUM_PUMP_SPEED_ENABLE, true);
  409. }
  410. /// <summary>
  411. /// Speed disable
  412. /// </summary>
  413. /// <returns></returns>
  414. public bool VacuumSpeedDisable()
  415. {
  416. return WriteVariableValue(VACUUM_PUMP_SPEED_ENABLE, false);
  417. }
  418. /// <summary>
  419. /// 写入Vacuum速度
  420. /// </summary>
  421. /// <param name="speed"></param>
  422. /// <returns></returns>
  423. private bool WriteVacuumSpeedOperation(string cmd, object[] param)
  424. {
  425. if (short.TryParse(param[0].ToString(), out var speed))
  426. {
  427. return WriteVariableValue(VACUUM_PUMP_SPEED, speed);
  428. }
  429. else
  430. {
  431. LOG.WriteLog(eEvent.ERR_VPWMAIN, Module, $"Write VacuumSpeed {param[0]} is not short");
  432. return false;
  433. }
  434. }
  435. /// <summary>
  436. /// 写入速度
  437. /// </summary>
  438. /// <param name="speed"></param>
  439. /// <returns></returns>
  440. public bool WriteVacuumSpeed(short speed)
  441. {
  442. return WriteVariableValue(VACUUM_PUMP_SPEED, speed);
  443. }
  444. #endregion
  445. #region Degas Pump
  446. /// <summary>
  447. /// Degas Pump Enable
  448. /// </summary>
  449. /// <returns></returns>
  450. public bool DegasPumpEnable()
  451. {
  452. return WriteVariableValue(DEGAS_PUMP_ENABLE, true);
  453. }
  454. /// <summary>
  455. /// Degas Pump disable
  456. /// </summary>
  457. /// <returns></returns>
  458. public bool DegasPumpDisable()
  459. {
  460. return WriteVariableValue(DEGAS_PUMP_ENABLE, false);
  461. }
  462. /// <summary>
  463. /// Degas Adjust On
  464. /// </summary>
  465. /// <returns></returns>
  466. public bool DegasAdjustOn()
  467. {
  468. return WriteVariableValue(DEGAS_ADJUST, true);
  469. }
  470. /// <summary>
  471. /// Degas Adjust Off
  472. /// </summary>
  473. /// <returns></returns>
  474. public bool DegasAdjustOff()
  475. {
  476. return WriteVariableValue(DEGAS_ADJUST, false);
  477. }
  478. #endregion
  479. #region Booster Pump
  480. /// <summary>
  481. /// Pump Enable操作
  482. /// </summary>
  483. /// <param name="cmd"></param>
  484. /// <param name="param"></param>
  485. /// <returns></returns>
  486. public bool BoosterPumpEnableOperation(string cmd, object[] param)
  487. {
  488. if (_status == RState.Running)
  489. {
  490. LOG.WriteLog(eEvent.ERR_PREWET, Module.ToString(), $"{Module} current execute {_currentOperation},cannot Pump enable");
  491. return false;
  492. }
  493. _status = _boosterPumpEnableRoutine.Start();
  494. _currentOperation = VPWOperation.PumpEnable;
  495. return _status == RState.Running;
  496. }
  497. /// <summary>
  498. /// pump disable 操作
  499. /// </summary>
  500. /// <param name="cmd"></param>
  501. /// <param name="param"></param>
  502. /// <returns></returns>
  503. public bool BoosterPumpDisableOperation(string cmd, object[] param)
  504. {
  505. if (_status == RState.Running)
  506. {
  507. LOG.WriteLog(eEvent.ERR_PREWET, Module.ToString(), $"{Module} current execute {_currentOperation},cannot Pump disable");
  508. return false;
  509. }
  510. _status = _boosterPumpDisableRoutine.Start();
  511. _currentOperation = VPWOperation.PumpDisable;
  512. return _status == RState.Running;
  513. //return PumpDisable();
  514. }
  515. /// <summary>
  516. /// Booster Pump enable
  517. /// </summary>
  518. /// <returns></returns>
  519. public bool BoosterPumpEnable()
  520. {
  521. return WriteVariableValue(BOOSTER_PUMP_ENABLE, true);
  522. }
  523. /// <summary>
  524. /// Booster Pump Disable
  525. /// </summary>
  526. /// <returns></returns>
  527. public bool BoosterPumpDisable()
  528. {
  529. return WriteVariableValue(BOOSTER_PUMP_ENABLE, false);
  530. }
  531. /// <summary>
  532. /// 写入Booster泵速
  533. /// </summary>
  534. /// <param name="speed"></param>
  535. /// <returns></returns>
  536. public bool BoosterPumpSpeed(short speed=0)
  537. {
  538. return WriteVariableValue(BOOSTER_PUMP_SPEED, speed == 0 ? _lastBoosterPumpSpeed : speed);
  539. }
  540. /// Booster Pump Speed回车操作
  541. /// </summary>
  542. /// <param name="cmd"></param>
  543. /// <param name="param"></param>
  544. /// <returns></returns>
  545. private bool BoosterPumpSpeedKeyDownOperation(string cmd, object[] param)
  546. {
  547. if (_commonData.BoosterPumpSpeedAuto)
  548. {
  549. LOG.WriteLog(eEvent.ERR_PREWET, Module, "Pump speed is auto,cannot change speed");
  550. return false;
  551. }
  552. short speed = (short)param[0];
  553. bool result = BoosterPumpSpeed(speed);
  554. if (result)
  555. {
  556. _vpwMainPersistentValue.Speed = speed;
  557. _lastBoosterPumpSpeed = speed;
  558. VpwMainPersistentManager.Instance.UpdatePersistentValue(Module);
  559. }
  560. return true;
  561. }
  562. /// <summary>
  563. /// Pump Speed手动模式
  564. /// </summary>
  565. /// <param name="cmd"></param>
  566. /// <param name="param"></param>
  567. /// <returns></returns>
  568. private bool BoosterPumpSpeedManualOperation()
  569. {
  570. _commonData.BoosterPumpSpeedAuto = false;
  571. _commonData.BoosterPumpModel = "Manual";
  572. string statusContent = _commonData.BoosterPumpStatus ? "On" : "Off";
  573. _commonData.BoosterPumpStatusContent = $"{_commonData.BoosterPumpModel}: {statusContent}";
  574. return true;
  575. }
  576. /// <summary>
  577. /// Pump Speed自动模式
  578. /// </summary>
  579. /// <param name="cmd"></param>
  580. /// <param name="param"></param>
  581. /// <returns></returns>
  582. private bool BoosterPumpSpeedAutoOperation()
  583. {
  584. _commonData.BoosterPumpSpeedAuto = true;
  585. _commonData.BoosterPumpModel = "Auto";
  586. string statusContent = _commonData.BoosterPumpStatus ? "On" : "Off";
  587. _commonData.BoosterPumpStatusContent = $"{_commonData.BoosterPumpModel}: {statusContent}";
  588. return true;
  589. }
  590. #endregion
  591. #region Chamber
  592. /// <summary>
  593. /// 上升
  594. /// </summary>
  595. /// <returns></returns>
  596. public bool ChamberUp()
  597. {
  598. return WriteVariableValue(CHAMBER_CLOSE, true);
  599. }
  600. /// <summary>
  601. /// 下降
  602. /// </summary>
  603. /// <returns></returns>
  604. public bool ChamberDown()
  605. {
  606. return WriteVariableValue(CHAMBER_CLOSE, false);
  607. }
  608. #endregion
  609. #region Mode switch
  610. /// <summary>
  611. /// DisabledAction
  612. /// </summary>
  613. /// <param name="cmd"></param>
  614. /// <param name="param"></param>
  615. /// <returns></returns>
  616. private bool DisabledOperation(string cmd, object[] args)
  617. {
  618. string currentOperation = "Disabled";
  619. VpwMainEntity vpwMainEntity = Singleton<RouteManager>.Instance.GetModule<VpwMainEntity>(Module);
  620. if (vpwMainEntity != null && _vpwMainPersistentValue != null && _vpwMainPersistentValue.OperatingMode != currentOperation)
  621. {
  622. string preOperation = _vpwMainPersistentValue.OperatingMode;
  623. if (vpwMainEntity.IsBusy)
  624. {
  625. LOG.WriteLog(eEvent.ERR_VPWMAIN, Module, $"{Module} is Busy, can't switch to Disabled mode");
  626. return false;
  627. }
  628. vpwMainEntity.EnterInit();
  629. _vpwMainPersistentValue.OperatingMode = currentOperation;
  630. LOG.WriteLog(eEvent.INFO_VPWMAIN, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
  631. }
  632. VpwMainPersistentManager.Instance.UpdatePersistentValue(Module);
  633. return true;
  634. }
  635. /// <summary>
  636. /// ManualAction
  637. /// </summary>
  638. /// <param name="cmd"></param>
  639. /// <param name="param"></param>
  640. /// <returns></returns>
  641. private bool ManualOperation(string cmd, object[] args)
  642. {
  643. string currentOperation = "Manual";
  644. VpwMainEntity vpwMainEntity = Singleton<RouteManager>.Instance.GetModule<VpwMainEntity>(Module);
  645. if (vpwMainEntity != null && _vpwMainPersistentValue != null && _vpwMainPersistentValue.OperatingMode != currentOperation)
  646. {
  647. string preOperation = _vpwMainPersistentValue.OperatingMode;
  648. if (vpwMainEntity.IsBusy)
  649. {
  650. LOG.WriteLog(eEvent.ERR_VPWMAIN, Module, $"{Module} is Busy, can't switch to Manual mode");
  651. return false;
  652. }
  653. vpwMainEntity.EnterInit();
  654. _vpwMainPersistentValue.OperatingMode = currentOperation;
  655. _boosterBoostPumpTarget = VPWBoostPumpTarget.Pressure;
  656. LOG.WriteLog(eEvent.INFO_VPWMAIN, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
  657. }
  658. VpwMainPersistentManager.Instance.UpdatePersistentValue(Module);
  659. return true;
  660. }
  661. /// <summary>
  662. /// AutoAction
  663. /// </summary>
  664. /// <param name="cmd"></param>
  665. /// <param name="param"></param>
  666. /// <returns></returns>
  667. private bool AutoOperation(string cmd, object[] args)
  668. {
  669. string currentOperation = "Auto";
  670. VpwMainEntity vpwMainEntity = Singleton<RouteManager>.Instance.GetModule<VpwMainEntity>(Module);
  671. if (vpwMainEntity != null && _vpwMainPersistentValue != null && _vpwMainPersistentValue.OperatingMode != currentOperation)
  672. {
  673. string preOperation = _vpwMainPersistentValue.OperatingMode;
  674. if (vpwMainEntity.IsBusy)
  675. {
  676. LOG.WriteLog(eEvent.ERR_VPWMAIN, Module, $"{Module} is Busy, can't switch to Auto mode");
  677. return false;
  678. }
  679. vpwMainEntity.EnterInit();
  680. _vpwMainPersistentValue.OperatingMode = currentOperation;
  681. LOG.WriteLog(eEvent.INFO_VPWMAIN, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
  682. }
  683. VpwMainPersistentManager.Instance.UpdatePersistentValue(Module);
  684. return true;
  685. }
  686. /// <summary>
  687. /// EngineeringModeAction
  688. /// </summary>
  689. /// <param name="cmd"></param>
  690. /// <param name="param"></param>
  691. /// <returns></returns>
  692. private bool EngineeringModeOperation(string cmd, object[] args)
  693. {
  694. string currentRecipeOperation = "Engineering";
  695. if (_vpwMainPersistentValue != null)
  696. {
  697. _vpwMainPersistentValue.RecipeOperatingMode = currentRecipeOperation;
  698. }
  699. VpwMainPersistentManager.Instance.UpdatePersistentValue(Module);
  700. return true;
  701. }
  702. /// <summary>
  703. /// ProductionAction
  704. /// </summary>
  705. /// <param name="cmd"></param>
  706. /// <param name="param"></param>
  707. /// <returns></returns>
  708. private bool ProductionModeOperation(string cmd, object[] args)
  709. {
  710. string currentRecipeOperation = "Production";
  711. if (_vpwMainPersistentValue != null)
  712. {
  713. _vpwMainPersistentValue.RecipeOperatingMode = currentRecipeOperation;
  714. }
  715. VpwMainPersistentManager.Instance.UpdatePersistentValue(Module);
  716. return true;
  717. }
  718. #endregion
  719. #region DIW
  720. /// <summary>
  721. /// DIW Enable
  722. /// </summary>
  723. /// <returns></returns>
  724. public bool DiwEnable()
  725. {
  726. return WriteVariableValue(DIW_ENABLE, true);
  727. }
  728. /// <summary>
  729. /// DIW Disable
  730. /// </summary>
  731. /// <returns></returns>
  732. public bool DiwDisable()
  733. {
  734. return WriteVariableValue(DIW_ENABLE, false);
  735. }
  736. /// <summary>
  737. /// DIW Process On
  738. /// </summary>
  739. /// <returns></returns>
  740. public bool DiwProcessOn()
  741. {
  742. return WriteVariableValue(DIW_PROCESS, true);
  743. }
  744. /// <summary>
  745. /// DIW Process On
  746. /// </summary>
  747. /// <returns></returns>
  748. public bool DiwProcessOff()
  749. {
  750. return WriteVariableValue(DIW_PROCESS, false);
  751. }
  752. /// <summary>
  753. /// DIW Degas Valve On
  754. /// </summary>
  755. /// <returns></returns>
  756. public bool DiwDegasValveOn()
  757. {
  758. return WriteVariableValue(DIW_DEGAS, true);
  759. }
  760. /// <summary>
  761. /// DIW Degas Valve Off
  762. /// </summary>
  763. /// <returns></returns>
  764. public bool DiwDegasValveOff()
  765. {
  766. return WriteVariableValue(DIW_DEGAS, false);
  767. }
  768. #endregion
  769. #region N2Purge
  770. /// <summary>
  771. /// 打开N2 Purge
  772. /// </summary>
  773. /// <returns></returns>
  774. public bool N2PurgeValveOn()
  775. {
  776. return WriteVariableValue(DEGAS_PURGE, true);
  777. }
  778. /// <summary>
  779. /// 关闭N2 Purge
  780. /// </summary>
  781. /// <returns></returns>
  782. public bool N2PurgeValveOff()
  783. {
  784. return WriteVariableValue(DEGAS_PURGE, false);
  785. }
  786. #endregion
  787. /// <summary>
  788. /// 写变量
  789. /// </summary>
  790. /// <param name="variable"></param>
  791. /// <param name="value"></param>
  792. /// <returns></returns>
  793. private bool WriteVariableValue(string variable, object value)
  794. {
  795. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{variable}");
  796. return IOModuleManager.Instance.WriteIoValue(ioName, value);
  797. }
  798. #endregion
  799. /// <summary>
  800. /// 定时器
  801. /// </summary>
  802. /// <returns></returns>
  803. public bool OnTimer()
  804. {
  805. _commonData.BoosterPumpPressureData.MinError = SC.GetValue<double>($"VPWMain.PumpPressure.Error_Min");
  806. _commonData.BoosterPumpPressureData.MinWarning = SC.GetValue<double>($"VPWMain.PumpPressure.Warning_Min");
  807. _commonData.BoosterPumpPressureData.MaxError = SC.GetValue<double>($"VPWMain.PumpPressure.Error_Max");
  808. _commonData.BoosterPumpPressureData.MaxWarning = SC.GetValue<double>($"VPWMain.PumpPressure.Warning_Max");
  809. _commonData.PressureTarget = SC.GetValue<double>($"VPWMain.PressureTarget");
  810. if (_status == RState.Running)
  811. {
  812. IRoutine routine = GetCurrentRoutine();
  813. if (routine != null)
  814. {
  815. RState rsState = routine.Monitor();
  816. if (rsState == RState.Failed || rsState == RState.Timeout)
  817. {
  818. _status = RState.Failed;
  819. _currentOperation = VPWOperation.None;
  820. LOG.WriteLog(eEvent.ERR_VPWMAIN, Module.ToString(), $"{_currentOperation} error");
  821. _isStartAutoSpeed = false;
  822. }
  823. else if (rsState == RState.End)
  824. {
  825. if (_currentOperation == VPWOperation.PumpEnable)
  826. {
  827. _isStartAutoSpeed = true;
  828. }
  829. else if (_currentOperation == VPWOperation.PumpDisable)
  830. {
  831. _isStartAutoSpeed = false;
  832. }
  833. _status = RState.End;
  834. _currentOperation = VPWOperation.None;
  835. }
  836. }
  837. }
  838. if (_isStartAutoSpeed)
  839. {
  840. AdjustPumpSpeed();
  841. }
  842. MonitorTotalFlow();
  843. BoosterPumpMonitor();
  844. WaterPressureMonitor();
  845. return true;
  846. }
  847. //Speed Auto模式同时pump enbled,对water pressure 上下限进行监控
  848. private void WaterPressureMonitor()
  849. {
  850. if (_commonData.BoosterPumpSpeedAuto && _commonData.BoosterPumpEnable)
  851. {
  852. if(_commonData.DiwPressure > _commonData.BoosterPumpPressureData.MaxError)
  853. {
  854. LOG.WriteLog(eEvent.ERR_VPW, Module, $"water pressure {_commonData.DiwPressure} is large than Error_max {_commonData.BoosterPumpPressureData.MaxError},Booster Pump Closed!");
  855. BoosterPumpDisable();
  856. }
  857. else if (_commonData.DiwPressure > _commonData.BoosterPumpPressureData.MaxWarning)
  858. {
  859. if(!AlarmListManager.Instance.IsContainDataWarn(Module, "WaterPressure"))
  860. {
  861. AlarmListManager.Instance.AddWarn(Module, "WaterPressure", $"water pressure {_commonData.DiwPressure} is large than Warning_max {_commonData.BoosterPumpPressureData.MaxWarning}");
  862. LOG.WriteLog(eEvent.WARN_VPW, Module, $"water pressure {_commonData.DiwPressure} is large than Warning_max {_commonData.BoosterPumpPressureData.MaxWarning}");
  863. }
  864. }
  865. else if (_commonData.DiwPressure < _commonData.BoosterPumpPressureData.MinError)
  866. {
  867. LOG.WriteLog(eEvent.ERR_VPW, Module, $"water pressure {_commonData.DiwPressure} is lower than Error_min {_commonData.BoosterPumpPressureData.MinError},Booster Pump Closed!");
  868. BoosterPumpDisable();
  869. }
  870. else if (_commonData.DiwPressure < _commonData.BoosterPumpPressureData.MinWarning)
  871. {
  872. if (!AlarmListManager.Instance.IsContainDataWarn(Module, "WaterPressure"))
  873. {
  874. AlarmListManager.Instance.AddWarn(Module, "WaterPressure", $"water pressure {_commonData.DiwPressure} is large than Warning_min {_commonData.BoosterPumpPressureData.MinWarning}");
  875. LOG.WriteLog(eEvent.WARN_VPW, Module, $"water pressure {_commonData.DiwPressure} is lower than Warning_min {_commonData.BoosterPumpPressureData.MinWarning}");
  876. }
  877. }
  878. }
  879. }
  880. //total flow不满足条件过一段时间自动关闭增压泵
  881. private void BoosterPumpMonitor()
  882. {
  883. double totalFlowStartLimit = SC.GetValue<double>("VPWMain.Plumbing.TotalFlowStartLowLimit");
  884. int flowFaultHoldOffTime = SC.GetValue<int>($"VPWMain.Plumbing.FlowFaultHoldoffTime");
  885. if (_commonData.DiwTotalFlow < totalFlowStartLimit)
  886. {
  887. if (!_totalFlowAbnormal)
  888. {
  889. _totalFlowAbnormal = true;
  890. _totalFlowAbnormalDetectTime = DateTime.Now;
  891. }
  892. if ((DateTime.Now - _totalFlowAbnormalDetectTime).TotalSeconds > flowFaultHoldOffTime && _commonData.BoosterPumpEnable)
  893. {
  894. LOG.WriteLog(eEvent.WARN_VPW, Module, $"total flow is lower than start limit more than {flowFaultHoldOffTime} min,Booster Pump Closed!");
  895. BoosterPumpDisable();
  896. _totalFlowAbnormalDetectTime = DateTime.Now;
  897. }
  898. }
  899. else
  900. {
  901. _totalFlowAbnormal = false;
  902. }
  903. }
  904. /// <summary>
  905. /// 调速
  906. /// </summary>
  907. public void AdjustPumpSpeed()
  908. {
  909. //Speed Auto模式同时pump enbled,根据kdi调整泵速
  910. if (_commonData.BoosterPumpSpeedAuto && _commonData.BoosterPumpEnable)
  911. {
  912. _pumpKp = SC.GetValue<double>($"VPWMain.PumpKp");
  913. _pumpKd = SC.GetValue<double>($"VPWMain.PumpKd");
  914. _pumpKi = SC.GetValue<double>($"VPWMain.PumpKi");
  915. double limit = SC.GetValue<double>("VPWMain.PrewetTargetLimit");
  916. double downLimit = SC.GetValue<double>("VPWMain.PrewetDownTargetLimit");
  917. double minSpeedDelta = SC.GetValue<double>("VPWMain.MinSpeedDelta");
  918. short speed = 0;
  919. if (_boosterBoostPumpTarget == VPWBoostPumpTarget.Pressure)
  920. {
  921. speed= PdiAlgorithm.Instance.CalculateSpeed(_pumpKp, _pumpKi, _pumpKd, _commonData.PressureTarget,
  922. _commonData.BoosterPumpPressureData.Value, _lastBoosterPumpSpeed, limit, downLimit, minSpeedDelta);
  923. }
  924. else
  925. {
  926. speed= PdiAlgorithm.Instance.CalculateSpeed(_pumpFlowKp, _pumpFlowKi, _pumpFlowKd, _boosterTargetFlow,
  927. _cellFlow, _lastBoosterPumpSpeed, limit, downLimit, minSpeedDelta);
  928. }
  929. //short speed = PdiAlgorithm.Instance.CalculateSpeed(PrewetPumpData.PressureTarget, PrewetPumpData.PumpPressureData.Value,
  930. // _lastPumpSpeed, limit, downLimit);
  931. if (Math.Abs(speed - _lastBoosterPumpSpeed) >= 1)
  932. {
  933. _lastBoosterPumpSpeed = speed;
  934. BoosterPumpSpeed(speed);
  935. }
  936. }
  937. }
  938. /// <summary>
  939. /// 当前Routine;
  940. /// </summary>
  941. /// <returns></returns>
  942. private IRoutine GetCurrentRoutine()
  943. {
  944. switch (_currentOperation)
  945. {
  946. case VPWOperation.PumpEnable:
  947. return _boosterPumpEnableRoutine;
  948. case VPWOperation.PumpDisable:
  949. return _boosterPumpDisableRoutine;
  950. case VPWOperation.HomeAllRotation:
  951. return _simpleHomeRoutine;
  952. default:
  953. return null;
  954. }
  955. }
  956. /// <summary>
  957. /// 监控总流量
  958. /// </summary>
  959. private void MonitorTotalFlow()
  960. {
  961. double totalFlow = _commonData.DiwTotalFlow;
  962. double totalFlowStartLimit = SC.GetValue<double>("VPWMain.Plumbing.TotalFlowStartLowLimit");
  963. int dripValveOpenIdlePeriod = SC.GetValue<int>("VPWMain.DripValveOpenIdlePeriod")*60*1000;
  964. if (dripValveOpenIdlePeriod == 0)
  965. {
  966. return;
  967. }
  968. if (totalFlow < totalFlowStartLimit&&_totalFlowWatch.IsRunning)
  969. {
  970. LOG.WriteLog(eEvent.INFO_VPW, Module, $"total flow is less then start limit");
  971. _totalFlowWatch.Stop();
  972. return;
  973. }
  974. _totalFlowTrig.CLK = totalFlow >= totalFlowStartLimit;
  975. if (_totalFlowTrig.Q)
  976. {
  977. LOG.WriteLog(eEvent.INFO_VPW, Module, $"total flow is over start limit");
  978. _totalFlowWatch.Start();
  979. }
  980. if (_totalFlowWatch.ElapsedMilliseconds >= dripValveOpenIdlePeriod)
  981. {
  982. LOG.WriteLog(eEvent.INFO_VPW, Module, $"the time of total flow is over DripValveOpenIdlePeriod");
  983. List<VpwCellDevice> vpwCellDevices = new List<VpwCellDevice>();
  984. VpwMainItem vpwMainItem = VpwMainItemManager.Instance.GetItem(ModuleName.VPWMain1.ToString());
  985. if (vpwMainItem == null || vpwMainItem.VpwCells == null)
  986. {
  987. return;
  988. }
  989. foreach (var item in vpwMainItem.VpwCells)
  990. {
  991. VpwCellDevice cellDevice = DEVICE.GetDevice<VpwCellDevice>(item.ModuleName);
  992. vpwCellDevices.Add(cellDevice);
  993. }
  994. _totalFlowWatch.Reset();
  995. foreach (var item in vpwCellDevices)
  996. {
  997. VpwCellEntity vpwCellEntity = Singleton<RouteManager>.Instance.GetModule<VpwCellEntity>(item.Module);
  998. if (vpwCellEntity == null || vpwCellEntity.IsDisable)
  999. {
  1000. continue;
  1001. }
  1002. if (item.CommonData.FlowDrip)
  1003. {
  1004. continue;
  1005. }
  1006. item.FlowDripOn();
  1007. LOG.WriteLog(eEvent.INFO_VPW, Module, $"{item.Module} open drip valve after DripValveOpenIdlePeriod");
  1008. }
  1009. }
  1010. }
  1011. /// <summary>
  1012. /// 监控
  1013. /// </summary>
  1014. public void Monitor()
  1015. {
  1016. }
  1017. public void Reset()
  1018. {
  1019. }
  1020. public void Terminate()
  1021. {
  1022. }
  1023. }
  1024. }