IoHeater.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  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.RT.Tolerance;
  12. using Aitex.Core.Util;
  13. using VirgoRT.Annotations;
  14. namespace VirgoRT.Devices
  15. {
  16. public interface IoHeaterController
  17. {
  18. bool SetPowerOnOff(bool isOn);
  19. bool Ramp(float temp);
  20. float GetFeedback();
  21. float GetSetPoint();
  22. bool GetIsOn();
  23. }
  24. public class IoHeater : BaseDevice, IDevice
  25. {
  26. public IoHeaterController Controller { get; set; }
  27. public double SetPointLimit
  28. {
  29. get
  30. {
  31. if (_aoSetPointLimit != null)
  32. //return _aoSetPointLimit.Value;
  33. return _GetRealFloat(_aoSetPointLimit);
  34. return 100;
  35. }
  36. }
  37. [Subscription(AITHeaterPropertyName.CoolantInletTempFeedback)]
  38. public float CoolantInletTcFeedback
  39. {
  40. get
  41. {
  42. if (_aiCoolantInletTempFeedback == null) return -1;
  43. //return _aiMonitorTcFeedback.Value;
  44. return _GetRealFloat(_aiCoolantInletTempFeedback);
  45. }
  46. }
  47. [Subscription(AITHeaterPropertyName.CoolantOutletTempFeedback)]
  48. public float CoolantOutletTcFeedback
  49. {
  50. get
  51. {
  52. if (_aiCoolantOutletTempFeedback == null) return -1;
  53. //return _aiMonitorTcFeedback.Value;
  54. return _GetRealFloat(_aiCoolantOutletTempFeedback);
  55. }
  56. }
  57. [Subscription(AITHeaterPropertyName.MonitorTcFeedback)]
  58. public float MonitorTcFeedback
  59. {
  60. get
  61. {
  62. if (_aiMonitorTcFeedback == null) return -1;
  63. //return _aiMonitorTcFeedback.Value;
  64. return _GetRealFloat(_aiMonitorTcFeedback);
  65. }
  66. }
  67. [Subscription(AITHeaterPropertyName.ControlTcFeedback)]
  68. public float ControlTcFeedback
  69. {
  70. get
  71. {
  72. if (Name == "ForelineHeater")
  73. {
  74. if (_aiControlTcFeedback == null) return -1;
  75. return _GetRealFloat(_aiControlTcFeedback);
  76. }
  77. if (_aiControlTcFeedback == null) return -1;
  78. float real = _GetRealFloat(_aiControlTcFeedback);
  79. return real - GetHeaterOffsetSetting(real - _offset);
  80. //return ((real - GetHeaterOffsetSetting(real - _offset)) >= ControlTcSetPoint - _offset) ? (real - _offset) : (real - GetHeaterOffsetSetting(real - _offset));
  81. }
  82. }
  83. [Subscription(AITHeaterPropertyName.ControlTcSetPoint)]
  84. public float ControlTcSetPoint
  85. {
  86. get
  87. {
  88. if (_aoSetPoint != null)
  89. //return _aoSetPoint.Value;
  90. return _GetRealFloat(_aoSetPoint);
  91. if (Controller != null)
  92. return Controller.GetSetPoint();
  93. return 0;
  94. }
  95. private set
  96. {
  97. if (_aoSetPoint != null)
  98. {
  99. //_aoSetPoint.Value = (short)setpoint;
  100. _SetRealFloat(_aoSetPoint, value);
  101. }
  102. }
  103. }
  104. [Subscription(AITHeaterPropertyName.IsMonitorTcBroken)]
  105. public bool IsMonitorTcBroken
  106. {
  107. get
  108. {
  109. if (_diMonitorTcBroken != null)
  110. return _diMonitorTcBroken.Value;
  111. return false;
  112. }
  113. }
  114. [Subscription(AITHeaterPropertyName.IsTcDeviation)]
  115. public bool IsTcDeviation
  116. {
  117. get
  118. {
  119. if (_diDeviation != null)
  120. return _diDeviation.Value;
  121. return false;
  122. }
  123. }
  124. [Subscription(AITHeaterPropertyName.IsControlTcBroken)]
  125. public bool IsControlTcBroken
  126. {
  127. get
  128. {
  129. if (_diControlTcBroken != null)
  130. return _diControlTcBroken.Value;
  131. return false;
  132. }
  133. }
  134. [Subscription(AITHeaterPropertyName.IsPowerOnFeedback)]
  135. public bool IsPowerOnFeedback
  136. {
  137. get
  138. {
  139. if (Controller!=null)
  140. {
  141. return Controller.GetIsOn();
  142. }
  143. if (_diPowerOnFeedback != null)
  144. return _diPowerOnFeedback.Value;
  145. if (_doPowerOn != null)
  146. return _doPowerOn.Value;
  147. return false;
  148. }
  149. }
  150. [Subscription(AITHeaterPropertyName.ControlTcSetPointView)]
  151. public float ControlTcSetPointView
  152. {
  153. get
  154. {
  155. return _controlTcSetPointView;
  156. }
  157. }
  158. [Subscription(AITHeaterPropertyName.IsPowerOnSetPoint)]
  159. public bool IsPowerOnSetPoint
  160. {
  161. get
  162. {
  163. if (_doPowerOn != null)
  164. return _doPowerOn.Value;
  165. return false;
  166. }
  167. }
  168. public string Unit { get; set; }
  169. //private int _stage = 0;
  170. private float _controlTcSetPointView = 0f;
  171. //private int _stageSet = 0;
  172. private float _offset = 0f;
  173. //private float _offsetSet = 0f;
  174. private readonly DIAccessor _diPowerOnFeedback;
  175. private readonly DIAccessor _diControlTcBroken;
  176. private readonly DIAccessor _diMonitorTcBroken;
  177. private readonly DIAccessor _diDeviation;
  178. private readonly DOAccessor _doPowerOn;
  179. private readonly AIAccessor _aiControlTcFeedback;
  180. private readonly AIAccessor _aiMonitorTcFeedback;
  181. private readonly AIAccessor _aiCoolantInletTempFeedback;
  182. private readonly AIAccessor _aiCoolantOutletTempFeedback;
  183. private readonly AOAccessor _aoSetPoint;
  184. private AOAccessor _aoSetPointLimit;
  185. private readonly SCConfigItem _scSetPointLimit;
  186. private readonly R_TRIG _trigMonitorTcBroken = new R_TRIG();
  187. private readonly R_TRIG _trigControlTcBroken = new R_TRIG();
  188. private readonly R_TRIG _trigDeviation = new R_TRIG();
  189. private SCConfigItem _scEnableToleranceCheck;
  190. private SCConfigItem _scDeviationAlarmRange;
  191. private SCConfigItem _scDeviationAlarmTime;
  192. private SCConfigItem _scDeviationWarningRange;
  193. private SCConfigItem _scDeviationWarningTime;
  194. private DeviceTimer _timerAlarm = new DeviceTimer();
  195. private DeviceTimer _timerWarning = new DeviceTimer();
  196. private readonly R_TRIG _trigWarning = new R_TRIG();
  197. private readonly R_TRIG _trigAlarm = new R_TRIG();
  198. private ToleranceChecker _checkerWarning = new ToleranceChecker();
  199. private ToleranceChecker _checkerAlarm = new ToleranceChecker();
  200. private string HeaterDeviationAlarm = "HeaterDeviationAlarm";
  201. public IoHeater(string module, XmlElement node, string ioModule = "")
  202. {
  203. base.Module = module;
  204. base.Name = node.GetAttribute("id");
  205. base.Display = node.GetAttribute("display");
  206. base.DeviceID = node.GetAttribute("schematicId");
  207. Unit = node.GetAttribute("unit");
  208. _diPowerOnFeedback = ParseDiNode("diPowerOnFeedback", node, ioModule);
  209. _diControlTcBroken = ParseDiNode("diControlTcBroken", node, ioModule);
  210. _diMonitorTcBroken = ParseDiNode("diMonitorTcBroken", node, ioModule);
  211. _doPowerOn = ParseDoNode("doPowerOn", node, ioModule);
  212. _diDeviation = ParseDiNode("diDeviation", node, ioModule);
  213. _aiControlTcFeedback = ParseAiNode("aiFeedback", node, ioModule);
  214. _aiMonitorTcFeedback = ParseAiNode("aiMonitor", node, ioModule);
  215. _aiCoolantInletTempFeedback = ParseAiNode("aiCoolantInletTemp", node, ioModule);
  216. _aiCoolantOutletTempFeedback = ParseAiNode("aiCoolantOutletTemp", node, ioModule);
  217. _aoSetPoint = ParseAoNode("aoSetPoint", node, ioModule);
  218. _aoSetPointLimit = ParseAoNode("aoSetPointLimit", node, ioModule);
  219. _scSetPointLimit = ParseScNodeEx("scSetPointLimit", node, ioModule);
  220. }
  221. //public void UpdateConfig(double setPointLimit)
  222. //{
  223. // if (_aoSetPointLimit != null)
  224. // _aoSetPointLimit.Value = (short)setPointLimit;
  225. //}
  226. public bool Initialize()
  227. {
  228. DATA.Subscribe($"{Module}.{Name}.DeviceData", () =>
  229. {
  230. AITHeaterData data = new AITHeaterData()
  231. {
  232. Module = Module,
  233. DeviceName = Name,
  234. DeviceSchematicId = DeviceID,
  235. DisplayName = Display,
  236. FeedBack = ControlTcFeedback,
  237. MonitorTcFeedBack = MonitorTcFeedback,
  238. CoolantInletTcFeedback = CoolantInletTcFeedback,
  239. CoolantOutletTcFeedback = CoolantOutletTcFeedback,
  240. Scale = SetPointLimit,
  241. SetPoint = ControlTcSetPointView,
  242. IsPowerOn = IsPowerOnFeedback,
  243. IsPowerOnSetPoint = IsPowerOnSetPoint,
  244. IsControlTcBroken = IsControlTcBroken,
  245. IsMonitorTcBroken = IsMonitorTcBroken,
  246. Unit = Unit,
  247. IsTcDeviation = IsTcDeviation,
  248. };
  249. return data;
  250. }, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  251. DATA.Subscribe($"{Module}.{Name}.Temperature", () => ControlTcFeedback, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  252. OP.Subscribe($"{Module}.{Name}.{AITHeaterOperation.SetPowerOnOff}", (functionName, param) =>
  253. {
  254. bool isEnable = Convert.ToBoolean((string)param[0]);
  255. return this.TurnOnOff(isEnable);
  256. });
  257. OP.Subscribe($"{Module}.{Name}.{AITHeaterOperation.Ramp}", (functionName, param) =>
  258. {
  259. float setpoint = (float)Convert.ToDouble((string)param[0]);
  260. if (!RampTemp(setpoint)) return false;
  261. return true;
  262. });
  263. this.SetBySC(_aoSetPointLimit, _scSetPointLimit);
  264. _scEnableToleranceCheck = SC.GetConfigItem($"{Module}.{Name}.HeaterEnableTolerance");
  265. _scDeviationAlarmRange = SC.GetConfigItem($"{Module}.{Name}.HeaterAlarmRange");
  266. _scDeviationAlarmTime = SC.GetConfigItem($"{Module}.{Name}.HeaterAlarmTime");
  267. _scDeviationWarningRange = SC.GetConfigItem($"{Module}.{Name}.HeaterWarningRange");
  268. _scDeviationWarningTime = SC.GetConfigItem($"{Module}.{Name}.HeaterWarningTime");
  269. EV.Subscribe(new EventItem("Event", HeaterDeviationAlarm, "Heater Deviation Out of Tolerance", EventLevel.Alarm, EventType.HostNotification));
  270. return true;
  271. }
  272. public bool TurnOnOff(bool on)
  273. {
  274. if (Controller!=null)
  275. {
  276. Controller.SetPowerOnOff(on);
  277. return true;
  278. }
  279. if (!_doPowerOn.SetValue(on, out string reason))
  280. {
  281. EV.PostWarningLog(Module, reason);
  282. return false;
  283. }
  284. EV.PostInfoLog(Module, $"Set Heater {Name} Power {(on ? "ON" : "OFF")}");
  285. return true;
  286. }
  287. public bool RampTemp(float setpoint)
  288. {
  289. // 是否越界
  290. if (setpoint > SetPointLimit || setpoint < 0)
  291. {
  292. EV.PostAlarmLog(Module, $"{Name} 温度设定 {setpoint} 无效, 正确范围是 (0, {SetPointLimit})");
  293. return false;
  294. }
  295. if (setpoint == 0)
  296. {
  297. EV.PostInfoLog(Module, $"{Name} setpoint = {setpoint}, ignore temperature control");
  298. return true;
  299. }
  300. if (Controller != null)
  301. {
  302. return Controller.Ramp(setpoint);
  303. }
  304. _offset = GetHeaterOffsetSetting(setpoint);
  305. // offset 处理后的设定值
  306. _controlTcSetPointView = setpoint;
  307. if (Name == "ForelineHeater")
  308. ControlTcSetPoint = setpoint;
  309. else
  310. ControlTcSetPoint = setpoint + _offset;
  311. EV.PostInfoLog(Module, $"设定 {Display} 温度到 {setpoint}");
  312. return true;
  313. }
  314. public void Stop()
  315. {
  316. if (_aoSetPoint != null)
  317. {
  318. _aoSetPoint.Value = 0;
  319. }
  320. }
  321. public void Terminate()
  322. {
  323. }
  324. public void Monitor()
  325. {
  326. try
  327. {
  328. _trigControlTcBroken.CLK = IsControlTcBroken;
  329. if (_trigControlTcBroken.Q)
  330. {
  331. EV.PostWarningLog(Module, $"{Display}, Found control TC broken");
  332. }
  333. _trigMonitorTcBroken.CLK = IsMonitorTcBroken;
  334. if (_trigMonitorTcBroken.Q)
  335. {
  336. EV.PostWarningLog(Module, $"{Display}, Found monitor TC broken");
  337. }
  338. _trigDeviation.CLK = IsTcDeviation;
  339. if (_trigDeviation.Q)
  340. {
  341. EV.PostWarningLog(Module, $"{Display}, Found TC Deviation out of range");
  342. }
  343. this.SetBySC(_aoSetPointLimit, _scSetPointLimit);
  344. CheckDeviation();
  345. }
  346. catch (Exception ex)
  347. {
  348. LOG.Write(ex);
  349. }
  350. }
  351. private void CheckDeviation()
  352. {
  353. if (!_scEnableToleranceCheck.BoolValue)
  354. return;
  355. if (Controller != null && !Controller.GetIsOn())
  356. {
  357. return;
  358. }
  359. if (!IsPowerOnFeedback)
  360. return;
  361. _checkerWarning.Monitor(ControlTcFeedback, ControlTcSetPointView - Math.Abs(_scDeviationWarningRange.IntValue)
  362. , ControlTcSetPoint + Math.Abs(_scDeviationWarningRange.IntValue),_scDeviationWarningTime.IntValue);
  363. if (_checkerWarning.Trig)
  364. {
  365. EV.PostWarningLog(Module, $"{Name} temperature feedback deviation than {Math.Abs(_scDeviationWarningRange.IntValue)} from setpoint for {_scDeviationWarningTime.IntValue} seconds");
  366. }
  367. _checkerAlarm.Monitor(ControlTcFeedback, ControlTcSetPointView - Math.Abs(_scDeviationAlarmRange.IntValue)
  368. , ControlTcSetPoint + Math.Abs(_scDeviationAlarmRange.IntValue), _scDeviationAlarmTime.IntValue);
  369. if (_checkerAlarm.Trig)
  370. {
  371. EV.PostAlarmLog(Module, $"{Name} temperature feedback deviation than {Math.Abs(_scDeviationAlarmRange.IntValue)} from setpoint for {_scDeviationAlarmTime.IntValue} seconds");
  372. EV.Notify(HeaterDeviationAlarm);
  373. }
  374. }
  375. public void Reset()
  376. {
  377. _trigControlTcBroken.RST = true;
  378. _trigMonitorTcBroken.RST = true;
  379. _trigDeviation.RST = true;
  380. _checkerWarning.RST = true;
  381. _checkerAlarm.RST = true;
  382. }
  383. private void SetBySC(AOAccessor acc, SCConfigItem scItem)
  384. {
  385. if (scItem != null && acc != null)
  386. {
  387. //acc.Value = (short)scItem.IntValue;
  388. _SetRealFloat(acc, scItem.IntValue);
  389. }
  390. }
  391. private float GetHeaterOffsetSetting(double val)
  392. {
  393. if (SC.GetValue<bool>($"{Module}.BiasRf.EnableBiasRF")) return 0;
  394. if (SC.GetValue<bool>($"{Module}.Chiller.EnableChiller")) return 0;
  395. int[] iTempPoint = new int[10];
  396. float[] fOffsetValue = new float[10];
  397. try
  398. {
  399. for (int i = 1; i < 10; i++)
  400. {
  401. iTempPoint[i] = SC.GetValue<int>($"{Module}.{Name}.TempOffsetPoint_{i}");
  402. fOffsetValue[i] = (float)SC.GetValue<double>($"{Module}.{Name}.OffsetValue_{i}");
  403. if (val < iTempPoint[i])
  404. {
  405. return (fOffsetValue[i] - fOffsetValue[i - 1]) / (iTempPoint[i] - iTempPoint[i - 1]) * ((float)val - iTempPoint[i - 1]) + fOffsetValue[i - 1];
  406. }
  407. }
  408. }
  409. catch
  410. { }
  411. return 0;
  412. }
  413. }
  414. }