StandardHotMetalDevice.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  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.UI.Control;
  7. using Aitex.Core.Util;
  8. using MECF.Framework.Common.Beckhoff.ModuleIO;
  9. using MECF.Framework.Common.CommonData.Metal;
  10. using MECF.Framework.Common.Persistent.Reservoirs;
  11. using MECF.Framework.Common.TwinCat;
  12. using CyberX8_Core;
  13. using CyberX8_RT.Devices.LinMot;
  14. using CyberX8_RT.Devices.Prewet;
  15. using System;
  16. using System.Collections.Generic;
  17. using System.Linq;
  18. using System.Reflection;
  19. using System.Diagnostics;
  20. using MECF.Framework.Common.IOCore;
  21. using Aitex.Core.RT.SCCore;
  22. using CyberX8_RT.Devices.PowerSupplier;
  23. using MECF.Framework.Common.ToolLayout;
  24. using SecsGem.Core.ItemModel;
  25. namespace CyberX8_RT.Devices.Metal
  26. {
  27. public class StandardHotMetalDevice : MetalCellDevice
  28. {
  29. private enum MetalOperation
  30. {
  31. None,
  32. CellPumpOn
  33. }
  34. #region 常量
  35. private const string PERSISTENT_VALUE = "PersistentValue";
  36. private const string CELL_PUMP = "CellPump";
  37. private const string CELL_FLOW = "CellFlow";
  38. private const string WH_CLAMP = "WaferHolderClamp";
  39. private const string CIRCULATION = "Circulation";
  40. #endregion
  41. #region 内部变量
  42. /// <summary>
  43. /// 设备数据
  44. /// </summary>
  45. private StandardHotMetalDeviceData _metalDeviceData = new StandardHotMetalDeviceData();
  46. /// <summary>
  47. /// 变量是否初始化字典
  48. /// </summary>
  49. private Dictionary<string, bool> _variableInitializeDic = new Dictionary<string, bool>();
  50. /// <summary>
  51. /// Pump Routine
  52. /// </summary>
  53. private StandardHotMetalCellPumpRoutine _cellPumpRoutine;
  54. /// <summary>
  55. /// 当前操作
  56. /// </summary>
  57. private MetalOperation _currentOperation;
  58. /// <summary>
  59. /// Flow Valve计时
  60. /// </summary>
  61. private Stopwatch _flowValveStopWatch = new Stopwatch();
  62. /// <summary>
  63. /// 是否有独立的泵
  64. /// </summary>
  65. private bool _isSignalPump;
  66. #endregion
  67. #region 属性
  68. /// <summary>
  69. /// 设备数据
  70. /// </summary>
  71. public StandardHotMetalDeviceData MetalDeviceData { get { return _metalDeviceData; } }
  72. /// <summary>
  73. /// Flow Valve稳定状态
  74. /// </summary>
  75. public bool FlowValveStable { get { return _metalDeviceData.Circulation && _flowValveStopWatch.ElapsedMilliseconds >= 3000; } }
  76. /// <summary>
  77. /// 是否有单独的泵
  78. /// </summary>
  79. public bool IsSignalPump { get { return _isSignalPump; } }
  80. #endregion
  81. /// <summary>
  82. /// 构造函数
  83. /// </summary>
  84. /// <param name="moduleName"></param>
  85. public StandardHotMetalDevice(string moduleName) : base(moduleName)
  86. {
  87. }
  88. /// <summary>
  89. /// 初始化
  90. /// </summary>
  91. /// <returns></returns>
  92. public override bool Initialize()
  93. {
  94. base.Initialize();
  95. InitializeParameter();
  96. InitializeRoutine();
  97. SubscribeValueAction();
  98. SubscribeData();
  99. return true;
  100. }
  101. /// <summary>
  102. /// 初始化参数
  103. /// </summary>
  104. private void InitializeParameter()
  105. {
  106. _persistentValue = MetalPersistentManager.Instance.GetMetalPersistentValue(Module);
  107. if (_persistentValue == null)
  108. {
  109. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Persistent Value Object is not exist");
  110. }
  111. MetalItem metalItem = MetalItemManager.Instance.GetMetalItem(Module);
  112. if (metalItem != null && metalItem.DepPump)
  113. {
  114. _isSignalPump = true;
  115. }
  116. }
  117. /// <summary>
  118. /// 初始化Routine
  119. /// </summary>
  120. private void InitializeRoutine()
  121. {
  122. _cellPumpRoutine = new StandardHotMetalCellPumpRoutine(Module.ToString());
  123. }
  124. /// <summary>
  125. /// 订阅数据
  126. /// </summary>
  127. private void SubscribeData()
  128. {
  129. DATA.Subscribe($"{Module}.MetalData", () => _metalDeviceData, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  130. DATA.Subscribe($"{Module}.CellPumpEnable", () => _metalDeviceData.CellPump, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  131. DATA.Subscribe($"{Module}.WaferShuttleClamped", () => _metalDeviceData.WaferHolderClamp, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  132. DATA.Subscribe($"{Module}.CellFlow", () => _metalDeviceData.CellFlow, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  133. DATA.Subscribe($"{Module}.Circulation", () => _metalDeviceData.Circulation, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  134. DATA.Subscribe($"{Module}.IsSingalPump", () => _isSignalPump, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  135. }
  136. /// <summary>
  137. /// 订阅变量数值发生变化
  138. /// </summary>
  139. private void SubscribeValueAction()
  140. {
  141. BeckhoffIoSubscribeUpdateVariable(CELL_PUMP);
  142. BeckhoffIoSubscribeUpdateVariable(CELL_FLOW);
  143. BeckhoffIoSubscribeUpdateVariable(WH_CLAMP);
  144. BeckhoffIoSubscribeUpdateVariable(CIRCULATION);
  145. }
  146. /// <summary>
  147. /// 订阅Operation
  148. /// </summary>
  149. protected override void InitializeOperation()
  150. {
  151. base.InitializeOperation();
  152. OP.Subscribe($"{Module}.PumpEnable", OpenPump);
  153. OP.Subscribe($"{Module}.PumpDisable", ClosePump);
  154. OP.Subscribe($"{Module}.CellSwitchToBypass", (cmd, args) => { return SwitchToBypass(cmd, args); });
  155. OP.Subscribe($"{Module}.CellSwitchToFlow", (cmd, args) => { return SwitchToFlow(cmd, args); });
  156. OP.Subscribe($"{Module}.ClampOn", (cmd, args) => { return WaferHolderClampOn(cmd, args); });
  157. OP.Subscribe($"{Module}.ClampOff", (cmd, args) => { return WaferHolderClampOff(cmd, args); });
  158. OP.Subscribe($"{Module}.WaferHolderClampOn", (cmd, args) => { return WaferHolderClampOn(cmd, args); });
  159. OP.Subscribe($"{Module}.WaferHolderUnclampOn", (cmd, args) => { return WaferHolderClampOff(cmd, args); });
  160. }
  161. /// <summary>
  162. /// 订阅IO变量
  163. /// </summary>
  164. /// <param name="variable"></param>
  165. private void BeckhoffIoSubscribeUpdateVariable(string variable)
  166. {
  167. _variableInitializeDic[variable] = false;
  168. IOModuleManager.Instance.SubscribeModuleVariable(Module, variable, UpdateVariableValue);
  169. }
  170. /// <summary>
  171. /// 更新变量数值
  172. /// </summary>
  173. /// <param name="variable"></param>
  174. /// <param name="value"></param>
  175. private void UpdateVariableValue(string variable, object value)
  176. {
  177. if (!_metalDeviceData.IsDataInitialized)
  178. {
  179. _metalDeviceData.IsDataInitialized = true;
  180. }
  181. PropertyInfo property = _metalDeviceData.GetType().GetProperty(variable);
  182. if (property != null)
  183. {
  184. property.SetValue(_metalDeviceData, value);
  185. }
  186. if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable])
  187. {
  188. _variableInitializeDic[variable] = true;
  189. }
  190. if (variable == CIRCULATION)
  191. {
  192. bool bValue = (bool)value;
  193. if (bValue)
  194. {
  195. _flowValveStopWatch.Restart();
  196. }
  197. }
  198. }
  199. public bool OpenPump(string cmd, Object[] args)
  200. {
  201. bool result = false;
  202. result = PumpOnOperation(cmd, args);
  203. return result;
  204. }
  205. public bool ClosePump(string cmd, Object[] args)
  206. {
  207. bool result = false;
  208. result = PumpOffOperation(cmd, args);
  209. return result;
  210. }
  211. #region CellPump
  212. /// <summary>
  213. /// Cell Pump On操作
  214. /// </summary>
  215. /// <param name="cmd"></param>
  216. /// <param name="param"></param>
  217. /// <returns></returns>
  218. public bool PumpOnOperation(string cmd, object[] param)
  219. {
  220. if (_status == RState.Running)
  221. {
  222. LOG.WriteLog(eEvent.ERR_METAL, Module.ToString(), $"{Module} current execute {_currentOperation},cannot Pump On");
  223. return false;
  224. }
  225. _status = _cellPumpRoutine.Start(true);
  226. _currentOperation = MetalOperation.CellPumpOn;
  227. return _status == RState.Running;
  228. }
  229. /// <summary>
  230. /// Cell Pump Off操作
  231. /// </summary>
  232. /// <param name="cmd"></param>
  233. /// <param name="param"></param>
  234. /// <returns></returns>
  235. public bool PumpOffOperation(string cmd, object[] param)
  236. {
  237. return PumpOff();
  238. }
  239. /// <summary>
  240. /// Pump Off
  241. /// </summary>
  242. /// <returns></returns>
  243. public bool PumpOff()
  244. {
  245. if (_status == RState.Running && _currentOperation == MetalOperation.CellPumpOn)
  246. {
  247. IRoutine routine = GetCurrentRoutine();
  248. if (routine != null)
  249. {
  250. routine.Abort();
  251. }
  252. }
  253. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CELL_PUMP}");
  254. return IOModuleManager.Instance.WriteIoValue(ioName, false);
  255. }
  256. #endregion
  257. #region WaferHolderClampOn
  258. /// <summary>
  259. /// Wafer Holder Clamp On
  260. /// </summary>
  261. /// <param name="cmd"></param>
  262. /// <param name="param"></param>
  263. /// <returns></returns>
  264. public bool WaferHolderClampOn(string cmd, object[] param)
  265. {
  266. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_CLAMP}");
  267. return IOModuleManager.Instance.WriteIoValue(ioName, true);
  268. }
  269. #endregion
  270. #region WaferHolderClampOff
  271. /// <summary>
  272. /// Wafer Holder Clamp On
  273. /// </summary>
  274. /// <param name="cmd"></param>
  275. /// <param name="param"></param>
  276. /// <returns></returns>
  277. public bool WaferHolderClampOff(string cmd, object[] param)
  278. {
  279. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_CLAMP}");
  280. return IOModuleManager.Instance.WriteIoValue(ioName, false);
  281. }
  282. #endregion
  283. #region circulation
  284. /// <summary>
  285. /// 切换至Bypass
  286. /// </summary>
  287. /// <returns></returns>
  288. public bool SwitchToBypass(string cmd, object[] param)
  289. {
  290. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CIRCULATION}");
  291. return IOModuleManager.Instance.WriteIoValue(ioName, false);
  292. }
  293. /// <summary>
  294. /// 切换至Flow
  295. /// </summary>
  296. /// <returns></returns>
  297. public bool SwitchToFlow(string cmd, object[] param)
  298. {
  299. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CIRCULATION}");
  300. return IOModuleManager.Instance.WriteIoValue(ioName, true);
  301. }
  302. #endregion
  303. /// <summary>
  304. /// Enter Disabled Operation
  305. /// </summary>
  306. /// <returns></returns>
  307. public void EnterDisabledOperation()
  308. {
  309. if (_metalDeviceData.CellPump)
  310. {
  311. ClosePump("", null);
  312. }
  313. }
  314. /// <summary>
  315. /// 定时器
  316. /// </summary>
  317. /// <returns></returns>
  318. public override bool OnTimer(int interval)
  319. {
  320. if (_status == RState.Running)
  321. {
  322. IRoutine routine = GetCurrentRoutine();
  323. if (routine != null)
  324. {
  325. RState rsState = routine.Monitor();
  326. if (rsState == RState.Failed || rsState == RState.Timeout)
  327. {
  328. _status = RState.Failed;
  329. ClosePump("", null);
  330. _currentOperation = MetalOperation.None;
  331. }
  332. else if (rsState == RState.End)
  333. {
  334. _status = RState.End;
  335. _currentOperation = MetalOperation.None;
  336. }
  337. }
  338. }
  339. return true;
  340. }
  341. /// <summary>
  342. /// 当前Routine;
  343. /// </summary>
  344. /// <returns></returns>
  345. private IRoutine GetCurrentRoutine()
  346. {
  347. switch (_currentOperation)
  348. {
  349. case MetalOperation.CellPumpOn:
  350. return _cellPumpRoutine;
  351. default:
  352. return null;
  353. }
  354. }
  355. #region 设备接口
  356. public override void Monitor()
  357. {
  358. }
  359. public override void Reset()
  360. {
  361. }
  362. public override void Terminate()
  363. {
  364. }
  365. #endregion
  366. }
  367. }