ANPumpOnRoutine.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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 MECF.Framework.Common.Beckhoff.ModuleIO;
  6. using MECF.Framework.Common.Routine;
  7. using MECF.Framework.Common.ToolLayout;
  8. using MECF.Framework.Common.TwinCat;
  9. using CyberX8_Core;
  10. using CyberX8_RT.Devices.Metal;
  11. using CyberX8_RT.Devices.Reservoir;
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Linq;
  15. using System.Text;
  16. using System.Threading.Tasks;
  17. using CyberX8_RT.Devices.Safety;
  18. using MECF.Framework.Common.IOCore;
  19. namespace CyberX8_RT.Modules.Reservoir
  20. {
  21. public class ANPumpOnRoutine : RoutineBase, IRoutine
  22. {
  23. private enum ANPumpStep
  24. {
  25. PumpSpeed,
  26. Delay,
  27. ANByPass,
  28. CellsFillValve,
  29. FlowDelay,
  30. CheckFlow,
  31. CheckByPass,
  32. End
  33. }
  34. #region 常量
  35. private const string AN_A_PINENABLE = "ANAPinEnable";
  36. private const string AN_B_PINENABLE = "ANBPinEnable";
  37. private const string AN_PUMP = "ANPump";
  38. private const string AN_BY_PASS = "ANByPass";
  39. #endregion
  40. #region 内部变量
  41. /// <summary>
  42. /// 默认泵速
  43. /// </summary>
  44. private double _anPumpSpeed = 5000;
  45. /// <summary>
  46. /// flow fault hold off时长
  47. /// </summary>
  48. private int _flowFaultHoldOffTime = 10000;
  49. /// <summary>
  50. /// 阳极最小流量
  51. /// </summary>
  52. private double _anMinFlow = 0.2;
  53. /// <summary>
  54. /// 最小Bypass数值
  55. /// </summary>
  56. private int _anBypassMinCellCount;
  57. /// <summary>
  58. /// AN流量总和
  59. /// </summary>
  60. private double _anTotalFlow = 0;
  61. /// <summary>
  62. /// Reservoir设备
  63. /// </summary>
  64. private CompactMembranReservoirDevice _device;
  65. /// <summary>
  66. /// 阳极打开阀Cell总数
  67. /// </summary>
  68. private int _anOpenValveCount;
  69. #endregion
  70. /// <summary>
  71. /// 构造函数
  72. /// </summary>
  73. /// <param name="module"></param>
  74. public ANPumpOnRoutine(string module) : base(module)
  75. {
  76. }
  77. /// <summary>
  78. /// 中止
  79. /// </summary>
  80. public void Abort()
  81. {
  82. Runner.Stop("Manual abort");
  83. }
  84. /// <summary>
  85. /// 监控
  86. /// </summary>
  87. /// <returns></returns>
  88. public RState Monitor()
  89. {
  90. Runner.Run(ANPumpStep.PumpSpeed, () => { return ANPumpSpeed(_anPumpSpeed); }, _delay_1ms)
  91. .Run(ANPumpStep.ANByPass,ANByPassOn,_delay_1ms)
  92. .Run(ANPumpStep.CellsFillValve, OpenAllCellsFillValve,_delay_1ms)
  93. .Delay(ANPumpStep.Delay, _flowFaultHoldOffTime)
  94. .Run(ANPumpStep.CheckFlow,CheckAllFlow,_delay_1ms)
  95. .RunIf(ANPumpStep.CheckByPass, CheckTotalFlowBypass(),ANByPassOff,NullFun,_delay_1ms)
  96. .End(ANPumpStep.End, NullFun, _delay_1ms);
  97. return Runner.Status;
  98. }
  99. /// <summary>
  100. /// Pump Speed
  101. /// </summary>
  102. /// <param name="speed"></param>
  103. /// <returns></returns>
  104. private bool ANPumpSpeed(double speed)
  105. {
  106. SafetyDevice safetyDevice = DEVICE.GetDevice<SafetyDevice>("Safety");
  107. if (safetyDevice != null && !safetyDevice.SafetyData.PumpEdm)
  108. {
  109. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Safety PumpEdm is Activate");
  110. return false;
  111. }
  112. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_PUMP}");
  113. return IOModuleManager.Instance.WriteIoValue(ioName, speed);
  114. }
  115. /// <summary>
  116. /// Pump Bypass
  117. /// </summary>
  118. /// <param name="speed"></param>
  119. /// <returns></returns>
  120. private bool ANByPassOn()
  121. {
  122. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_BY_PASS}");
  123. return IOModuleManager.Instance.WriteIoValue(ioName, true);
  124. }
  125. /// <summary>
  126. /// Pump Bypass
  127. /// </summary>
  128. /// <param name="speed"></param>
  129. /// <returns></returns>
  130. private bool ANByPassOff()
  131. {
  132. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_BY_PASS}");
  133. return IOModuleManager.Instance.WriteIoValue(ioName, false);
  134. }
  135. /// <summary>
  136. /// 检验所有流量
  137. /// </summary>
  138. /// <returns></returns>
  139. private bool OpenAllCellsFillValve()
  140. {
  141. bool result = false;
  142. ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module.ToString());
  143. if (reservoirItem != null)
  144. {
  145. List<MetalItem> metalItems = reservoirItem.MetalCells;
  146. if (metalItems != null && metalItems.Count > 0)
  147. {
  148. foreach (MetalItem metalItem in metalItems)
  149. {
  150. if (metalItem.Installed)
  151. {
  152. CompactMembranMetalDevice metalDevice = DEVICE.GetDevice<CompactMembranMetalDevice>(metalItem.ModuleName);
  153. if (metalDevice != null && metalDevice.IsAuto)
  154. {
  155. _anOpenValveCount++;
  156. result = metalDevice.AnSideAFillOn("", null);
  157. if(!result)
  158. {
  159. return false;
  160. }
  161. result = metalDevice.AnSideBFillOn("", null);
  162. if (!result)
  163. {
  164. return false;
  165. }
  166. }
  167. }
  168. }
  169. }
  170. }
  171. return true;
  172. }
  173. /// <summary>
  174. /// 关闭所有Cell的Flow Valve
  175. /// </summary>
  176. /// <returns></returns>
  177. private bool CloseAllCellsFlowValve()
  178. {
  179. ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module.ToString());
  180. if (reservoirItem != null)
  181. {
  182. List<MetalItem> metalItems = reservoirItem.MetalCells;
  183. if (metalItems != null && metalItems.Count > 0)
  184. {
  185. foreach (MetalItem metalItem in metalItems)
  186. {
  187. if (metalItem.Installed)
  188. {
  189. CompactMembranMetalDevice metalDevice = DEVICE.GetDevice<CompactMembranMetalDevice>(metalItem.ModuleName);
  190. if (metalDevice != null && metalDevice.IsAuto)
  191. {
  192. metalDevice.AnSideAFillOff("", null);
  193. metalDevice.AnSideBFillOff("", null);
  194. }
  195. }
  196. }
  197. }
  198. }
  199. return true;
  200. }
  201. /// <summary>
  202. /// 检验所有流量
  203. /// </summary>
  204. /// <returns></returns>
  205. private bool CheckAllFlow()
  206. {
  207. if (_anOpenValveCount == 0)
  208. {
  209. return true;
  210. }
  211. _anTotalFlow = 0.0;
  212. ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module.ToString());
  213. if (reservoirItem != null)
  214. {
  215. List<MetalItem> metalItems = reservoirItem.MetalCells;
  216. if (metalItems != null && metalItems.Count > 0)
  217. {
  218. foreach (MetalItem metalItem in metalItems)
  219. {
  220. if (metalItem.Installed)
  221. {
  222. CompactMembranMetalDevice metalDevice = DEVICE.GetDevice<CompactMembranMetalDevice>(metalItem.ModuleName);
  223. if (metalDevice != null&&metalDevice.IsAuto)
  224. {
  225. _anTotalFlow += metalDevice.ANACellFlow.CounterValue;
  226. _anTotalFlow += metalDevice.ANBCellFlow.CounterValue;
  227. }
  228. }
  229. }
  230. }
  231. }
  232. if(_anTotalFlow<=_anMinFlow)
  233. {
  234. CloseAllCellsFlowValve();
  235. ANPumpSpeed(0);
  236. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"total flow {_anTotalFlow} is not over {_anMinFlow}");
  237. return false;
  238. }
  239. else
  240. {
  241. LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"total flow {_anTotalFlow} is over {_anMinFlow}");
  242. return true;
  243. }
  244. }
  245. /// <summary>
  246. /// 检验总流量Bypass情况
  247. /// </summary>
  248. /// <returns></returns>
  249. private bool CheckTotalFlowBypass()
  250. {
  251. return _anTotalFlow > _anBypassMinCellCount;
  252. }
  253. /// <summary>
  254. /// 启动
  255. /// </summary>
  256. /// <param name="objs"></param>
  257. /// <returns></returns>
  258. public RState Start(params object[] objs)
  259. {
  260. _device = DEVICE.GetDevice<CompactMembranReservoirDevice>(Module);
  261. _anPumpSpeed = SC.GetValue<double>("Reservoir.ANDefaultPumpSpeed");
  262. _flowFaultHoldOffTime = SC.GetValue<int>($"Reservoir.{Module}.FlowFaultHoldOffTime");
  263. _anBypassMinCellCount = SC.GetValue<int>($"Reservoir.{Module}.ANBypassMinCellCount");
  264. _anTotalFlow = 0;
  265. return Runner.Start(Module, "AN Pump On");
  266. }
  267. }
  268. }