TruPlasmaRF.cs 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  1. using Aitex.Core.Common.DeviceData;
  2. using Aitex.Core.RT.DataCenter;
  3. using Aitex.Core.RT.Device;
  4. using Aitex.Core.RT.Log;
  5. using Aitex.Core.RT.OperationCenter;
  6. using Aitex.Core.RT.SCCore;
  7. using Aitex.Core.RT.Tolerance;
  8. using Aitex.Core.UI.Control;
  9. using Aitex.Core.Util;
  10. using CommunityToolkit.HighPerformance.Buffers;
  11. using MECF.Framework.Common.Communications;
  12. using MECF.Framework.Common.DataCenter;
  13. using MECF.Framework.Common.Device.Bases;
  14. using MECF.Framework.Common.Equipment;
  15. using System;
  16. using System.Collections;
  17. using System.Collections.Generic;
  18. using System.Diagnostics;
  19. using System.Linq;
  20. using System.ServiceModel.Channels;
  21. using Venus_Core;
  22. namespace Venus_RT.Devices
  23. {
  24. public class TruPlasmaRF : RfPowerBase
  25. {
  26. private readonly AsyncSerialPort _serial;
  27. private List<byte> buffer = new List<byte>(4096);
  28. private double _total;
  29. private double _fromLast;
  30. private bool _bRFPowerOn = false;
  31. private readonly DeviceTimer _timerQueryStatus = new DeviceTimer();
  32. private readonly DeviceTimer _timerTotal = new DeviceTimer();
  33. private readonly DeviceTimer _timerFromLast = new DeviceTimer();
  34. private readonly DeviceTimer _timerRFTurnOn = new DeviceTimer();
  35. private readonly RD_TRIG _rfOnTrigger = new RD_TRIG();
  36. private readonly R_TRIG _ErrTrigger = new R_TRIG();
  37. private readonly R_TRIG _trigPMNeeded = new R_TRIG();
  38. private readonly RD_TRIG _trigOnOff = new RD_TRIG();
  39. private ToleranceChecker _alarmChecker;
  40. private ToleranceChecker _warningChecker;
  41. private ToleranceChecker _checkerReflectPower;
  42. private readonly double _scPowerAlarmTime;
  43. private readonly double _scPowerAlarmRange;
  44. private readonly double _scPowerWarningTime;
  45. private readonly double _scPowerWarningRange;
  46. private readonly double _scReflectPowerAlarmTime;
  47. private readonly double _scReflectPowerAlarmRange;
  48. private StatsDataItemRFAndPump _statRFOnTime = new StatsDataItemRFAndPump();
  49. public string LastPMTime
  50. {
  51. get
  52. {
  53. return _statRFOnTime != null ? _statRFOnTime.LastPMTime.ToString() : "";
  54. }
  55. }
  56. public double DaysFromLastPM
  57. {
  58. get
  59. {
  60. return _statRFOnTime == null ? 0 : _statRFOnTime.fromLastPM;
  61. }
  62. set
  63. {
  64. if (_statRFOnTime != null)
  65. _statRFOnTime.fromLastPM = value;
  66. }
  67. }
  68. public double TotalDays
  69. {
  70. get
  71. {
  72. return _statRFOnTime != null ? _statRFOnTime.Total : 0;
  73. }
  74. set
  75. {
  76. if (_statRFOnTime != null)
  77. _statRFOnTime.Total = value;
  78. }
  79. }
  80. public double PMIntervalDays
  81. {
  82. get
  83. {
  84. return _statRFOnTime != null ? _statRFOnTime.PMInterval : 0;
  85. }
  86. }
  87. public bool IsPMNeeded
  88. {
  89. get
  90. {
  91. return DaysFromLastPM > PMIntervalDays;
  92. }
  93. }
  94. public bool EnableAlarm
  95. {
  96. get
  97. {
  98. return _statRFOnTime == null || _statRFOnTime.AlarmEnable;
  99. }
  100. }
  101. private readonly double _scPowerRange;
  102. public override float ScalePower => (float)_scPowerRange;
  103. public TruPlasmaRF(ModuleName mod, VenusDevice device) : base(mod.ToString(), device.ToString())
  104. {
  105. this.Status = GeneratorStatus.Unknown;
  106. var portNum = SC.GetStringValue(device == VenusDevice.Rf ? $"{mod}.Rf.Port" : $"{mod}.BiasRf.Port");
  107. _serial = new AsyncSerialPort(portNum, 9600, 8, System.IO.Ports.Parity.None, System.IO.Ports.StopBits.One, "/r", false);
  108. ResetRFStats();
  109. _scPowerAlarmTime = SC.GetValue<double>($"{Module}.{Name}.PowerAlarmTime");
  110. _scPowerAlarmRange = SC.GetValue<double>($"{Module}.{Name}.PowerAlarmRange");
  111. _scPowerWarningTime = SC.GetValue<double>($"{Module}.{Name}.PowerWarningTime");
  112. _scPowerWarningRange = SC.GetValue<double>($"{Module}.{Name}.PowerWarningRange");
  113. _scReflectPowerAlarmTime = SC.GetValue<double>($"{Module}.{Name}.ReflectPowerAlarmTime");
  114. _scReflectPowerAlarmRange = SC.GetValue<double>($"{Module}.{Name}.ReflectPowerAlarmRange");
  115. _scPowerRange = SC.GetValue<double>($"{Module}.{Name}.PowerRange");
  116. _scEnableCalibration = SC.GetConfigItem($"{Module}.{Name}.EnableCalibration");
  117. _scCalibrationTable = SC.GetConfigItem($"{Module}.{Name}.CalibrationTable");
  118. _scRFPhysicalMaxPower = SC.GetConfigItem($"{Module}.{Name}.RFPhysicalMaxPower");
  119. _scCurrentRFMaxPower = SC.GetConfigItem($"{Module}.{Name}.CurrentRFMaxPower");
  120. }
  121. public override bool Initialize()
  122. {
  123. base.Initialize();
  124. DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData);
  125. if (_serial.Open())
  126. {
  127. _serial.OnBinaryDataChanged += SerialPortDataReceived;
  128. _serial.OnErrorHappened += SerialPortErrorOccurred;
  129. ResetCommand();
  130. getcontrol();
  131. SetPulseMode(false);
  132. }
  133. else
  134. {
  135. LOG.Write(eEvent.ERR_RF, Module, "Tru 射频发生器串口无法打开");
  136. return false;
  137. }
  138. return true;
  139. }
  140. public new AITRfData DeviceData =>
  141. new AITRfData
  142. {
  143. Module = Module,
  144. DeviceName = Name,
  145. ScalePower = ScalePower,
  146. ForwardPower = ForwardPower,
  147. ReflectPower = ReflectPower,
  148. IsRfOn = IsPowerOn,
  149. PowerSetPoint = PowerSetPoint,
  150. };
  151. private void SerialPortDataReceived(byte[] rawMessage)
  152. {
  153. try
  154. {
  155. buffer.AddRange(rawMessage);
  156. while (buffer.Count >= 18) //至少包含ACK帧头(1字节)、长度、校验位(17或12字节)
  157. {
  158. //2.1 查找数据头
  159. if (buffer[0] == 0x06) //传输数据有帧头,用于判断
  160. {
  161. //得到完整的数据,复制到ReceiveBytes中进行校验
  162. byte[] ReceiveBytes = new byte[13];
  163. byte[] ReadReceiveBytes = new byte[18];
  164. buffer.CopyTo(0, ReceiveBytes, 0, 13);
  165. buffer.CopyTo(0, ReadReceiveBytes, 0, 18);
  166. if ((ReceiveBytes[12] == 0x55) && (ReceiveBytes[1] == 0xAA)) //校验,最后一个字节是校验位
  167. {
  168. parsecmd(ReceiveBytes);
  169. buffer.RemoveRange(0, 13);
  170. }
  171. else if ((ReadReceiveBytes[17] == 0x55) && (ReceiveBytes[1] == 0xAA))
  172. {
  173. parsecmd(ReadReceiveBytes);
  174. buffer.RemoveRange(0, 18);
  175. }
  176. else
  177. {
  178. buffer.Clear();
  179. LOG.Write(eEvent.ERR_RF, Module, $"rf通讯错误");
  180. }
  181. }
  182. else //帧头不正确时,记得清除
  183. {
  184. //buffer.RemoveAt(0);
  185. }
  186. }
  187. }
  188. catch (Exception ex)
  189. {
  190. buffer.Clear();
  191. LOG.WriteExeption(ex);
  192. }
  193. }
  194. public GeneratorStatus Status { get; set; }
  195. private float _forwardPower;
  196. public override float ForwardPower
  197. {
  198. get
  199. {
  200. return _forwardPower;
  201. }
  202. set
  203. {
  204. _forwardPower = CalibrationData(value, false);
  205. }
  206. }
  207. private bool GetBitValue(byte value, int bit)
  208. {
  209. return (value & (byte)Math.Pow(2, bit)) > 0 ? true : false;
  210. }
  211. public override bool ReConnect()
  212. {
  213. return _serial.ReConnect();
  214. }
  215. public override bool IsPowerOn
  216. {
  217. get => Status == GeneratorStatus.ON;
  218. set { }
  219. }
  220. public void parsecmd(byte[] message)
  221. {
  222. try
  223. {
  224. IsPowerOn = GetBitValue(message[4], 4);
  225. if (GetBitValue(message[4], 4))
  226. {
  227. //LOG.Write(eEvent.INFO_RF,Module,"RF Status:ON");
  228. Status = GeneratorStatus.ON;
  229. }
  230. else
  231. {
  232. //LOG.Write(eEvent.INFO_RF, Module, "RF Status:OFF");
  233. Status = GeneratorStatus.OFF;
  234. }
  235. switch (message[5])
  236. {
  237. case 0x01://ParamRead
  238. if (message.Length == 18 && message[6] == 0x14)
  239. {
  240. int DataValue = BitConverter.ToInt32(new byte[] { message[11], message[12], message[13], message[14] }, 0);
  241. ReflectPower = DataValue;
  242. }
  243. else if (message.Length == 18 && message[6] == 0x12)
  244. {
  245. int DataValue1 = BitConverter.ToInt32(new byte[] { message[11], message[12], message[13], message[14] }, 0);
  246. ForwardPower = DataValue1;
  247. }
  248. break;
  249. case 0x02://ParamWrite
  250. break;
  251. case 0xFE://TelegramError
  252. LOG.Write(eEvent.ERR_RF, Module, "Telegram structure is not correct");
  253. break;
  254. default:
  255. // 默认代码块
  256. break;
  257. }
  258. switch (message[9])
  259. {
  260. case 0x26:
  261. //LOG.Write(eEvent.INFO_RF, Module, "RF Status:OFF");
  262. Status = GeneratorStatus.OFF;
  263. IsPowerOn = false;
  264. break;
  265. case 0x24:
  266. LOG.Write(eEvent.ERR_RF, Module, "Telegram structure is not correct");
  267. break;
  268. default:
  269. // 默认代码块
  270. break;
  271. }
  272. }
  273. catch (Exception ex)
  274. {
  275. LOG.WriteExeption(ex);
  276. }
  277. }
  278. private void SerialPortErrorOccurred(string obj)
  279. {
  280. LOG.Write(eEvent.ERR_RF, Module, $"Tru 射频串口出错, [{obj}]");
  281. }
  282. public override void SetPower(float val)
  283. {
  284. List<byte> baseBytes = new List<byte>() { 0xAA, 0x02, 0x0B, 0x00, 0x02, 0x06, 0x00, 0x01, 0x00, 0x04 };
  285. val = !_scEnableCalibration.BoolValue ? (ushort)val : (ushort)CalibrationData(val, true);
  286. byte[] valueBytes = BitConverter.GetBytes((int)val);
  287. baseBytes.AddRange(valueBytes);
  288. baseBytes = CRC16(baseBytes.ToArray());
  289. baseBytes.Add(0x55);
  290. _serial.Write(baseBytes.ToArray());
  291. }
  292. public override void Monitor()
  293. {
  294. readpi();
  295. readpr();
  296. _rfOnTrigger.CLK = IsPowerOn;
  297. if (_rfOnTrigger.R)
  298. {
  299. _total = TotalDays;
  300. _fromLast = DaysFromLastPM;
  301. _timerTotal.Start(0);
  302. _timerFromLast.Start(0);
  303. _timerTotal.Restart(0);
  304. _timerFromLast.Restart(0);
  305. _alarmChecker.Reset(_scPowerAlarmTime);
  306. _warningChecker.Reset(_scPowerWarningTime);
  307. _checkerReflectPower.Reset(_scReflectPowerAlarmTime);
  308. }
  309. if (_rfOnTrigger.M)
  310. {
  311. TotalDays = _timerTotal.GetElapseTime() / 1000 / 60 / 60;
  312. DaysFromLastPM = _timerFromLast.GetElapseTime() / 1000 / 60 / 60;
  313. }
  314. if (PMIntervalDays > 0)
  315. {
  316. _trigPMNeeded.CLK = IsPMNeeded;
  317. if (_trigPMNeeded.Q)
  318. {
  319. if (EnableAlarm)
  320. {
  321. LOG.Write(eEvent.ERR_RF, $"{Module}", "rf on time value larger than setting interval days");
  322. }
  323. }
  324. }
  325. if (_rfOnTrigger.T)
  326. {
  327. _timerTotal.Stop();
  328. _timerFromLast.Stop();
  329. StatsDataManager.Instance.Increase($"{Module}.{Name}OnTime", $"{Module}{Name}RfOnTime", DaysFromLastPM, TotalDays);
  330. }
  331. if (!_rfOnTrigger.CLK)
  332. {
  333. ForwardPower = 0;
  334. ReflectPower = 0;
  335. }
  336. // RF Turn On & Off Timeout Check
  337. _trigOnOff.CLK = _bRFPowerOn;
  338. if (_trigOnOff.R) //RF Turn On
  339. {
  340. _timerRFTurnOn.Start(SC.GetValue<int>($"{Module}.{Name}.RFTurnOnTimeout") * 1000);
  341. }
  342. if (_trigOnOff.M) //RF Stay On
  343. {
  344. if (_timerRFTurnOn.IsTimeout())
  345. {
  346. if (!IsPowerOn)
  347. {
  348. LOG.Write(eEvent.ERR_RF, $"{Module}", $"{Name} Turn On Failed");
  349. _timerRFTurnOn.Stop();
  350. }
  351. }
  352. }
  353. if (_trigOnOff.T)
  354. {
  355. _timerRFTurnOn.Stop();
  356. }
  357. base.Monitor();
  358. }
  359. public override void ResetRFStats()
  360. {
  361. _statRFOnTime = StatsDataManager.Instance.GetItemRFAndPump($"{Module}.{Name}OnTime");
  362. }
  363. public void getcontrol()
  364. {
  365. byte[] getincontrol = new byte[] { 0xAA, 0x02, 0x06, 0x00, 0x05, 0x01, 0x00, 0x00, 0xFF, 0x34, 0x8A, 0x55 };
  366. _serial.Write(getincontrol.ToArray());
  367. }
  368. public void releasecontrol()
  369. {
  370. byte[] getincontrol = new byte[] { 0xAA, 0x02, 0x06, 0x00, 0x05, 0x02, 0x00, 0x00, 0xFF, 0xE8, 0x11, 0x55 };
  371. _serial.Write(getincontrol.ToArray());
  372. }
  373. public void readpr()//reflect
  374. {
  375. byte[] getincontrol = new byte[] { 0xAA, 0x02, 0x06, 0x00, 0x01, 0x14, 0x00, 0x01, 0xFF, 0xE1, 0x97, 0x55 };
  376. _serial.Write(getincontrol.ToArray());
  377. }
  378. public void readpi()//forward
  379. {
  380. byte[] getincontrola = new byte[] { 0xAA, 0x02, 0x06, 0x00, 0x01, 0x12, 0x00, 0x01, 0xFF, 0x78, 0xB0, 0x55 };
  381. _serial.Write(getincontrola.ToArray());
  382. }
  383. public void ResetCommand()
  384. {
  385. LOG.Write(eEvent.ERR_RF, Module, $"Send rest");
  386. byte[] getincontrol = new byte[] { 0xAA, 0x02, 0x0B, 0x00, 0x02, 0x4D, 0x00, 0x01, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x30, 0x72, 0x55 };
  387. _serial.Write(getincontrol.ToArray());
  388. }
  389. public override void Reset()
  390. {
  391. byte[] getincontrol = new byte[] { 0xAA, 0x02, 0x0B, 0x00, 0x02, 0x4D, 0x00, 0x01, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x30, 0x72, 0x55 };
  392. _serial.Write(getincontrol.ToArray());
  393. }
  394. public override bool SetPowerOnOff(bool on, out string str)
  395. {
  396. str = "";
  397. var _chamber = DEVICE.GetDevice<JetPMBase>(Module);
  398. if (on && !_chamber.CheckGeneratorAndHVInterlock(VenusDevice.Rf))
  399. {
  400. return false;
  401. }
  402. getcontrol();
  403. List<byte> baseBytes = new List<byte>() { 0xAA, 0x02, 0x0B, 0x00, 0x02, 0x6F, 0x00, 0x01, 0x00, 0x07 };
  404. if (on == true)
  405. {
  406. _bRFPowerOn = true;
  407. baseBytes.AddRange(new List<byte> { 0x01, 0x00, 0x00, 0x00 });
  408. }
  409. else
  410. {
  411. _bRFPowerOn = false;
  412. baseBytes.AddRange(new List<byte> { 0x00, 0x00, 0x00, 0x00 });
  413. }
  414. baseBytes = CRC16(baseBytes.ToArray());
  415. baseBytes.Add(0x55);
  416. _serial.Write(baseBytes.ToArray());
  417. if (on == false)
  418. {
  419. releasecontrol();
  420. }
  421. return true;
  422. }
  423. public override void SetPulseMode(bool on)
  424. {
  425. List<byte> baseBytes = new List<byte>() { 0xAA, 0x02, 0x0B, 0x00, 0x02, 0x6A, 0x01, 0x01, 0x00, 0x04 };
  426. if (on == true)
  427. {
  428. baseBytes.AddRange(new List<byte> { 0x01, 0x00, 0x00, 0x00 });
  429. }
  430. else
  431. {
  432. baseBytes.AddRange(new List<byte> { 0x00, 0x00, 0x00, 0x00 });
  433. }
  434. baseBytes = CRC16(baseBytes.ToArray());
  435. baseBytes.Add(0x55);
  436. _serial.Write(baseBytes.ToArray());
  437. }
  438. public override void SetPulseRateFreq(int nFreq)
  439. {
  440. if (nFreq > 0)
  441. {
  442. List<byte> baseBytes = new List<byte>() { 0xAA, 0x02, 0x0B, 0x00, 0x02, 0x6C, 0x01, 0x01, 0x00, 0x04 };
  443. byte[] valueBytes = BitConverter.GetBytes(nFreq);
  444. baseBytes.AddRange(valueBytes);
  445. baseBytes = CRC16(baseBytes.ToArray());
  446. baseBytes.Add(0x55);
  447. _serial.Write(baseBytes.ToArray());
  448. }
  449. else
  450. {
  451. LOG.Write(eEvent.ERR_RF, Module, $"{Name},SetPulseRateFreq() parameter error: {nFreq}");
  452. }
  453. }
  454. public override void SetPulseDutyCycle(int percentage)
  455. {
  456. if (percentage >= 10 && percentage <= 90)
  457. {
  458. List<byte> baseBytes = new List<byte>() { 0xAA, 0x02, 0x0B, 0x00, 0x02, 0x6D, 0x01, 0x01, 0x00, 0x04 };
  459. byte[] valueBytes = BitConverter.GetBytes(percentage);
  460. baseBytes.AddRange(valueBytes);
  461. baseBytes = CRC16(baseBytes.ToArray());
  462. baseBytes.Add(0x55);
  463. _serial.Write(baseBytes.ToArray());
  464. }
  465. else
  466. {
  467. LOG.Write(eEvent.ERR_RF, Module, $"{Name},SetPulseDutyCycle() parameter error: {percentage}");
  468. }
  469. }
  470. #region 霍廷格RF协议crc-16/CCITT-FALSE校验
  471. private bool CRC16(byte[] buffer, ref byte[] ResCRC16) // crc-16/CCITT-FALSE,判断校验
  472. {
  473. bool status = false;
  474. ushort crc = 0xFFFF;
  475. int size = buffer.Length; //计算待计算的数据长度
  476. int i = 0;
  477. if (size > 0)
  478. {
  479. while (size-- > 0)
  480. {
  481. crc = (ushort)((crc >> 8) | (crc << 8));
  482. crc ^= buffer[i++];
  483. crc ^= (ushort)(((byte)crc) >> 4);
  484. crc ^= (ushort)(crc << 12);
  485. crc ^= (ushort)((crc & 0xff) << 5);
  486. }
  487. }
  488. //判断输入的ResCRC16与计算出来的是否一致
  489. if (ResCRC16[0] == (byte)((crc >> 8) & 0xff) && ResCRC16[1] == (byte)(crc & 0xff))
  490. {
  491. status = true;
  492. }
  493. return status;
  494. }
  495. private List<byte> CRC16(byte[] buffer) // crc-16/CCITT-FALSE,补全两个字节
  496. {
  497. ushort crc = 0xFFFF;
  498. int size = buffer.Length; //计算待计算的数据长度
  499. int i = 0;
  500. if (size > 0)
  501. {
  502. while (size-- > 0)
  503. {
  504. crc = (ushort)((crc >> 8) | (crc << 8));
  505. crc ^= buffer[i++];
  506. crc ^= (ushort)(((byte)crc) >> 4);
  507. crc ^= (ushort)(crc << 12);
  508. crc ^= (ushort)((crc & 0xff) << 5);
  509. }
  510. }
  511. var byteList = buffer.ToList();
  512. byteList.Add((byte)(crc & 0xff));
  513. byteList.Add((byte)((crc >> 8) & 0xff));
  514. return byteList;
  515. }
  516. #endregion
  517. }
  518. class TruPlasmaMatch : RfMatchBase
  519. {
  520. private readonly AsyncSerialPort _serial;
  521. private const ushort S3_HEAD_LENGTH = 2;
  522. private readonly DeviceTimer _timerQueryStatus = new DeviceTimer();
  523. private int QUERY_INTERVAL = 1000;
  524. private List<byte> buffer = new List<byte>(4096);
  525. [Subscription("MatchWorkMode")]
  526. public EnumRfMatchTuneMode WorkMode { get; set; }
  527. public float C1 { get; set; }
  528. public float C2 { get; set; }
  529. public float _C1setpoint { get; set; }
  530. public float _C2setpoint { get; set; }
  531. //[Subscription("VPP")]
  532. public ushort VPP { get; set; }
  533. public float VDC { get; set; }
  534. public new AITMatchData DeviceData
  535. {
  536. get
  537. {
  538. return new AITMatchData
  539. {
  540. Module = Module,
  541. DeviceName = Name,
  542. WorkMode = WorkMode.ToString(),
  543. C1 = TunePosition1,
  544. C2 = TunePosition2,
  545. VPP = "",
  546. DCBias = DCBias.ToString(),
  547. C1SetPoint= _C1setpoint,
  548. C2SetPoint = _C2setpoint,
  549. };
  550. }
  551. }
  552. public TruPlasmaMatch(ModuleName mod, VenusDevice device) : base(mod.ToString(), device.ToString())
  553. {
  554. var portNum = SC.GetStringValue($"{mod}.{device}.Port");
  555. _serial = new AsyncSerialPort(portNum, 9600, 8, System.IO.Ports.Parity.None, System.IO.Ports.StopBits.One, "/r", false);
  556. intervalTime = 100;
  557. }
  558. ~TruPlasmaMatch()
  559. {
  560. _serial?.Close();
  561. }
  562. public override bool Initialize()
  563. {
  564. base.Initialize();
  565. preset(50,50);
  566. DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData);
  567. if (_serial.Open())
  568. {
  569. _serial.OnBinaryDataChanged += SerialBinaryPortDataReceived;
  570. _serial.OnErrorHappened += SerialPortErrorOccurred;
  571. }
  572. else
  573. {
  574. LOG.Write(eEvent.ERR_RF, Module, "Match 串口无法打开");
  575. return false;
  576. }
  577. DATA.Subscribe($"{Module}.{Name}.C1", () => TunePosition1);
  578. DATA.Subscribe($"{Module}.{Name}.C2", () => TunePosition2);
  579. DATA.Subscribe($"{Module}.{Name}.VDC", () => VDC);
  580. DATA.Subscribe($"{Module}.{Name}.WorkMode", () => WorkMode.ToString());
  581. OP.Subscribe($"{Module}.{Name}.SetC1", (func, args) =>
  582. {
  583. return true;
  584. });
  585. OP.Subscribe($"{Module}.{Name}.SetC2", (func, args) =>
  586. {
  587. return true;
  588. });
  589. OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchPositionC1}", (out string reason, int time, object[] param) =>
  590. {
  591. SetMatchPositionC1((float)Convert.ToDouble(param[0]), out reason);
  592. return true;
  593. });
  594. OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchPositionC2}", (out string reason, int time, object[] param) =>
  595. {
  596. SetMatchPositionC2((float)Convert.ToDouble(param[0]), out reason);
  597. return true;
  598. });
  599. OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchPosition}", (out string reason, int time, object[] param) =>
  600. {
  601. SetMatchPosition((float)Convert.ToDouble(param[0]), (float)Convert.ToDouble(param[1]), out reason);
  602. return true;
  603. });
  604. OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchProcessMode}", (out string reason, int time, object[] param) =>
  605. {
  606. SetMatchMode((string)param[0] == "Auto" ? EnumRfMatchTuneMode.Auto : EnumRfMatchTuneMode.Manual, out reason);
  607. return true;
  608. });
  609. return true;
  610. }
  611. public void readc1()
  612. {
  613. byte[] readc1 = new byte[] { 0x0C, 0xF3, 0x00, 0x02, 0x00, 0x01, 0x61, 0x42, 0x79, 0x18, 0x01, 0x37 };
  614. _serial.Write(readc1.ToArray());
  615. }
  616. public void readc2()
  617. {
  618. byte[] readc1 = new byte[] { 0x0C, 0xF3, 0x00, 0x02, 0x00, 0x01, 0x61, 0x42, 0x79, 0x19, 0x01, 0x38 };
  619. _serial.Write(readc1.ToArray());
  620. }
  621. public void readVDC()
  622. {
  623. byte[] readvdc = new byte[] { 0x0C, 0xF3, 0x00, 0x02, 0x00, 0x00, 0x61, 0x42, 0x79, 0x1E, 0x01, 0x3C };
  624. _serial.Write(readvdc.ToArray());
  625. }
  626. public override void Monitor()
  627. {
  628. //ReadPosition(50,50);//0x10 (present mode)CMD 可实现任意模式下只读不设值,0x08(auto then manual)在auto模式下可实现相同功能
  629. readc1();
  630. readc2();
  631. //readVDC();
  632. }
  633. public override void Terminate()
  634. {
  635. }
  636. public override void Reset()
  637. {
  638. preset(50, 50);
  639. }
  640. /// <summary>
  641. ///
  642. /// </summary>
  643. /// <param name="c1,c2">百分比数字</param>
  644. /// <param name="c2"></param>
  645. ///
  646. private void executeMatchPostion(float c1, float c2)
  647. {
  648. SetPositionManualAuto(c1, c2);
  649. }
  650. public override void SetMatchPosition(float c1, float c2, out string reason)
  651. {
  652. //preset(c1, c2);
  653. executeMatchPostion(c1, c2);
  654. reason = "";
  655. }
  656. public void SetPresetMode(RfMatchPresetMode mode)
  657. {
  658. }
  659. // -----------------------Private Method-------------------------
  660. //
  661. private void SerialBinaryPortDataReceived(byte[] message)
  662. {
  663. if (message.Count() < 18)
  664. {
  665. string hexString = BitConverter.ToString(message.ToArray()).Replace("-", " ");
  666. //LOG.Write(eEvent.ERR_MATCH, Module, hexString);
  667. //LOG.Write(eEvent.ERR_RF, Module, "收到 Match 数据格式不正确");
  668. }
  669. else
  670. {
  671. try
  672. {
  673. buffer.AddRange(message);
  674. while (buffer.Count >= 18) //至少包含帧头(1字节)、长度(1字节)、其余27字节
  675. {
  676. //2.1 查找数据头
  677. if (buffer[0] == 0x1D && buffer[1] == 0xE2) //传输数据有帧头,用于判断
  678. {
  679. //得到完整的数据,复制到ReceiveBytes中进行校验
  680. byte[] ReceiveBytes = new byte[29];
  681. buffer.CopyTo(0, ReceiveBytes, 0, 29);
  682. TunePosition1 = BitConverter.ToSingle(new byte[] { ReceiveBytes[10], ReceiveBytes[11], ReceiveBytes[12], ReceiveBytes[13] }, 0) * 100;
  683. TunePosition2 = BitConverter.ToSingle(new byte[] { ReceiveBytes[14], ReceiveBytes[15], ReceiveBytes[16], ReceiveBytes[17] }, 0) * 100;
  684. buffer.RemoveRange(0, 29);
  685. switch (ReceiveBytes[19])
  686. {
  687. case 0x01:
  688. this.WorkMode = EnumRfMatchTuneMode.Manual;
  689. break;
  690. case 0x02:
  691. this.WorkMode = EnumRfMatchTuneMode.Auto;
  692. break;
  693. case 0x20:
  694. this.WorkMode = EnumRfMatchTuneMode.Undefined;
  695. break;
  696. default:
  697. break;
  698. }
  699. }
  700. else if (buffer[0] == 0x12 && buffer[1] == 0xED)
  701. {
  702. byte[] ReceiveBytes18 = new byte[18];
  703. buffer.CopyTo(0, ReceiveBytes18, 0, 18);
  704. if (ReceiveBytes18[10] == 0x79 && ReceiveBytes18[11] == 0x18)
  705. {
  706. TunePosition1 = BitConverter.ToSingle(new byte[] { ReceiveBytes18[12], ReceiveBytes18[13], ReceiveBytes18[14], ReceiveBytes18[15] }, 0) * 100;
  707. } else if (ReceiveBytes18[10] == 0x79 && ReceiveBytes18[11] == 0x19)
  708. {
  709. TunePosition2 = BitConverter.ToSingle(new byte[] { ReceiveBytes18[12], ReceiveBytes18[13], ReceiveBytes18[14], ReceiveBytes18[15] }, 0) * 100;
  710. }
  711. else if (ReceiveBytes18[10] == 0x79 && ReceiveBytes18[11] == 0x1E)
  712. {
  713. VDC = BitConverter.ToSingle(new byte[] { ReceiveBytes18[12], ReceiveBytes18[13], ReceiveBytes18[14], ReceiveBytes18[15] }, 0);
  714. }
  715. buffer.RemoveRange(0, 18);
  716. }
  717. else //帧头不正确时,记得清除
  718. {
  719. buffer.Clear();
  720. //LOG.Write(eEvent.ERR_MATCH, Module, $"Match通讯错误");
  721. }
  722. }
  723. }
  724. catch (Exception ex)
  725. {
  726. buffer.Clear();
  727. LOG.WriteExeption(ex);
  728. }
  729. }
  730. }
  731. private void SerialPortErrorOccurred(string str)
  732. {
  733. LOG.Write(eEvent.ERR_RF, Module, $"TruPlasma Match error [{str}]");
  734. }
  735. private void SetPositionManualAuto(float c1val, float c2val)
  736. {
  737. _C1setpoint = c1val;
  738. _C2setpoint = c2val;
  739. List<byte> Len = new List<byte>() { 0x16, 0xE9 };
  740. List<byte> DstSrc = new List<byte>() { 0x00, 0x02, 0x00, 0x01 };
  741. List<byte> Cmd = new List<byte> { 0x60, 0x40 };
  742. byte[] val1Bytes = BitConverter.GetBytes(c1val / 100);
  743. byte[] val2Bytes = BitConverter.GetBytes(c2val / 100);
  744. List<byte> Act = new List<byte>() { 0x00 };
  745. List<byte> Ctr123 = new List<byte> { 0x08, 0x00, 0x00 };
  746. List<byte> baseBytes = new List<byte>() { };
  747. baseBytes.AddRange(Len);
  748. baseBytes.AddRange(DstSrc);
  749. baseBytes.AddRange(Cmd);
  750. baseBytes.AddRange(val1Bytes);
  751. baseBytes.AddRange(val2Bytes);
  752. baseBytes.AddRange(Act);
  753. baseBytes.AddRange(Ctr123);
  754. int a = 0;
  755. for (int i = 2; i < baseBytes.Count; i++)
  756. {
  757. a += (Int16)baseBytes[i];
  758. }
  759. byte[] ackture = new byte[2];
  760. byte[] ackbyte = BitConverter.GetBytes(a);
  761. ackture[0] = ackbyte[1];
  762. ackture[1] = ackbyte[0];
  763. baseBytes.AddRange(ackture);
  764. _serial.Write(baseBytes.ToArray());
  765. }
  766. private void preset(float c1val, float c2val)
  767. {
  768. _C1setpoint = c1val;
  769. _C2setpoint = c2val;
  770. List<byte> Len = new List<byte>() { 0x16, 0xE9 };
  771. List<byte> DstSrc = new List<byte>() { 0x00, 0x02, 0x00, 0x01 };
  772. List<byte> Cmd = new List<byte> { 0x60, 0x40 };
  773. byte[] val1Bytes = BitConverter.GetBytes(c1val / 100);
  774. byte[] val2Bytes = BitConverter.GetBytes(c2val / 100);
  775. List<byte> Act = new List<byte>() { 0x00 };
  776. List<byte> Ctr123 = new List<byte> { 0x04, 0x10, 0x80 };
  777. List<byte> baseBytes = new List<byte>() { };
  778. baseBytes.AddRange(Len);
  779. baseBytes.AddRange(DstSrc);
  780. baseBytes.AddRange(Cmd);
  781. baseBytes.AddRange(val1Bytes);
  782. baseBytes.AddRange(val2Bytes);
  783. baseBytes.AddRange(Act);
  784. baseBytes.AddRange(Ctr123);
  785. int a = 0;
  786. for (int i = 2; i < baseBytes.Count; i++)
  787. {
  788. a += (Int16)baseBytes[i];
  789. }
  790. byte[] ackture = new byte[2];
  791. byte[] ackbyte = BitConverter.GetBytes(a);
  792. ackture[0] = ackbyte[1];
  793. ackture[1] = ackbyte[0];
  794. baseBytes.AddRange(ackture);
  795. _serial.Write(baseBytes.ToArray());
  796. }
  797. public override bool SetMatchMode(EnumRfMatchTuneMode enumRfMatchTuneMode, out string reason)
  798. {
  799. reason = string.Empty;
  800. return true;
  801. }
  802. public override bool ReConnect()
  803. {
  804. return _serial.ReConnect();
  805. }
  806. private void SetWorkMode(EnumRfMatchTuneMode mode)
  807. {
  808. }
  809. private void SetPresetMemory(byte gear)
  810. {
  811. }
  812. }
  813. }