StandardHotMetalDevice.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  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. bool result = true;
  238. if (MetalDeviceData.CellPump)
  239. {
  240. result = PumpOff();
  241. }
  242. return result;
  243. //return PumpOff();
  244. }
  245. /// <summary>
  246. /// Pump Off
  247. /// </summary>
  248. /// <returns></returns>
  249. public bool PumpOff()
  250. {
  251. if (_status == RState.Running && _currentOperation == MetalOperation.CellPumpOn)
  252. {
  253. IRoutine routine = GetCurrentRoutine();
  254. if (routine != null)
  255. {
  256. routine.Abort();
  257. }
  258. }
  259. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CELL_PUMP}");
  260. return IOModuleManager.Instance.WriteIoValue(ioName, false);
  261. }
  262. #endregion
  263. #region WaferHolderClampOn
  264. /// <summary>
  265. /// Wafer Holder Clamp On
  266. /// </summary>
  267. /// <param name="cmd"></param>
  268. /// <param name="param"></param>
  269. /// <returns></returns>
  270. public bool WaferHolderClampOn(string cmd, object[] param)
  271. {
  272. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_CLAMP}");
  273. return IOModuleManager.Instance.WriteIoValue(ioName, true);
  274. }
  275. #endregion
  276. #region WaferHolderClampOff
  277. /// <summary>
  278. /// Wafer Holder Clamp On
  279. /// </summary>
  280. /// <param name="cmd"></param>
  281. /// <param name="param"></param>
  282. /// <returns></returns>
  283. public bool WaferHolderClampOff(string cmd, object[] param)
  284. {
  285. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_CLAMP}");
  286. return IOModuleManager.Instance.WriteIoValue(ioName, false);
  287. }
  288. #endregion
  289. #region circulation
  290. /// <summary>
  291. /// 切换至Bypass
  292. /// </summary>
  293. /// <returns></returns>
  294. public bool SwitchToBypass(string cmd, object[] param)
  295. {
  296. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CIRCULATION}");
  297. return IOModuleManager.Instance.WriteIoValue(ioName, false);
  298. }
  299. /// <summary>
  300. /// 切换至Flow
  301. /// </summary>
  302. /// <returns></returns>
  303. public bool SwitchToFlow(string cmd, object[] param)
  304. {
  305. string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CIRCULATION}");
  306. return IOModuleManager.Instance.WriteIoValue(ioName, true);
  307. }
  308. #endregion
  309. /// <summary>
  310. /// Enter Disabled Operation
  311. /// </summary>
  312. /// <returns></returns>
  313. public void EnterDisabledOperation()
  314. {
  315. if (_metalDeviceData.CellPump)
  316. {
  317. ClosePump("", null);
  318. }
  319. }
  320. /// <summary>
  321. /// 定时器
  322. /// </summary>
  323. /// <returns></returns>
  324. public override bool OnTimer(int interval)
  325. {
  326. if (_status == RState.Running)
  327. {
  328. IRoutine routine = GetCurrentRoutine();
  329. if (routine != null)
  330. {
  331. RState rsState = routine.Monitor();
  332. if (rsState == RState.Failed || rsState == RState.Timeout)
  333. {
  334. _status = RState.Failed;
  335. ClosePump("", null);
  336. _currentOperation = MetalOperation.None;
  337. }
  338. else if (rsState == RState.End)
  339. {
  340. _status = RState.End;
  341. _currentOperation = MetalOperation.None;
  342. }
  343. }
  344. }
  345. return true;
  346. }
  347. /// <summary>
  348. /// 当前Routine;
  349. /// </summary>
  350. /// <returns></returns>
  351. private IRoutine GetCurrentRoutine()
  352. {
  353. switch (_currentOperation)
  354. {
  355. case MetalOperation.CellPumpOn:
  356. return _cellPumpRoutine;
  357. default:
  358. return null;
  359. }
  360. }
  361. #region 设备接口
  362. public override void Monitor()
  363. {
  364. }
  365. public override void Reset()
  366. {
  367. }
  368. public override void Terminate()
  369. {
  370. }
  371. #endregion
  372. }
  373. }