SunWayVce.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. using Aitex.Core.Common;
  2. using Aitex.Core.RT.Device;
  3. using Aitex.Core.RT.Log;
  4. using Aitex.Core.RT.SCCore;
  5. using Aitex.Core.Util;
  6. using MECF.Framework.Common.Communications;
  7. using MECF.Framework.Common.Equipment;
  8. using MECF.Framework.Common.SubstrateTrackings;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.IO.Ports;
  12. using System.Linq;
  13. using System.Text;
  14. using System.Text.RegularExpressions;
  15. using System.Threading.Tasks;
  16. using Venus_Core;
  17. using Venus_RT.Devices.EFEM;
  18. using Venus_RT.Devices.TM;
  19. using Venus_RT.Modules;
  20. namespace Venus_RT.Devices.VCE
  21. {
  22. public class SunWayVce : VCEModuleBase
  23. {
  24. #region 私有变量
  25. private AsyncSerialPort _serialport;
  26. private string _portname;
  27. private string _newline = "\r\n";//终止符 0D 0A
  28. private object _locker = new object();
  29. private bool _IsAsciiMode;
  30. private LinkedList<string> _lstAsciiMsgs = new LinkedList<string>();
  31. private PeriodicJob _thread;
  32. private Regex _match_ReadMsg = new Regex(@"X,.*");
  33. private Regex _matchErrorCode = new Regex(@"(?<=_ERR,)(.*)");
  34. private ModuleName _moduleName;
  35. private RState _status;
  36. private string _currentMsg;
  37. private VceMessage _currentVceMessage;
  38. private bool _HasReceiveMsg;
  39. private bool _IsDashWaferError;
  40. private int _currentSlot = 0;
  41. public override int CurrentSlot => _currentSlot;
  42. private ModuleName _baseLPIndex
  43. {
  44. get
  45. {
  46. switch (RtInstance.ConfigType)
  47. {
  48. case ConfigType.VenusSE:
  49. return ModuleName.LP1;
  50. case ConfigType.VenusDE:
  51. return _moduleName == ModuleName.VCEA ? ModuleName.LP1 : ModuleName.LP2;
  52. default:
  53. return ModuleName.System;
  54. }
  55. }
  56. }
  57. private Loadport[] _LPMs = new Loadport[1];
  58. public override ILoadport this[ModuleName mod]
  59. {
  60. get
  61. {
  62. if (!ModuleHelper.IsLoadPort(mod))
  63. throw new ApplicationException($"{mod} is NOT Loadport");
  64. return _LPMs[mod - _baseLPIndex];
  65. }
  66. }
  67. //待补充
  68. private Dictionary<string, string> _ErrorCode2Reason = new Dictionary<string, string>()
  69. {
  70. {"221","错误的 ARM 参数" },
  71. {"233","伸缩信号未使能" },
  72. {"304","未识别的错误码" },
  73. {"305","未识别的指令" },
  74. {"309","不支持的指令" },
  75. {"401","ZWAFER 参数错误" },
  76. {"402","非法的 slot 参数" },
  77. {"403","运动指令 RX 参数错误" },
  78. {"404","晶圆夹取失败" },
  79. {"405","晶圆释放失败" },
  80. {"406","气缸压力表检测错误" },
  81. {"407","Mapping 传感器伸出失败" },
  82. {"408","Mapping 传感器缩回失败" },
  83. {"409","Mapping 传感器位置数据不正确" },
  84. {"411","Mapping 传感器高度不一致" },
  85. {"412","工位 VIA 参数未使能" },
  86. {"413","不是有效的 Mapping 工位" },
  87. {"414","手指有晶圆无法 mapping" },
  88. {"415","采集的数据个数错误" },
  89. {"416","采集的晶圆厚度过小" },
  90. {"417","晶圆位置超出有效范围" },
  91. {"418","晶圆上下沿槽数错误" },
  92. {"419","斜片上下沿槽数错误" },
  93. {"550","工位号超范围" },
  94. {"552","VIA 参数错误" },
  95. {"553","MAPVIA 参数错误" },
  96. {"600","系统未上电" },
  97. {"602","指令正在执行中" },
  98. {"603","系统上电失败" },
  99. {"604","示教器控制中" },
  100. {"605","机械手运动中停止" },
  101. {"609","系统存在错误" },
  102. {"610","示教盒急停启动" },
  103. {"611","驱动器报警" },
  104. {"629","驱动器存在报警" },
  105. {"705","LOAD 状态未知" },
  106. {"712","真空吸附动作失败" },
  107. {"730","PLACE 前 LOAD 状态错误" },
  108. {"731","PLACE 后 LOAD 状态错误" },
  109. {"734","PLACE 执行 Extend 过程中未检测到晶圆" },
  110. {"736","PLACE 执行 Retract 过程中检测到晶圆" },
  111. {"740","PICK 前 LOAD 状态错误" },
  112. {"741","PICK 后 LOAD 状态错误" },
  113. {"744","PICK 执行 Extend 过程中检测到晶圆" },
  114. {"745","PICK 执行 Retract 过程中未检测到晶圆" },
  115. {"1006","非法的 IO 端口号" },
  116. {"1314","PITCH 轴超界" },
  117. {"1315","关节位置超界" },
  118. {"1316","关节位置超硬限" },
  119. {"1320","机械手跟踪差超限错误" },
  120. {"1321","机械手发生碰撞" },
  121. {"1322","机械手超出工作区" },
  122. {"1323","关节速度超限" },
  123. {"1401","当前位置不正确" },
  124. {"1407","大气压力不足" },
  125. {"1412","晶圆已滑出" },
  126. {"1500","打开门失败" },
  127. {"1501","关闭门失败" },
  128. {"1502","门开关状态不对" },
  129. {"1503","门松开失败" },
  130. {"1504","门夹紧失败" },
  131. {"1506","当前不是自动门模式" },
  132. {"1507","开盖检测互锁" },
  133. {"1508","开门不允许运动" },
  134. {"1509","无 casette 盒不允许运动" },
  135. {"1510","安全检测触发" },
  136. {"1511","R 轴未运动到位" },
  137. {"1512","门动作开关未使能" },
  138. {"1513","运动开关未使能" },
  139. };
  140. //
  141. #endregion
  142. #region 暴露变量
  143. public override bool IsConnected => _serialport.IsOpen();
  144. public override RState Status => _status;
  145. public override bool IsReady => _status == RState.Init || _status == RState.End;
  146. public override bool IsError => _status == RState.Failed || _status == RState.Timeout;
  147. public override bool IsInit => _status == RState.Init;
  148. public override bool IsDashWaferError => _IsDashWaferError;
  149. private string[] _slotMap = new string[25];
  150. public string SlotMap
  151. {
  152. get
  153. {
  154. WaferInfo[] wafers = WaferManager.Instance.GetWafers(ModuleHelper.Converter(Name));
  155. string slot = "";
  156. for (int i = 0; i < 25; i++)
  157. {
  158. slot += wafers[i].IsEmpty ? "0" : "1";
  159. }
  160. return slot;
  161. }
  162. }
  163. private bool _OutDoorIsOpen
  164. {
  165. get
  166. {
  167. switch (_moduleName)
  168. {
  169. case ModuleName.VCE1:
  170. //2024-05-20 16:35:34 泓浒四边形硬件还未实现
  171. //DEVICE.GetDevice<HongHuTM>("SETM").VCEACassPresent
  172. return _vcedoorflag;
  173. case ModuleName.VCEA:
  174. if (DEVICE.GetDevice<SunWayDETM>("TM").VCEACassPresent)
  175. {
  176. _LPMs[0].HasCassette = true;
  177. }
  178. else
  179. {
  180. _LPMs[0].HasCassette = false;
  181. WaferManager.Instance.DeleteWafer(_LPMs[0].Module, 0, 25);
  182. }
  183. return !DEVICE.GetDevice<SunWayDETM>("TM").VCEALOCKED;
  184. case ModuleName.VCEB:
  185. if (DEVICE.GetDevice<SunWayDETM>("TM").VCEBCassPresent)
  186. {
  187. _LPMs[0].HasCassette = true;
  188. }
  189. else
  190. {
  191. _LPMs[0].HasCassette = false;
  192. WaferManager.Instance.DeleteWafer(_LPMs[0].Module, 0, 25);
  193. }
  194. return !DEVICE.GetDevice<SunWayDETM>("TM").VCEBLOCKED;
  195. default:
  196. return false;
  197. }
  198. }
  199. }
  200. public override bool OutDoorIsOpen => _OutDoorIsOpen;
  201. private bool _vcedoorflag;
  202. private bool _hasProtrusion
  203. {
  204. get
  205. {
  206. switch (_moduleName)
  207. {
  208. case ModuleName.VCE1:
  209. //2024-05-20 16:35:34 泓浒四边形硬件还未实现
  210. //DEVICE.GetDevice<HongHuTM>("SETM").VCEProtrusion
  211. return true;
  212. case ModuleName.VCEA:
  213. if (DEVICE.GetDevice<SunWayDETM>("TM").VCEAProtrusion)
  214. {
  215. _LPMs[0].Protrusion = true;
  216. return true;
  217. }
  218. else
  219. {
  220. _LPMs[0].Protrusion = false;
  221. return false;
  222. }
  223. case ModuleName.VCEB:
  224. if (DEVICE.GetDevice<SunWayDETM>("TM").VCEBProtrusion)
  225. {
  226. _LPMs[0].Protrusion = true;
  227. return true;
  228. }
  229. else
  230. {
  231. _LPMs[0].Protrusion = false;
  232. return false;
  233. }
  234. default:
  235. return false;
  236. }
  237. }
  238. }
  239. #endregion
  240. public SunWayVce(int slot, ModuleName moduleName) : base(slot, moduleName)
  241. {
  242. _moduleName = moduleName;
  243. _vcedoorflag = false;
  244. _IsAsciiMode = true;
  245. _portname = SC.GetStringValue($"{moduleName}.Port");
  246. _serialport = new AsyncSerialPort(_portname, 9600, 8, Parity.None, StopBits.One, _newline, _IsAsciiMode);
  247. _serialport.Open();
  248. _status = RState.Init;
  249. _serialport.OnDataChanged += onDataChange;
  250. _thread = new PeriodicJob(50, fnTimer, _moduleName.ToString(), true);
  251. if (moduleName == ModuleName.VCE1)
  252. _LPMs[0] = new Loadport(ModuleName.LP1);
  253. else
  254. _LPMs[0] = new Loadport((moduleName - ModuleName.VCEA) + ModuleName.LP1);
  255. CarrierManager.Instance.DeleteCarrier(_LPMs[0].Module.ToString());
  256. WaferManager.Instance.DeleteWafer(_LPMs[0].Module, 0, 25);
  257. CarrierManager.Instance.SubscribeLocation(_LPMs[0].Module.ToString(), 1);
  258. Action<ModuleName, int> _subscribeLoc = (ModuleName module, int waferCount) => {
  259. if (ModuleHelper.IsInstalled(module))
  260. {
  261. WaferManager.Instance.SubscribeLocation(module, waferCount);
  262. }
  263. };
  264. _subscribeLoc(_LPMs[0].Module, slot);
  265. }
  266. private bool fnTimer()
  267. {
  268. lock (_locker)
  269. {
  270. //采用ascii传输
  271. if (_IsAsciiMode)
  272. {
  273. //有数据尚未处理
  274. while (_lstAsciiMsgs.Count > 0)
  275. {
  276. string _needHandle = _lstAsciiMsgs.First.Value;
  277. HandleSingleMsg(_needHandle);
  278. _lstAsciiMsgs.RemoveFirst();
  279. }
  280. }
  281. //采用binary
  282. else
  283. {
  284. }
  285. }
  286. return true;
  287. }
  288. private void HandleSingleMsg(string rawmsgs)
  289. {
  290. string[] msgs = rawmsgs.Split('\r');
  291. foreach (var Msg in msgs)
  292. {
  293. string msg = Msg.Trim();
  294. LOG.Write(eEvent.EV_VCE_COMMON_INFO, _moduleName, $"{_moduleName} Receive msg=>{msg}");
  295. if (!string.IsNullOrEmpty(msg))
  296. {
  297. //action set petrify _BKGRDY结束
  298. switch (_currentVceMessage.Head)
  299. {
  300. case VceMessageHead.Action:
  301. case VceMessageHead.Set:
  302. case VceMessageHead.Petrify:
  303. switch (msg)
  304. {
  305. //设备收到 开始运行 目前状态在下发
  306. case "_RDY":
  307. LOG.Write(eEvent.EV_VCE_COMMON_INFO, _moduleName, $"vce {_currentVceMessage.Head} over");
  308. switch (_currentVceMessage.Command)
  309. {
  310. case VceCommand.Home:
  311. case VceCommand.Map:
  312. case VceCommand.GotoLP:
  313. _currentSlot = 0;
  314. break;
  315. case VceCommand.DoorClose:
  316. _vcedoorflag = false;
  317. break;
  318. case VceCommand.DoorOpen:
  319. _vcedoorflag = true;
  320. break;
  321. }
  322. _status = RState.End;
  323. break;
  324. //异常处理
  325. default:
  326. _status = RState.Failed;
  327. string reason;
  328. Errorhandle(msg, out reason);
  329. LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, reason);
  330. break;
  331. }
  332. break;
  333. case VceMessageHead.Read:
  334. //如果收到的信息符合
  335. if (_match_ReadMsg.IsMatch(msg))
  336. {
  337. //收到消息 用于结束
  338. _HasReceiveMsg = true;
  339. switch (_currentVceMessage.Command)
  340. {
  341. //处理wafer 信息为map数据
  342. case VceCommand.ReadMap:
  343. ReadMapData(msg);
  344. break;
  345. case VceCommand.CheckStatus:
  346. ReadStatus(msg);
  347. break;
  348. }
  349. }
  350. //_RDY查询结束
  351. else
  352. {
  353. if (msg == "_RDY")
  354. {
  355. if (_HasReceiveMsg)
  356. {
  357. _status = RState.End;
  358. }
  359. else
  360. {
  361. LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Read Message is over but not receive msg! raw message:{_currentMsg}");
  362. _status = RState.Failed;
  363. }
  364. }
  365. else
  366. {
  367. _status = RState.Failed;
  368. LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Read Message is invalid: receive message {msg} and send message {_currentMsg}");
  369. }
  370. }
  371. break;
  372. }
  373. }
  374. }
  375. }
  376. private void ReadStatus(string msg)
  377. {
  378. try
  379. {
  380. //BRa,SLbb,CPc,WPd,ERe
  381. string[] status = msg.Split(',');
  382. _currentSlot = Convert.ToInt32(status[4].Substring(2, 2));
  383. }
  384. catch (Exception ex)
  385. {
  386. LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"illegal msg:{msg}, {ex.Message}");
  387. }
  388. }
  389. private void ReadMapData(string msg)
  390. {
  391. string waferinfo = "";
  392. string[] waferitems = msg.Split(',');
  393. //智能模式 可以识别叠片
  394. for (int i = 3; i < waferitems.Length - 1; ++i)
  395. {
  396. //如果包含只需要逐个检查
  397. if (waferitems[i].Contains('?'))
  398. {
  399. foreach (char j in waferitems[i])
  400. {
  401. if (waferinfo.Length >= 25)
  402. break;
  403. else
  404. waferinfo += j;
  405. }
  406. }
  407. else
  408. waferinfo += waferitems[i];
  409. }
  410. for (int i = 0; i < waferinfo.Length; ++i)
  411. {
  412. int slotnum = i;
  413. if (slotnum < 25)
  414. {
  415. switch (waferinfo[i])
  416. {
  417. case '0':
  418. WaferManager.Instance.DeleteWafer(_LPMs[0].Module, slotnum);
  419. break;
  420. case 'X':
  421. WaferManager.Instance.CreateWafer(_LPMs[0].Module, slotnum, WaferStatus.Normal);
  422. break;
  423. case 'C':
  424. LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Slot {i + 1}:double or dummy wafer.");
  425. WaferManager.Instance.CreateWafer(_LPMs[0].Module, slotnum, WaferStatus.Double);
  426. break;
  427. case '?':
  428. LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Slot {i + 1}:Crossed wafer.");
  429. WaferManager.Instance.CreateWafer(_LPMs[0].Module, slotnum, WaferStatus.Crossed);
  430. break;
  431. }
  432. }
  433. }
  434. _LPMs[0].IsMapped = true;
  435. }
  436. private void Errorhandle(string msg, out string reason)
  437. {
  438. if (_matchErrorCode.IsMatch(msg))
  439. {
  440. //若是匹配
  441. //包含原因
  442. string errorcode = _matchErrorCode.Match(msg).Value;
  443. if (_ErrorCode2Reason.ContainsKey(errorcode))
  444. {
  445. if (errorcode == "L13")
  446. _IsDashWaferError = true;
  447. reason = _ErrorCode2Reason[errorcode];
  448. }
  449. else
  450. {
  451. reason = "未找到相关Error Code";
  452. }
  453. }
  454. else
  455. {
  456. //若不匹配
  457. reason = "回复消息不符合标准格式";
  458. }
  459. }
  460. private void onDataChange(string oneLineMessage)
  461. {
  462. lock (_locker)
  463. {
  464. if (string.IsNullOrEmpty(_newline))//没有CR
  465. {
  466. _lstAsciiMsgs.AddLast(oneLineMessage);//将消息添加到最后
  467. return;
  468. }
  469. string[] array = oneLineMessage.Split(_newline.ToCharArray());//按照cr分开通讯数据
  470. foreach (string text in array)
  471. {
  472. if (!string.IsNullOrEmpty(text))
  473. {
  474. _lstAsciiMsgs.AddLast(text + _newline);//存进list中等待处理
  475. }
  476. }
  477. }
  478. }
  479. public override bool ServerUp()
  480. {
  481. if (!CheckVceStatus())
  482. return false;
  483. _currentVceMessage = new VceMessage { Head = VceMessageHead.Set, Command = VceCommand.ServerUp, Param = "ALL,ON" };
  484. _currentMsg = _currentVceMessage.toSunWayString() + _newline;
  485. _status = RState.Running;
  486. return _serialport.Write(_currentMsg);
  487. }
  488. public override bool HomeALL()
  489. {
  490. _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.Home, Param = "ALL" };
  491. _currentMsg = _currentVceMessage.toSunWayString() + _newline;
  492. _status = RState.Running;
  493. return _serialport.Write(_currentMsg);
  494. }
  495. public override bool Home(string axis)
  496. {
  497. _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.Home, Param = axis };
  498. _currentMsg = _currentVceMessage.toSunWayString() + _newline;
  499. _status = RState.Running;
  500. return _serialport.Write(_currentMsg);
  501. }
  502. public override bool CheckStatus()
  503. {
  504. if (!CheckVceStatus())
  505. return false;
  506. _currentVceMessage = new VceMessage { Head = VceMessageHead.Read, Command = VceCommand.CheckStatus };
  507. _currentMsg = _currentVceMessage.toSunWayString() + _newline;
  508. _status = RState.Running;
  509. return _serialport.Write(_currentMsg);
  510. }
  511. public override bool CloseDoor()
  512. {
  513. if (!CheckVceStatus())
  514. return false;
  515. _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.DoorClose };
  516. _currentMsg = _currentVceMessage.toSunWayString() + _newline;
  517. _status = RState.Running;
  518. return _serialport.Write(_currentMsg);
  519. }
  520. /// <summary>
  521. /// 开门提示
  522. /// 在honghuVCE中没有ATM信号的内部卡控 可能会导致开门的压差
  523. /// 因此每一次都要增加判断,只要引用此处功能的,前面都需要有判断
  524. ///
  525. /// </summary>
  526. /// <returns></returns>
  527. public override bool OpenDoor()
  528. {
  529. //如果其他指令正在执行 且
  530. //if (!CheckVceStatus())
  531. // return false;
  532. if (_IsDashWaferError)
  533. _IsDashWaferError = false;
  534. _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.DoorOpen };
  535. _currentMsg = _currentVceMessage.toSunWayString() + _newline;
  536. _status = RState.Running;
  537. return _serialport.Write(_currentMsg);
  538. }
  539. public override bool Load()
  540. {
  541. if (!CheckVceStatus())
  542. return false;
  543. _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.Load };
  544. _currentMsg = _currentVceMessage.toSunWayString() + _newline;
  545. _status = RState.Running;
  546. return _serialport.Write(_currentMsg);
  547. }
  548. public override bool UnLoad()
  549. {
  550. if (!CheckVceStatus())
  551. return false;
  552. _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.UnLoad };
  553. _currentMsg = _currentVceMessage.toSunWayString() + _newline;
  554. _status = RState.Running;
  555. return _serialport.Write(_currentMsg);
  556. }
  557. public override bool Map()
  558. {
  559. if (!CheckVceStatus())
  560. return false;
  561. _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.Map };
  562. _currentMsg = _currentVceMessage.toSunWayString() + _newline;
  563. _status = RState.Running;
  564. return _serialport.Write(_currentMsg);
  565. }
  566. public override bool ReadMap()
  567. {
  568. if (!CheckVceStatus())
  569. return false;
  570. _currentVceMessage = new VceMessage { Head = VceMessageHead.Read, Command = VceCommand.ReadMap, Param = "S" };
  571. _currentMsg = _currentVceMessage.toSunWayString() + _newline;
  572. _status = RState.Running;
  573. _HasReceiveMsg = false;
  574. return _serialport.Write(_currentMsg);
  575. }
  576. public override bool Goto(int Targetslot)
  577. {
  578. if (!CheckVceStatus())
  579. return false;
  580. LOG.Write(eEvent.EV_VCE_COMMON_INFO, _moduleName, $"SlotNum:{Targetslot}");
  581. _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.Goto, Param = (Targetslot + 1).ToString().PadLeft(2, '0') };
  582. _currentMsg = _currentVceMessage.toSunWayString() + _newline;
  583. _status = RState.Running;
  584. return _serialport.Write(_currentMsg);
  585. }
  586. public override bool GotoLP()
  587. {
  588. if (!CheckVceStatus())
  589. return false;
  590. _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.GotoLP };
  591. _currentMsg = _currentVceMessage.toSunWayString() + _newline;
  592. _status = RState.Running;
  593. return _serialport.Write(_currentMsg);
  594. }
  595. public override bool ClearError()
  596. {
  597. _currentVceMessage = new VceMessage { Head = VceMessageHead.Set, Command = VceCommand.ClearError };
  598. _currentMsg = _currentVceMessage.toSunWayString() + _newline;
  599. _status = RState.Running;
  600. return _serialport.Write(_currentMsg);
  601. }
  602. }
  603. }