IoMfc.cs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. using System;
  2. using System.Xml;
  3. using Aitex.Core.Common.DeviceData;
  4. using Aitex.Core.RT.DataCenter;
  5. using Aitex.Core.RT.Event;
  6. using Aitex.Core.RT.IOCore;
  7. using Aitex.Core.RT.SCCore;
  8. using Aitex.Core.RT.Tolerance;
  9. using Aitex.Core.Util;
  10. namespace Aitex.Core.RT.Device.Unit
  11. {
  12. public class IoMfc : BaseDevice, IDevice
  13. {
  14. public string Unit
  15. {
  16. get; set;
  17. }
  18. [Subscription(AITMfcDataPropertyName.Scale)]
  19. public double Scale
  20. {
  21. get
  22. {
  23. if (_scN2Scale == null || _scScaleFactor == null)
  24. return 0;
  25. return _scN2Scale.Value * _scScaleFactor.Value;
  26. }
  27. }
  28. [Subscription(AITMfcDataPropertyName.SetPoint)]
  29. public double SetPoint
  30. {
  31. get
  32. {
  33. if (_aoFlow != null)
  34. {
  35. return _aoFlow.Value;
  36. }
  37. return 0;
  38. }
  39. set
  40. {
  41. if (_aoFlow != null)
  42. {
  43. _aoFlow.Value = (float)value;
  44. }
  45. }
  46. }
  47. [Subscription(AITMfcDataPropertyName.DefaultSetPoint)]
  48. public double DefaultSetPoint
  49. {
  50. get
  51. {
  52. if (_scDefaultSetPoint != null)
  53. return _scDefaultSetPoint.Value;
  54. return 0;
  55. }
  56. }
  57. [Subscription(AITMfcDataPropertyName.FeedBack)]
  58. public double FeedBack
  59. {
  60. get
  61. {
  62. if (_aiFlow != null)
  63. return (_scRegulationFactor != null && _scRegulationFactor.Value > 0) ? _aiFlow.Value / _scRegulationFactor.Value : _aiFlow.Value;
  64. return 0;
  65. }
  66. }
  67. [Subscription(AITMfcDataPropertyName.IsOutOfTolerance)]
  68. public bool IsOutOfTolerance
  69. {
  70. get
  71. {
  72. return _toleranceChecker.Result;
  73. }
  74. }
  75. [Subscription(AITMfcDataPropertyName.IsEnableAlarm)]
  76. public bool EnableAlarm
  77. {
  78. get
  79. {
  80. if (_scEnableAlarm != null)
  81. return _scEnableAlarm.Value;
  82. return false;
  83. }
  84. }
  85. [Subscription(AITMfcDataPropertyName.AlarmRange)]
  86. public double AlarmRange
  87. {
  88. get
  89. {
  90. if (_scAlarmRange != null)
  91. return _scAlarmRange.Value;
  92. return 0;
  93. }
  94. }
  95. [Subscription(AITMfcDataPropertyName.AlarmTime)]
  96. public double AlarmTime
  97. {
  98. get
  99. {
  100. if (_scAlarmTime != null)
  101. return _scAlarmTime.Value;
  102. return 0;
  103. }
  104. }
  105. [Subscription(AITMfcDataPropertyName.IsOffline)]
  106. public bool IsOffline
  107. {
  108. get
  109. {
  110. if (_diOffline != null)
  111. return _diOffline.Value;
  112. return false;
  113. }
  114. }
  115. public string DisplayName
  116. {
  117. get
  118. {
  119. if (_scGasName != null)
  120. return _scGasName.Value;
  121. return Display;
  122. }
  123. }
  124. private DeviceTimer rampTimer = new DeviceTimer();
  125. private double rampTarget;
  126. private double rampInitValue;
  127. private int rampTime;
  128. private ToleranceChecker _toleranceChecker = new ToleranceChecker();
  129. private AIAccessor _aiFlow;
  130. private AOAccessor _aoFlow;
  131. private AOAccessor _aoRange;
  132. private DIAccessor _diOffline;
  133. private SCString _scGasName;
  134. private SCItem<bool> _scEnable;
  135. private SCItem<double> _scN2Scale;
  136. private SCItem<double> _scScaleFactor;
  137. private SCItem<double> _scAlarmRange;
  138. private SCItem<bool> _scEnableAlarm;
  139. private SCItem<double> _scAlarmTime;
  140. private SCItem<double> _scDefaultSetPoint;
  141. private SCItem<double> _scRegulationFactor;
  142. private R_TRIG _trigOffline = new R_TRIG();
  143. public IoMfc(string module, XmlElement node)
  144. {
  145. Unit = node.GetAttribute("unit");
  146. base.Module = module;
  147. base.Name = node.GetAttribute("id");
  148. base.Display = node.GetAttribute("display");
  149. base.DeviceID = node.GetAttribute("schematicId");
  150. _aoRange = ParseAoNode("aoRange", node);
  151. _diOffline = ParseDiNode("diOffline", node);
  152. _aiFlow = ParseAiNode("aiFlow", node);
  153. _aoFlow = ParseAoNode("aoFlow", node);
  154. _scGasName = ParseScNodeString("scGasName", node);
  155. _scEnable = ParseScNodeBool("scEnable", node);
  156. _scN2Scale = ParseScNodeDouble("scN2Scale", node);
  157. _scScaleFactor = ParseScNodeDouble("scScaleFactor", node);
  158. _scAlarmRange = ParseScNodeDouble("scAlarmRange", node);
  159. _scEnableAlarm = ParseScNodeBool("scEnableAlarm", node);
  160. _scAlarmTime = ParseScNodeDouble("scAlarmTime", node);
  161. _scDefaultSetPoint = ParseScNodeDouble("scDefaultSetPoint", node);
  162. _scRegulationFactor = ParseScNodeDouble("scFlowRegulationFactor", node);
  163. }
  164. public bool Initialize()
  165. {
  166. DATA.Subscribe(string.Format("Device.{0}.{1}", Module, Name), () =>
  167. {
  168. AITMfcData data = new AITMfcData()
  169. {
  170. Type = "MFC",
  171. DeviceName = Name,
  172. DeviceSchematicId = DeviceID,
  173. DisplayName = DisplayName,
  174. FeedBack = FeedBack,
  175. SetPoint = SetPoint,
  176. Scale = Scale,
  177. IsOffline = IsOffline,
  178. };
  179. return data;
  180. }, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  181. DEVICE.Register($"{Name}.{AITMfcOperation.Ramp}", (out string reason, int time, object[] param) =>
  182. {
  183. double target = Convert.ToDouble((string)param[0]);
  184. target = Math.Min(target, Scale);
  185. target = Math.Max(target, 0);
  186. Ramp(target, time);
  187. reason = string.Format("{0} ramp to {1}{2}", Display, target, Unit);
  188. return true;
  189. });
  190. //@AAA use recipe
  191. DEVICE.Register($"{Name}", (out string reason, int time, object[] param) =>
  192. {
  193. double target = Convert.ToDouble((string)param[0]);
  194. target = Math.Min(target, Scale);
  195. target = Math.Max(target, 0);
  196. Ramp(target, time);
  197. reason = string.Format("{0} ramp to {1}{2}", Display, target, Unit);
  198. return true;
  199. });
  200. return true;
  201. }
  202. public void Monitor()
  203. {
  204. Ramping();
  205. CheckTolerance();
  206. if (_aoRange != null)
  207. _aoRange.Value = (float)Scale;
  208. _trigOffline.CLK = IsOffline;
  209. if (_trigOffline.Q)
  210. {
  211. EV.PostMessage(Module, EventEnum.DefaultAlarm, string.Format("{0} is offline", DisplayName));
  212. }
  213. }
  214. public void Reset()
  215. {
  216. _toleranceChecker.Reset(AlarmTime);
  217. _trigOffline.RST = true;
  218. }
  219. public void Terminate()
  220. {
  221. Ramp(DefaultSetPoint, 0);
  222. }
  223. public void Ramp(int time)
  224. {
  225. Ramp(DefaultSetPoint, time);
  226. }
  227. public void Ramp(double target, int time)
  228. {
  229. target = Math.Max(0, target);
  230. target = Math.Min(Scale, target);
  231. rampInitValue = SetPoint; //ramp 初始值取当前设定值,而非实际读取值。零漂问题
  232. rampTime = time;
  233. rampTarget = target;
  234. rampTimer.Start(rampTime);
  235. }
  236. public void StopRamp()
  237. {
  238. Ramp(SetPoint, 0);
  239. }
  240. private void Ramping()
  241. {
  242. if (rampTimer.IsTimeout() || rampTime == 0)
  243. {
  244. SetPoint = rampTarget;
  245. }
  246. else
  247. {
  248. SetPoint = rampInitValue + (rampTarget - rampInitValue) * rampTimer.GetElapseTime() / rampTime;
  249. }
  250. }
  251. private void CheckTolerance()
  252. {
  253. if (!EnableAlarm)
  254. return;
  255. _toleranceChecker.Monitor(FeedBack, (SetPoint - Math.Abs(AlarmRange)), (SetPoint + Math.Abs(AlarmRange)), AlarmTime);
  256. if (_toleranceChecker.Trig)
  257. {
  258. EV.PostMessage(Module, EventEnum.ToleranceAlarm, Module, Display, $"Out of range in {AlarmTime.ToString("0")} seconds");
  259. }
  260. }
  261. }
  262. }