IoThrottleValve.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. using System;
  2. using System.Xml;
  3. using Aitex.Core.Common.DeviceData;
  4. using Aitex.Core.RT.DataCenter;
  5. using Aitex.Core.RT.Device;
  6. using Aitex.Core.RT.Event;
  7. using Aitex.Core.RT.IOCore;
  8. using Aitex.Core.RT.Log;
  9. using Aitex.Core.RT.OperationCenter;
  10. using Aitex.Core.RT.SCCore;
  11. using Aitex.Core.Util;
  12. namespace VirgoRT.Devices
  13. {
  14. public class IoThrottleValve : BaseDevice, IDevice
  15. {
  16. public struct Context
  17. {
  18. public string tvName;
  19. public string aoPressureModeName;
  20. public string aoPressureSetPointName;
  21. public string aoPositionSetPointName;
  22. public string aiPressureFeedbackName;
  23. public string aiPositionFeedbackName;
  24. public string aiStateName;
  25. };
  26. public PressureCtrlMode PressureMode
  27. {
  28. get
  29. {
  30. if (_aoPressureMode == null)
  31. return PressureCtrlMode.TVPositionCtrl;
  32. byte[] high = BitConverter.GetBytes(_aoPositionSetPoint.Buffer[_aoPressureMode.Index]);
  33. byte[] low = BitConverter.GetBytes(_aoPositionSetPoint.Buffer[_aoPressureMode.Index + 1]);
  34. float _pressureMode = BitConverter.ToSingle(new[] { high[0], high[1], low[0], low[1] }, 0);
  35. return Math.Abs(_pressureMode - 2) < 0.1 ? PressureCtrlMode.TVPositionCtrl : PressureCtrlMode.TVPressureCtrl;
  36. }
  37. set
  38. {
  39. if (_aoPositionSetPoint == null || _aoPressureSetPoint == null || _aoPressureMode == null)
  40. return;
  41. short setpoint = (short)(value == PressureCtrlMode.TVPositionCtrl ? 2 : 1);
  42. byte[] high = BitConverter.GetBytes(_aoPositionSetPoint.Buffer[_aoPressureMode.Index]);
  43. byte[] low = BitConverter.GetBytes(_aoPositionSetPoint.Buffer[_aoPressureMode.Index + 1]);
  44. float _pressureMode = BitConverter.ToSingle(new[] { high[0], high[1], low[0], low[1] }, 0);
  45. if (Math.Abs(_pressureMode - setpoint) > 0.01)
  46. {
  47. if (value == PressureCtrlMode.TVPositionCtrl)
  48. {
  49. //_aoPositionSetPoint.Value = PositionFeedback;
  50. byte[] _position = BitConverter.GetBytes(PositionFeedback);
  51. _aoPositionSetPoint.Buffer[_aoPositionSetPoint.Index] = BitConverter.ToInt16(_position, 0);
  52. _aoPositionSetPoint.Buffer[_aoPositionSetPoint.Index + 1] = BitConverter.ToInt16(_position, 2);
  53. }
  54. else
  55. {
  56. //_aoPressureSetPoint.Value = PressureFeedback;
  57. byte[] _pressure = BitConverter.GetBytes(PressureFeedback);
  58. _aoPressureSetPoint.Buffer[_aoPressureSetPoint.Index] = BitConverter.ToInt16(_pressure, 0);
  59. _aoPressureSetPoint.Buffer[_aoPressureSetPoint.Index + 1] = BitConverter.ToInt16(_pressure, 2);
  60. }
  61. //_aoPressureMode.Value = setpoint;
  62. byte[] flow = BitConverter.GetBytes((float)setpoint);
  63. _aoPressureMode.Buffer[_aoPressureMode.Index] = BitConverter.ToInt16(flow, 0);
  64. _aoPressureMode.Buffer[_aoPressureMode.Index + 1] = BitConverter.ToInt16(flow, 2);
  65. }
  66. }
  67. }
  68. public int State => _aiState == null ? 1 : (int)_aiState.Value;
  69. [Subscription("ProcessPressureOffset")]
  70. public double ProcessPressureOffset
  71. {
  72. get
  73. {
  74. if (_scProcessPressureOffset != null)
  75. return _scProcessPressureOffset.DoubleValue;
  76. return 0;
  77. }
  78. }
  79. [Subscription(AITThrottleValvePropertyName.TVPositionSetPoint)]
  80. public float PositionSetpoint
  81. {
  82. get
  83. {
  84. if (_aoPositionSetPoint != null)
  85. {
  86. byte[] high = BitConverter.GetBytes(_aoPositionSetPoint.Buffer[_aoPositionSetPoint.Index]);
  87. byte[] low = BitConverter.GetBytes(_aoPositionSetPoint.Buffer[_aoPositionSetPoint.Index + 1]);
  88. float flow = BitConverter.ToSingle(new[] { high[0], high[1], low[0], low[1] }, 0);
  89. return flow;
  90. }
  91. return 0;
  92. }
  93. set
  94. {
  95. if (_aoPositionSetPoint != null)
  96. {
  97. byte[] flow = BitConverter.GetBytes(value);
  98. _aoPositionSetPoint.Buffer[_aoPositionSetPoint.Index] = BitConverter.ToInt16(flow, 0);
  99. _aoPositionSetPoint.Buffer[_aoPositionSetPoint.Index + 1] = BitConverter.ToInt16(flow, 2);
  100. }
  101. }
  102. }
  103. [Subscription(AITThrottleValvePropertyName.TVPosition)]
  104. public float PositionFeedback //=> _aiPositionFeedback?.Value ?? 0;
  105. {
  106. get
  107. {
  108. if (_aiPositionFeedback != null)
  109. {
  110. byte[] high = BitConverter.GetBytes(_aiPositionFeedback.Buffer[_aiPositionFeedback.Index]);
  111. byte[] low = BitConverter.GetBytes(_aiPositionFeedback.Buffer[_aiPositionFeedback.Index + 1]);
  112. float flow = BitConverter.ToSingle(new[] { high[0], high[1], low[0], low[1] }, 0);
  113. return flow;
  114. }
  115. return 0;
  116. }
  117. }
  118. [Subscription(AITThrottleValvePropertyName.TVPressureSetPoint)]
  119. public float PressureSetpoint
  120. {
  121. get
  122. {
  123. if (_aoPressureSetPoint != null)
  124. {
  125. byte[] high = BitConverter.GetBytes(_aoPressureSetPoint.Buffer[_aoPressureSetPoint.Index]);
  126. byte[] low = BitConverter.GetBytes(_aoPressureSetPoint.Buffer[_aoPressureSetPoint.Index + 1]);
  127. float flow = BitConverter.ToSingle(new[] { high[0], high[1], low[0], low[1] }, 0);
  128. return flow;
  129. }
  130. return 0;
  131. }
  132. set
  133. {
  134. if (_aoPressureSetPoint != null)
  135. {
  136. byte[] flow = BitConverter.GetBytes(value);
  137. _aoPressureSetPoint.Buffer[_aoPressureSetPoint.Index] = BitConverter.ToInt16(flow, 0);
  138. _aoPressureSetPoint.Buffer[_aoPressureSetPoint.Index + 1] = BitConverter.ToInt16(flow, 2);
  139. }
  140. }
  141. }
  142. [Subscription(AITThrottleValvePropertyName.TVPressure)]
  143. public float PressureFeedback //=> _aiPressureFeedback?.Value ?? 0;
  144. {
  145. get
  146. {
  147. if (_aiPressureFeedback != null)
  148. {
  149. byte[] high = BitConverter.GetBytes(_aiPressureFeedback.Buffer[_aiPressureFeedback.Index]);
  150. byte[] low = BitConverter.GetBytes(_aiPressureFeedback.Buffer[_aiPressureFeedback.Index + 1]);
  151. float flow = BitConverter.ToSingle(new[] { high[0], high[1], low[0], low[1] }, 0);
  152. return flow;
  153. }
  154. return 0;
  155. }
  156. }
  157. public bool IsIndependent { get; set; }
  158. public bool IsOffline => _diOffline != null && _diOffline.RawData;
  159. private readonly DIAccessor _diOffline;
  160. private readonly AIAccessor _aiPressureFeedback;
  161. private readonly AIAccessor _aiPositionFeedback;
  162. private readonly AOAccessor _aoPressureSetPoint;
  163. private readonly AOAccessor _aoPositionSetPoint;
  164. private readonly AOAccessor _aoPressureMode;
  165. private readonly AIAccessor _aiState;
  166. private SCConfigItem _scProcessPressureOffset;
  167. private readonly R_TRIG _tvStatusAlmTrig = new R_TRIG();
  168. private readonly R_TRIG _trigOffline = new R_TRIG();
  169. public IoThrottleValve(string module, XmlElement node, string ioModule = "")
  170. {
  171. base.Module = module;
  172. base.Name = node.GetAttribute("id");
  173. base.Display = node.GetAttribute("display");
  174. base.DeviceID = node.GetAttribute("schematicId");
  175. _aiPositionFeedback = ParseAiNode("aiPositionFeedback", node, ioModule);
  176. _aiPressureFeedback = ParseAiNode("aiPressureFeedback", node, ioModule);
  177. _aoPositionSetPoint = ParseAoNode("aoPositionSetPoint", node, ioModule);
  178. _aoPressureSetPoint = ParseAoNode("aoPressureSetPoint", node, ioModule);
  179. _aiState = ParseAiNode("aiState", node, ioModule);
  180. _aoPressureMode = ParseAoNode("aoPressureMode", node, ioModule);
  181. _diOffline = ParseDiNode("diOffline", node, ioModule);
  182. _scProcessPressureOffset = SC.GetConfigItem($"{Module}.ProcessPressureOffset");
  183. }
  184. public bool Initialize()
  185. {
  186. DATA.Subscribe($"{Module}.{Name}", Getter, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  187. PressureMode = PressureCtrlMode.TVPressureCtrl;
  188. DEVICE.Register($"{Module}.{Name}.{AITThrottleValveOperation.SetMode}", _setMode);
  189. DEVICE.Register($"{Module}.{Name}.{AITThrottleValveOperation.SetPosition}", _setPosition);
  190. DEVICE.Register($"{Module}.{Name}.{AITThrottleValveOperation.SetPressure}", _setPressure);
  191. OP.Subscribe($"{Module}.{Name}.{AITThrottleValveOperation.SetMode}", _setMode2);
  192. OP.Subscribe($"{Module}.{Name}.{AITThrottleValveOperation.SetPressure}", _setPressure2);
  193. OP.Subscribe($"{Module}.{Name}.{AITThrottleValveOperation.SetPosition}", _setPosition2);
  194. return true;
  195. }
  196. private bool _setPosition2(string arg1, object[] arg2)
  197. {
  198. return this._setPosition(out string str1, 0, arg2).Value;
  199. }
  200. private bool _setMode2(string arg1, object[] arg2)
  201. {
  202. return this._setMode(out string str, 0, arg2).Value;
  203. }
  204. private bool _setPressure2(string arg1, object[] arg2)
  205. {
  206. return this._setPressure(out string str, 0, arg2).Value;
  207. }
  208. private bool? _setPressure(out string reason, int time, object[] param)
  209. {
  210. PressureMode = PressureCtrlMode.TVPressureCtrl;
  211. //double target = Convert.ToDouble((string) param[0]);
  212. double target = (double)param[0];
  213. PositionSetpoint = 0.0f;
  214. PressureSetpoint = (float)target - (float)ProcessPressureOffset;
  215. reason = $"pressure set {target} mTorr";
  216. return true;
  217. }
  218. private bool? _setPosition(out string reason, int time, object[] param)
  219. {
  220. //double target = Convert.ToDouble((string) param[0]);
  221. double target = (double)param[0];
  222. PressureMode = PressureCtrlMode.TVPositionCtrl;
  223. PositionSetpoint = (short) target;
  224. PressureSetpoint = 0.0f;
  225. reason = $"position set to {target:F1}%";
  226. return true;
  227. }
  228. private bool? _setMode(out string reason, int time, object[] param)
  229. {
  230. PressureMode = (PressureCtrlMode) Enum.Parse(typeof(PressureCtrlMode), (string) param[0], true);
  231. reason = $"Throttle valve set to {PressureMode} mode";
  232. return true;
  233. }
  234. private object Getter()
  235. {
  236. AITThrottleValveData data = new AITThrottleValveData()
  237. {
  238. Module = Module,
  239. DeviceName = Name,
  240. DeviceSchematicId = DeviceID,
  241. DisplayName = Display,
  242. Mode = (int) PressureMode,
  243. PositionFeedback = PositionFeedback,
  244. PositionSetPoint = PositionSetpoint,
  245. PressureFeedback = PressureFeedback,
  246. PressureSetPoint = PressureSetpoint,
  247. State = State,
  248. };
  249. return data;
  250. }
  251. public void Terminate()
  252. {
  253. }
  254. public void Monitor()
  255. {
  256. try
  257. {
  258. _tvStatusAlmTrig.CLK = State != 1;
  259. if (_tvStatusAlmTrig.Q)
  260. {
  261. EV.PostAlarmLog(Module, "蝶阀工作状态异常");
  262. }
  263. _trigOffline.CLK = IsOffline;
  264. if (_trigOffline.Q)
  265. {
  266. EV.PostAlarmLog(Module, "蝶阀离线");
  267. }
  268. }
  269. catch (Exception ex)
  270. {
  271. LOG.Write(ex);
  272. throw ex;
  273. }
  274. }
  275. public void Reset()
  276. {
  277. _tvStatusAlmTrig.RST = true;
  278. _trigOffline.RST = true;
  279. }
  280. public void SetPositionMode(int position)
  281. {
  282. PressureMode = PressureCtrlMode.TVPositionCtrl;
  283. PositionSetpoint = (short)position;
  284. }
  285. }
  286. }