IoHeater.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  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) + (float)_scMonitorTcFeedbackOffset.DoubleValue;
  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) + (float)_scControlTcFeedbackOffset.DoubleValue;
  76. }
  77. if (_aiControlTcFeedback == null) return -1;
  78. float real = _GetRealFloat(_aiControlTcFeedback);
  79. return real - GetHeaterOffsetSetting(real - _offset) + (float)_scControlTcFeedbackOffset.DoubleValue;
  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 SCConfigItem _scMonitorTcFeedbackOffset;
  195. private SCConfigItem _scControlTcFeedbackOffset;
  196. private DeviceTimer _timerAlarm = new DeviceTimer();
  197. private DeviceTimer _timerWarning = new DeviceTimer();
  198. private readonly R_TRIG _trigWarning = new R_TRIG();
  199. private readonly R_TRIG _trigAlarm = new R_TRIG();
  200. private ToleranceChecker _checkerWarning = new ToleranceChecker();
  201. private ToleranceChecker _checkerAlarm = new ToleranceChecker();
  202. private string HeaterDeviationAlarm = "HeaterDeviationAlarm";
  203. public IoHeater(string module, XmlElement node, string ioModule = "")
  204. {
  205. base.Module = module;
  206. base.Name = node.GetAttribute("id");
  207. base.Display = node.GetAttribute("display");
  208. base.DeviceID = node.GetAttribute("schematicId");
  209. Unit = node.GetAttribute("unit");
  210. _diPowerOnFeedback = ParseDiNode("diPowerOnFeedback", node, ioModule);
  211. _diControlTcBroken = ParseDiNode("diControlTcBroken", node, ioModule);
  212. _diMonitorTcBroken = ParseDiNode("diMonitorTcBroken", node, ioModule);
  213. _doPowerOn = ParseDoNode("doPowerOn", node, ioModule);
  214. _diDeviation = ParseDiNode("diDeviation", node, ioModule);
  215. _aiControlTcFeedback = ParseAiNode("aiFeedback", node, ioModule);
  216. _aiMonitorTcFeedback = ParseAiNode("aiMonitor", node, ioModule);
  217. _aiCoolantInletTempFeedback = ParseAiNode("aiCoolantInletTemp", node, ioModule);
  218. _aiCoolantOutletTempFeedback = ParseAiNode("aiCoolantOutletTemp", node, ioModule);
  219. _aoSetPoint = ParseAoNode("aoSetPoint", node, ioModule);
  220. _aoSetPointLimit = ParseAoNode("aoSetPointLimit", node, ioModule);
  221. _scSetPointLimit = ParseScNodeEx("scSetPointLimit", node, ioModule);
  222. }
  223. //public void UpdateConfig(double setPointLimit)
  224. //{
  225. // if (_aoSetPointLimit != null)
  226. // _aoSetPointLimit.Value = (short)setPointLimit;
  227. //}
  228. public bool Initialize()
  229. {
  230. DATA.Subscribe($"{Module}.{Name}.DeviceData", () =>
  231. {
  232. AITHeaterData data = new AITHeaterData()
  233. {
  234. Module = Module,
  235. DeviceName = Name,
  236. DeviceSchematicId = DeviceID,
  237. DisplayName = Display,
  238. FeedBack = ControlTcFeedback,
  239. MonitorTcFeedBack = MonitorTcFeedback,
  240. CoolantInletTcFeedback = CoolantInletTcFeedback,
  241. CoolantOutletTcFeedback = CoolantOutletTcFeedback,
  242. Scale = SetPointLimit,
  243. SetPoint = ControlTcSetPointView,
  244. IsPowerOn = IsPowerOnFeedback,
  245. IsPowerOnSetPoint = IsPowerOnSetPoint,
  246. IsControlTcBroken = IsControlTcBroken,
  247. IsMonitorTcBroken = IsMonitorTcBroken,
  248. Unit = Unit,
  249. IsTcDeviation = IsTcDeviation,
  250. };
  251. return data;
  252. }, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  253. DATA.Subscribe($"{Module}.{Name}.Temperature", () => ControlTcFeedback, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  254. OP.Subscribe($"{Module}.{Name}.{AITHeaterOperation.SetPowerOnOff}", (functionName, param) =>
  255. {
  256. bool isEnable = Convert.ToBoolean((string)param[0]);
  257. return this.TurnOnOff(isEnable);
  258. });
  259. OP.Subscribe($"{Module}.{Name}.{AITHeaterOperation.Ramp}", (functionName, param) =>
  260. {
  261. float setpoint = (float)Convert.ToDouble((string)param[0]);
  262. if (!RampTemp(setpoint)) return false;
  263. return true;
  264. });
  265. this.SetBySC(_aoSetPointLimit, _scSetPointLimit);
  266. _scEnableToleranceCheck = SC.GetConfigItem($"{Module}.{Name}.HeaterEnableTolerance");
  267. _scDeviationAlarmRange = SC.GetConfigItem($"{Module}.{Name}.HeaterAlarmRange");
  268. _scDeviationAlarmTime = SC.GetConfigItem($"{Module}.{Name}.HeaterAlarmTime");
  269. _scDeviationWarningRange = SC.GetConfigItem($"{Module}.{Name}.HeaterWarningRange");
  270. _scDeviationWarningTime = SC.GetConfigItem($"{Module}.{Name}.HeaterWarningTime");
  271. _scMonitorTcFeedbackOffset = SC.GetConfigItem($"{Module}.{Name}.MonitorTcFeedbackOffset");
  272. _scControlTcFeedbackOffset = SC.GetConfigItem($"{Module}.{Name}.ControlTcFeedbackOffset");
  273. EV.Subscribe(new EventItem("Event", HeaterDeviationAlarm, "Heater Deviation Out of Tolerance", EventLevel.Alarm, EventType.HostNotification));
  274. return true;
  275. }
  276. public bool TurnOnOff(bool on)
  277. {
  278. if (Controller != null)
  279. {
  280. Controller.SetPowerOnOff(on);
  281. return true;
  282. }
  283. if (!_doPowerOn.SetValue(on, out string reason))
  284. {
  285. EV.PostWarningLog(Module, reason);
  286. return false;
  287. }
  288. EV.PostInfoLog(Module, $"Set Heater {Name} Power {(on ? "ON" : "OFF")}");
  289. return true;
  290. }
  291. public bool RampTemp(float setpoint)
  292. {
  293. // 是否越界
  294. if (setpoint > SetPointLimit || setpoint < 0)
  295. {
  296. EV.PostAlarmLog(Module, $"{Name} 温度设定 {setpoint} 无效, 正确范围是 (0, {SetPointLimit})");
  297. return false;
  298. }
  299. if (setpoint == 0)
  300. {
  301. EV.PostInfoLog(Module, $"{Name} setpoint = {setpoint}, ignore temperature control");
  302. return true;
  303. }
  304. if (Controller != null)
  305. {
  306. return Controller.Ramp(setpoint);
  307. }
  308. _offset = GetHeaterOffsetSetting(setpoint);
  309. // offset 处理后的设定值
  310. _controlTcSetPointView = setpoint;
  311. if (Name == "ForelineHeater")
  312. ControlTcSetPoint = setpoint;
  313. else
  314. ControlTcSetPoint = setpoint + _offset;
  315. EV.PostInfoLog(Module, $"设定 {Display} 温度到 {setpoint}");
  316. return true;
  317. }
  318. public void Stop()
  319. {
  320. if (_aoSetPoint != null)
  321. {
  322. _aoSetPoint.Value = 0;
  323. }
  324. }
  325. public void Terminate()
  326. {
  327. }
  328. public void Monitor()
  329. {
  330. try
  331. {
  332. _trigControlTcBroken.CLK = IsControlTcBroken;
  333. if (_trigControlTcBroken.Q)
  334. {
  335. EV.PostAlarmLog(Module, $"{Display}, Found control TC broken");
  336. }
  337. _trigMonitorTcBroken.CLK = IsMonitorTcBroken;
  338. if (_trigMonitorTcBroken.Q)
  339. {
  340. EV.PostAlarmLog(Module, $"{Display}, Found monitor TC broken");
  341. }
  342. _trigDeviation.CLK = IsTcDeviation;
  343. if (_trigDeviation.Q)
  344. {
  345. EV.PostAlarmLog(Module, $"{Display}, Found TC Deviation out of range");
  346. }
  347. this.SetBySC(_aoSetPointLimit, _scSetPointLimit);
  348. CheckDeviation();
  349. }
  350. catch (Exception ex)
  351. {
  352. LOG.Write(ex);
  353. }
  354. }
  355. private void CheckDeviation()
  356. {
  357. if (!_scEnableToleranceCheck.BoolValue)
  358. return;
  359. if (Controller != null && !Controller.GetIsOn())
  360. {
  361. return;
  362. }
  363. if (!IsPowerOnFeedback)
  364. return;
  365. _checkerWarning.Monitor(ControlTcFeedback, ControlTcSetPointView - Math.Abs(_scDeviationWarningRange.IntValue)
  366. , ControlTcSetPoint + Math.Abs(_scDeviationWarningRange.IntValue), _scDeviationWarningTime.IntValue);
  367. if (_checkerWarning.Trig)
  368. {
  369. EV.PostWarningLog(Module, $"{Name} temperature feedback deviation than {Math.Abs(_scDeviationWarningRange.IntValue)} from setpoint for {_scDeviationWarningTime.IntValue} seconds");
  370. }
  371. _checkerAlarm.Monitor(ControlTcFeedback, ControlTcSetPointView - Math.Abs(_scDeviationAlarmRange.IntValue)
  372. , ControlTcSetPoint + Math.Abs(_scDeviationAlarmRange.IntValue), _scDeviationAlarmTime.IntValue);
  373. if (_checkerAlarm.Trig)
  374. {
  375. EV.PostAlarmLog(Module, $"{Name} temperature feedback deviation than {Math.Abs(_scDeviationAlarmRange.IntValue)} from setpoint for {_scDeviationAlarmTime.IntValue} seconds");
  376. EV.Notify(HeaterDeviationAlarm);
  377. }
  378. }
  379. public void Reset()
  380. {
  381. _trigControlTcBroken.RST = true;
  382. _trigMonitorTcBroken.RST = true;
  383. _trigDeviation.RST = true;
  384. _checkerWarning.RST = true;
  385. _checkerAlarm.RST = true;
  386. }
  387. private void SetBySC(AOAccessor acc, SCConfigItem scItem)
  388. {
  389. if (scItem != null && acc != null)
  390. {
  391. //acc.Value = (short)scItem.IntValue;
  392. _SetRealFloat(acc, scItem.IntValue);
  393. }
  394. }
  395. private float GetHeaterOffsetSetting(double val)
  396. {
  397. if (SC.GetValue<bool>($"{Module}.BiasRf.EnableBiasRF")) return 0;
  398. if (SC.GetValue<bool>($"{Module}.Chiller.EnableChiller")) return 0;
  399. int[] iTempPoint = new int[10];
  400. float[] fOffsetValue = new float[10];
  401. try
  402. {
  403. for (int i = 1; i < 10; i++)
  404. {
  405. iTempPoint[i] = SC.GetValue<int>($"{Module}.{Name}.TempOffsetPoint_{i}");
  406. fOffsetValue[i] = (float)SC.GetValue<double>($"{Module}.{Name}.OffsetValue_{i}");
  407. if (val < iTempPoint[i])
  408. {
  409. return (fOffsetValue[i] - fOffsetValue[i - 1]) / (iTempPoint[i] - iTempPoint[i - 1]) * ((float)val - iTempPoint[i - 1]) + fOffsetValue[i - 1];
  410. }
  411. }
  412. }
  413. catch
  414. { }
  415. return 0;
  416. }
  417. }
  418. }