HirataLoadPort.cs 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085
  1. using Aitex.Core.Common;
  2. using Aitex.Core.RT.Device;
  3. using Aitex.Core.RT.Device.Unit;
  4. using Aitex.Core.RT.IOCore;
  5. using Aitex.Core.RT.Log;
  6. using Aitex.Core.RT.SCCore;
  7. using Aitex.Core.Util;
  8. using Aitex.Sorter.Common;
  9. using athosRT.tool;
  10. using Common.DataCenter;
  11. using Common.OP;
  12. using MECF.Framework.Common.Communications;
  13. using MECF.Framework.Common.Equipment;
  14. using MECF.Framework.Common.SubstrateTrackings;
  15. using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts.LoadPortBase;
  16. using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotBase;
  17. using System;
  18. using System.Collections.Generic;
  19. using System.Diagnostics;
  20. using System.IO.Ports;
  21. using System.Linq;
  22. using System.Text;
  23. using System.Text.RegularExpressions;
  24. using System.Threading.Tasks;
  25. namespace athosRT.Devices.LP
  26. {
  27. //注意要与brooks的lp实现保持一致
  28. class HirataLoadPort : LoadPortBaseDevice
  29. {
  30. private string _lpname = string.Empty;
  31. private AsyncSerialPort _serial;
  32. private string _port = string.Empty;
  33. private object _locker = new object();
  34. private LinkedList<string> _lstAsciiMsgs = new LinkedList<string>();
  35. private string _newLine = "\r";//协议的CR
  36. private byte _newHeader = 0x01;//协议的头 此处为SOH 也可以是SOT等 对着表就OK
  37. private PeriodicJob lp_thread;//监听收到数据的线程
  38. private bool _isAsciiMode;
  39. private bool _isLoaded;
  40. private LoadPortStateEnum _current = LoadPortStateEnum.Init;
  41. private readonly int _timeout = 1*60*1000;
  42. private IoTrigger _lpIsEnable;
  43. //private DeviceTimer _device_timer;
  44. //关键变量
  45. /* _isPresent 是否Present
  46. * _isPlaced 是否Placed
  47. * _isLoaded load状态 load后置map后置true
  48. * IsReady() 是否busy
  49. * _isMapped map状态 map后置true
  50. * _isDocked dock状态 load后置map后置true
  51. * IsCarrierEnabled 看sc的厚薄设置*/
  52. public override bool IsHomed { get; set; }//是否home过 orgn
  53. public override bool IsLoaded => _isLoaded;
  54. public override bool IsIdle => fsm.State == (int)LoadPortStateEnum.Idle;
  55. public bool IsConnected => _serial != null && _serial.IsOpen();//是否建立连接
  56. public bool IsQueryComplete { get; set; }
  57. public string ProtrusionState { get; set; }
  58. public override bool IsReady() => fsm.State == (int)LoadPortStateEnum.Idle|| fsm.State == (int)LoadPortStateEnum.Init;
  59. private readonly Regex mov_interlock_error = new Regex(@".*MOV:.*\/");//MOV:.../...即是interlock错误发生
  60. private readonly Regex mov_abs_error = new Regex(@".*ABS:.*");//含有ABS即是MOV执行失败 成功是INF
  61. private readonly Regex catch_After_param = new Regex(@"(?<=\/)(.+?)(?=\;)");//提取错误
  62. private readonly Regex catch_command = new Regex(@"(?<=\:)(.+?)(?=[\/,\;])");//提取命令
  63. private readonly Regex catch_command_type = new Regex(@"(?<=0000)(.+?)(?=\:)");//提取命令类型
  64. public HirataLoadPort(string module, string lpname, string scRoot, RobotBaseDevice robot,IoTrigger[] LPTriggers) : base(module, lpname, robot)
  65. {
  66. base.Module = module;
  67. base.Name = lpname;
  68. _lpname = lpname;
  69. _isAsciiMode = true;
  70. _port = SC.GetStringValue($"LoadPort.{_lpname}.PortName");
  71. //LOG.Write();
  72. //_port = "COM12";//
  73. //参数类型string port, int baudRate, int dataBits, Parity parity, StopBits stopBits,
  74. _serial = new AsyncSerialPort(_port, 9600, 8, Parity.None, StopBits.One, _newLine, _isAsciiMode);
  75. _serial.OnDataChanged += OnAsciiDataReceived;//使用ascii类型时的数据变化处理
  76. _serial.OnBinaryDataChanged += OnBinaryDataChanged;//使用binary类型时的数据变化处理
  77. _serial.OnErrorHappened += onErrorHappend;
  78. DoorState = FoupDoorState.Close;
  79. if (_serial.Open())
  80. {
  81. LOG.Write($"{_lpname}连接成功");
  82. }
  83. else
  84. {
  85. LOG.Write($"{_lpname}连接失败");
  86. }
  87. lp_thread = new PeriodicJob(10, OnTimer, $"{_lpname}->OnTimer", true);
  88. Singleton<WaferManager>.Instance.SubscribeLocation($"{_lpname}", 25);
  89. Singleton<CarrierManager>.Instance.SubscribeLocation($"{_lpname}");
  90. for (int index = 0;index < 25;++index)
  91. {
  92. Singleton<WaferManager>.Instance.DeleteWafer(ModuleHelper.Converter(_lpname), index);
  93. }
  94. //_device_timer = new DeviceTimer();
  95. }
  96. protected override void SubscribeDataVariable()
  97. {
  98. }
  99. private void OnBinaryDataChanged(byte[] obj)
  100. {
  101. }
  102. /// <summary>
  103. /// 定时函数 用来监听最新收到的消息 并交给函数处理
  104. /// </summary>
  105. /// <returns></returns>
  106. private bool OnTimer()
  107. {
  108. //处理消息
  109. lock (_locker)
  110. {
  111. if (DoorState == FoupDoorState.Open)
  112. {
  113. if (Name == "LP1")
  114. DeviceModel.TrigSafetytoSMIF1.SetTrigger(true, out _);
  115. if (Name == "LP2")
  116. DeviceModel.TrigSafetytoSMIF2.SetTrigger(true, out _);
  117. }
  118. else
  119. {
  120. if (Name == "LP1")
  121. DeviceModel.TrigSafetytoSMIF1.SetTrigger(false, out _);
  122. if (Name == "LP2")
  123. DeviceModel.TrigSafetytoSMIF2.SetTrigger(false, out _);
  124. }
  125. switch (Name)
  126. {
  127. case "LP1":
  128. _isPlaced = DeviceModel.LP1Placement.Value;
  129. _isPresent = DeviceModel.LP1Presence.Value;
  130. break;
  131. case "LP2":
  132. _isPlaced = DeviceModel.LP2Placement.Value;
  133. _isPresent = DeviceModel.LP2Presence.Value;
  134. break;
  135. }
  136. //if (_device_timer.IsTimeout())
  137. //{
  138. // _device_timer.Stop();
  139. // LogObject.Error(_lpname,$"while {CurrentState} Timeout");
  140. // CheckToPostMessage(LoadPortMsg.Error);
  141. // return false;
  142. //}
  143. //Trace.WriteLine($"{_lpname} state: {CurrentState}");
  144. if (_isAsciiMode)//按照ascii码处理
  145. {
  146. while (_lstAsciiMsgs.Count > 0)
  147. {
  148. string value = _lstAsciiMsgs.First.Value;
  149. HandleAsciiData(value);
  150. _lstAsciiMsgs.RemoveFirst();
  151. }
  152. }
  153. else
  154. {
  155. //暂时用不上
  156. //while (_lstBinsMsgs.Count > 0)
  157. //{
  158. // byte[] value2 = _lstBinsMsgs.First.Value;
  159. // _port_HandleBinarayData(value2);
  160. // _lstBinsMsgs.RemoveFirst();
  161. //}
  162. }
  163. }
  164. return true;
  165. }
  166. private void HandleAsciiData(string ReceiveMsg)
  167. {
  168. if (string.IsNullOrEmpty(ReceiveMsg))
  169. return;
  170. Trace.WriteLine(_lpname+"收到的msg" +ReceiveMsg);
  171. LogObject.Info(_lpname,"======收到的msg======="+ReceiveMsg+"==============");
  172. //解析返回的数据
  173. //收到的数据的头是否为00 不是就按照错误代码打log
  174. if (ReceiveMsg.Substring(1, 2) != "00")
  175. {
  176. /*
  177. * 错误代码
  178. * Check sum error
  179. * Command error
  180. * Interlock
  181. * Alarm occurring
  182. * Command processing
  183. * Mode error
  184. * Mapping error
  185. */
  186. string reason = string.Empty;
  187. switch (ReceiveMsg.Substring(0, 2))
  188. {
  189. case "01":
  190. reason = "Check sum error";
  191. break;
  192. case "02":
  193. reason = "Command error";
  194. break;
  195. case "04":
  196. reason = "Interlock";
  197. break;
  198. case "05":
  199. reason = "Alarm occurring";
  200. break;
  201. case "06":
  202. reason = "Command processing";
  203. break;
  204. case "07":
  205. reason = "Mode error";
  206. break;
  207. case "08":
  208. reason = "Mapping error";
  209. break;
  210. default:
  211. reason = "Unknown Error";
  212. break;
  213. }
  214. //找到的原因
  215. LogObject.Error(_lpname, $"Received Error Message:{reason}");
  216. }
  217. //MOV不能执行的错误
  218. else if (mov_interlock_error.IsMatch(ReceiveMsg))
  219. {
  220. //MOV错误 获取/...;间的数据 Interlock code 表示错误代码
  221. LogObject.Error(_lpname, $"MOV:{catch_command.Match(ReceiveMsg).Value} received the error:{catch_After_param.Match(ReceiveMsg).Value}");
  222. }
  223. //MOV执行后 获取ABS错误
  224. else if (mov_abs_error.IsMatch(ReceiveMsg))
  225. {
  226. //获取/;之间的参数
  227. string param = string.Empty;
  228. if (!string.IsNullOrEmpty(catch_After_param.Match(ReceiveMsg).Value))
  229. param = catch_After_param.Match(ReceiveMsg).Value;
  230. if (string.IsNullOrEmpty(param))
  231. {
  232. LogObject.Error(_lpname, $"MOV:{catch_command.Match(ReceiveMsg).Value} failed for the Unknown error");
  233. }
  234. else
  235. {
  236. string reason = "";
  237. switch (param[0])
  238. {
  239. case '1':
  240. switch (param[1])
  241. {
  242. case '0': reason = "Clamp time over"; break;
  243. case '1': reason = "Unclamp time over"; break;
  244. case '2': reason = "Dock time over"; break;
  245. case '3': reason = "Undock time over"; break;
  246. case '4': reason = "Latch time over"; break;
  247. case '5': reason = "Unlatch time over"; break;
  248. case '6': reason = "Vacuum time over"; break;
  249. case '7': reason = "Vacuum release time over"; break;
  250. case '8': reason = "Door open time over"; break;
  251. case '9': reason = "Door close time over"; break;
  252. case 'A': reason = "Mapping forward time over"; break;
  253. case 'B': reason = "Mapping return time over"; break;
  254. case 'F': reason = "communication error(3 times of resending)"; break;
  255. }
  256. break;
  257. case '2':
  258. switch (param[1])
  259. {
  260. case '0': reason = "Home return time over"; break;
  261. case '1': reason = "Loading time over"; break;
  262. case '2': reason = "Unloading time over"; break;
  263. case '3': reason = "Positioning time over"; break;
  264. case '8': reason = "Door open/close position movement time over"; break;
  265. case '9': reason = "Mapping start position movement time over"; break;
  266. case 'A': reason = "Mapping end position movement time over"; break;
  267. case 'B': reason = "Load position movement time over"; break;
  268. }
  269. break;
  270. case '4':
  271. switch (param[1])
  272. {
  273. case '0': reason = "Mapping data error"; break;
  274. case '1': reason = "Mode select error"; break;
  275. }
  276. break;
  277. case '7':
  278. switch (param[1])
  279. {
  280. case '0': reason = "Clamp sensor error"; break;
  281. case '1': reason = "Dock sensor error"; break;
  282. case '2': reason = "Latch sensor error"; break;
  283. case '3': reason = "Door sensor error"; break;
  284. case '4': reason = "Mapping sensor error"; break;
  285. case '7': reason = "Elevator axis sensor error"; break;
  286. }
  287. break;
  288. case 'A':
  289. switch (param[1])
  290. {
  291. case '0': reason = "Wafer drop"; break;
  292. case '1': reason = "Wafer protrusion"; break;
  293. case '2': reason = "FOUP mount error"; break;
  294. case '3': reason = "FOUP mount error"; break;
  295. case '5': reason = "Air pressure drop"; break;
  296. }
  297. break;
  298. case 'B':
  299. switch (param[1])
  300. {
  301. case '0': reason = "Host error"; break;
  302. }
  303. break;
  304. case 'C':
  305. switch (param[1])
  306. {
  307. case '0': reason = "Parameter error"; break;
  308. }
  309. break;
  310. case 'E':
  311. switch (param[1])
  312. {
  313. case '0': reason = "FAN stop alarm"; break;
  314. case '3': reason = "Voltage drop"; break;
  315. }
  316. break;
  317. case 'F':
  318. switch (param[1])
  319. {
  320. case 'E': reason = "Dock hand pinch error"; break;
  321. }
  322. break;
  323. }
  324. if (string.IsNullOrEmpty(reason))
  325. {
  326. LogObject.Error(_lpname, $"MOV:{catch_command.Match(ReceiveMsg).Value} failed for the Unknown error {param}");
  327. }
  328. else
  329. {
  330. LogObject.Error(_lpname, $"MOV:{catch_command.Match(ReceiveMsg).Value} failed for the error {param}:{reason}");
  331. }
  332. }
  333. }
  334. else
  335. {
  336. //基本没有错误 若有遗漏 继续加else if(条件补充)
  337. //对事件进行分割 SET GET涉及到wafer mapping MOV涉及到home open clamp等
  338. OnEventHappend(ReceiveMsg);//接受信息 涉及状态机切换
  339. return;
  340. }
  341. //走到这里表示是错误走出 需要发送message给状态机
  342. CheckToPostMessage(LoadPortMsg.Error);
  343. IsError = true;
  344. }
  345. private void FindErrorReason(string param,out string reason)
  346. {
  347. reason = string.Empty;
  348. switch (param[0])
  349. {
  350. case '1':
  351. switch (param[1])
  352. {
  353. case '0': reason = "Clamp time over"; break;
  354. case '1': reason = "Unclamp time over"; break;
  355. case '2': reason = "Dock time over"; break;
  356. case '3': reason = "Undock time over"; break;
  357. case '4': reason = "Latch time over"; break;
  358. case '5': reason = "Unlatch time over"; break;
  359. case '6': reason = "Vacuum time over"; break;
  360. case '7': reason = "Vacuum release time over"; break;
  361. case '8': reason = "Door open time over"; break;
  362. case '9': reason = "Door close time over"; break;
  363. case 'A': reason = "Mapping forward time over"; break;
  364. case 'B': reason = "Mapping return time over"; break;
  365. case 'F': reason = "communication error(3 times of resending)"; break;
  366. }
  367. break;
  368. case '2':
  369. switch (param[1])
  370. {
  371. case '0': reason = "Home return time over"; break;
  372. case '1': reason = "Loading time over"; break;
  373. case '2': reason = "Unloading time over"; break;
  374. case '3': reason = "Positioning time over"; break;
  375. case '8': reason = "Door open/close position movement time over"; break;
  376. case '9': reason = "Mapping start position movement time over"; break;
  377. case 'A': reason = "Mapping end position movement time over"; break;
  378. case 'B': reason = "Load position movement time over"; break;
  379. }
  380. break;
  381. case '4':
  382. switch (param[1])
  383. {
  384. case '0': reason = "Mapping data error"; break;
  385. case '1': reason = "Mode select error"; break;
  386. }
  387. break;
  388. case '7':
  389. switch (param[1])
  390. {
  391. case '0': reason = "Clamp sensor error"; break;
  392. case '1': reason = "Dock sensor error"; break;
  393. case '2': reason = "Latch sensor error"; break;
  394. case '3': reason = "Door sensor error"; break;
  395. case '4': reason = "Mapping sensor error"; break;
  396. case '7': reason = "Elevator axis sensor error"; break;
  397. }
  398. break;
  399. case 'A':
  400. switch (param[1])
  401. {
  402. case '0': reason = "Wafer drop"; break;
  403. case '1': reason = "Wafer protrusion"; break;
  404. case '2': reason = "FOUP mount error"; break;
  405. case '3': reason = "FOUP mount error"; break;
  406. case '5': reason = "Air pressure drop"; break;
  407. }
  408. break;
  409. case 'B':
  410. switch (param[1])
  411. {
  412. case '0': reason = "Host error"; break;
  413. }
  414. break;
  415. case 'C':
  416. switch (param[1])
  417. {
  418. case '0': reason = "Parameter error"; break;
  419. }
  420. break;
  421. case 'E':
  422. switch (param[1])
  423. {
  424. case '0': reason = "FAN stop alarm"; break;
  425. case '3': reason = "Voltage drop"; break;
  426. }
  427. break;
  428. case 'F':
  429. switch (param[1])
  430. {
  431. case 'E': reason = "Dock hand pinch error"; break;
  432. }
  433. break;
  434. }
  435. }
  436. //按照返回数据处理 包括mov后的状态机切换 set反馈 get反馈
  437. private void OnEventHappend(string receiveMsg)
  438. {
  439. //首先按照收到的正确数据类型进行分类
  440. //收到的可能是1、set 2、get 3、mov 4、inf
  441. string command_type = catch_command_type.Match(receiveMsg).Value;//获取到操作的类型
  442. string command_name = catch_command.Match(receiveMsg).Value;//获取操作的名称
  443. switch (command_type)
  444. {
  445. case "SET":
  446. SetEndAnalysis(command_name);
  447. break;//主要是设置 没有太多内容
  448. case "GET"://涉及mapping state要对返回值序列进行处理
  449. string command_parameter = catch_After_param.Match(receiveMsg).Value;
  450. GetEndAnalysis(command_name, command_parameter);
  451. break;
  452. case "MOV"://设备回复收到MOV命令
  453. MovCanExcute(command_name);
  454. break;
  455. case "INF"://设备回复完成MOV命令 需要对该指令处理并下发msg给状态机
  456. MovOPEnd(command_name);
  457. break;
  458. default: break;
  459. }
  460. }
  461. private void SetEndAnalysis(string command_name)
  462. {
  463. switch (command_name)
  464. {
  465. case "RSET":
  466. CheckToPostMessage(LoadPortMsg.ResetComplete);
  467. break;
  468. default:
  469. break;
  470. }
  471. }
  472. private void MovCanExcute(string command_name)
  473. {
  474. }
  475. //设备回复完成MOV命令 需要对该指令处理并下发msg给状态机
  476. private void MovOPEnd(string command_name)
  477. {
  478. switch(command_name)
  479. {
  480. //home完成
  481. case "ORGN":
  482. CheckToPostMessage(LoadPortMsg.InitComplete);
  483. break;
  484. //Load完成
  485. case "FPML":
  486. SendMessage("GET:MAPR;");//获取扫片的结果
  487. break;
  488. //Unload完成
  489. case "FPMU":
  490. CheckToPostMessage(LoadPortMsg.UnloadComplete);
  491. break;
  492. //Unclamp
  493. case "FCOP":
  494. CheckToPostMessage(LoadPortMsg.MoveComplete, "Unclamp over");
  495. break;
  496. //Clamp
  497. case "FCCL":
  498. CheckToPostMessage(LoadPortMsg.MoveComplete, "Clamp over");
  499. break;
  500. }
  501. }
  502. private void GetEndAnalysis(string command_name, string command_parameter)
  503. {
  504. switch (command_name)
  505. {
  506. case "STAS"://此处涉及LP关键状态变量的获取 对efem中的判断有重要影响
  507. OnStasRead(command_parameter);
  508. break;
  509. case "MAPR"://此处涉及扫片的结果转化为wafermanager存储 efem上层会从wafermanager中读取转化 重要!
  510. //================判断
  511. OnSlotMapRead(command_parameter);
  512. if (CurrentState == LoadPortStateEnum.Loading)
  513. {
  514. CheckToPostMessage(LoadPortMsg.LoadComplete);
  515. }
  516. break;
  517. }
  518. }
  519. private void OnStasRead(string command_parameter)
  520. {
  521. _isLoaded = false;
  522. switch (command_parameter[6])//Continer Status
  523. {
  524. case '0':
  525. //_isPlaced = false;
  526. //_isPresent = false;
  527. break;
  528. case '1':
  529. //_isPlaced = true;
  530. //_isPresent = true;
  531. break;
  532. case '2':
  533. //_isPlaced = false;
  534. //_isPresent = true;
  535. break;
  536. }
  537. switch (command_parameter[7])//Clamp position
  538. {
  539. case '0':
  540. ClampState = FoupClampState.Open;
  541. break;
  542. case '1':
  543. ClampState = FoupClampState.Close;
  544. break;
  545. case '?':
  546. ClampState = FoupClampState.Unknown;
  547. break;
  548. }
  549. switch (command_parameter[10])//Door positon
  550. {
  551. case '0':
  552. DoorState = FoupDoorState.Open;
  553. if(Module == "LP1")
  554. DeviceModel.TrigSafetytoSMIF1.SetTrigger(true,out _);
  555. if (Module == "LP2")
  556. DeviceModel.TrigSafetytoSMIF2.SetTrigger(true, out _);
  557. break;
  558. case '1':
  559. DoorState = FoupDoorState.Close;
  560. if (Module == "LP1")
  561. DeviceModel.TrigSafetytoSMIF1.SetTrigger(false, out _);
  562. if (Module == "LP2")
  563. DeviceModel.TrigSafetytoSMIF2.SetTrigger(false, out _);
  564. break;
  565. case '?':
  566. DoorState = FoupDoorState.Unknown;
  567. if (Module == "LP1")
  568. DeviceModel.TrigSafetytoSMIF1.SetTrigger(false, out _);
  569. if (Module == "LP2")
  570. DeviceModel.TrigSafetytoSMIF2.SetTrigger(false, out _);
  571. break;
  572. }
  573. switch (command_parameter[11])//Wafer protrusion sensor(2025.4.18 +)
  574. {
  575. case '0':
  576. ProtrusionState = "Shading";
  577. break;
  578. case '1':
  579. ProtrusionState = "Lighting";
  580. break;
  581. }
  582. switch (command_parameter[13])//Dock positon
  583. {
  584. case '0':
  585. DockState = FoupDockState.Undocked;
  586. break;
  587. case '1':
  588. DockState = FoupDockState.Docked;
  589. break;
  590. case '?':
  591. DockState = FoupDockState.Unknown;
  592. break;
  593. }
  594. if (command_parameter[4]!='0')//状态不是normal
  595. {
  596. string reason;
  597. string param = "";
  598. param += command_parameter[4];
  599. param += command_parameter[5];
  600. FindErrorReason(param, out reason);
  601. LogObject.Error(_lpname,reason);
  602. CheckToPostMessage(LoadPortMsg.Error);
  603. }
  604. }
  605. //覆盖原SlotMap函数 slotMap是一串数字 代表wafer的状态
  606. public override void OnSlotMapRead(string slotMap)
  607. {
  608. lock (_locker)
  609. {
  610. int error_num = 0;
  611. //循环所有wafer
  612. for (int i = 0; i < slotMap.Length; i++)
  613. {
  614. WaferInfo waferInfo = null;
  615. LogObject.Info(_lpname,$"Slot:{i}:{slotMap[i]}");
  616. switch (slotMap[i])
  617. {
  618. case '0'://没有wafer delete
  619. Singleton<WaferManager>.Instance.DeleteWafer(base.LPModuleName, i);
  620. Singleton<CarrierManager>.Instance.UnregisterCarrierWafer(base.Name, i);
  621. break;
  622. case '1'://有wafer add
  623. waferInfo = Singleton<WaferManager>.Instance.CreateWafer(LPModuleName, i, WaferStatus.Normal, WaferSize.WS8);
  624. Singleton<CarrierManager>.Instance.RegisterCarrierWafer(base.Name, i, waferInfo);
  625. break;
  626. case '2'://错误
  627. waferInfo = Singleton<WaferManager>.Instance.CreateWafer(base.LPModuleName, i, WaferStatus.Normal, WaferSize.WS8);
  628. Singleton<CarrierManager>.Instance.RegisterCarrierWafer(base.Name, i, waferInfo);
  629. error_num++;
  630. LogObject.Error(base.Name, $"Slot {i + 1}: occur Crossed");
  631. break;
  632. case '3':
  633. waferInfo = Singleton<WaferManager>.Instance.CreateWafer(base.LPModuleName, i, WaferStatus.Normal, WaferSize.WS8);
  634. Singleton<CarrierManager>.Instance.RegisterCarrierWafer(base.Name, i, waferInfo);
  635. LogObject.Warning(base.Name, $"Slot {i + 1}: Thickness is too Thick");
  636. break;
  637. case '4':
  638. waferInfo = Singleton<WaferManager>.Instance.CreateWafer(base.LPModuleName, i, WaferStatus.Normal, WaferSize.WS8);
  639. Singleton<CarrierManager>.Instance.RegisterCarrierWafer(base.Name, i, waferInfo);
  640. LogObject.Warning(base.Name, $"Slot {i + 1}: Thickness is too Thin");
  641. break;
  642. case '5':
  643. waferInfo = Singleton<WaferManager>.Instance.CreateWafer(base.LPModuleName, i, WaferStatus.Normal, WaferSize.WS8);
  644. Singleton<CarrierManager>.Instance.RegisterCarrierWafer(base.Name, i, waferInfo);
  645. LogObject.Error(base.Name, $"Slot {i + 1}: Position error”");
  646. break;
  647. }
  648. }
  649. if (error_num == 0)
  650. {
  651. base.MapError = false;
  652. }
  653. else
  654. {
  655. base.MapError = true;
  656. }
  657. _isMapped = true;//十二分重要
  658. //无所谓的部分
  659. //SerializableDictionary<string, object> serializableDictionary = new SerializableDictionary<string, object>();
  660. //serializableDictionary["SlotMap"] = CurrentSlotMapResult;
  661. //serializableDictionary["PortID"] = base.PortID;
  662. //serializableDictionary["PORT_CTGRY"] = base.SpecPortName;
  663. //serializableDictionary["CarrierType"] = SpecCarrierType;
  664. //serializableDictionary["CarrierIndex"] = InfoPadCarrierIndex;
  665. //serializableDictionary["InfoPadSensorIndex"] = InfoPadSensorIndex;
  666. //serializableDictionary["CarrierID"] = base.CarrierId;
  667. //EV.Notify(EventSlotMapAvailable, serializableDictionary);
  668. //if (base.LPCallBack != null)
  669. //{
  670. // base.LPCallBack.MappingComplete(_carrierId, CurrentSlotMapResult);
  671. //}
  672. }
  673. }
  674. public override WaferSize GetCurrentWaferSize()
  675. {
  676. return WaferSize.WS8;
  677. }
  678. /// <summary>
  679. /// 用来将接受到的数据按照CR分散为一条 等待OnTimer解析
  680. /// </summary>
  681. /// <param name="oneLineMessage"></param>
  682. private void OnAsciiDataReceived(string oneLineMessage)
  683. {
  684. lock (_locker)
  685. {
  686. if (string.IsNullOrEmpty(_newLine))//没有CR
  687. {
  688. _lstAsciiMsgs.AddLast(oneLineMessage);//将消息添加到最后
  689. return;
  690. }
  691. string[] array = oneLineMessage.Split(_newLine.ToCharArray());//按照cr分开通讯数据
  692. foreach (string text in array)
  693. {
  694. if (!string.IsNullOrEmpty(text))
  695. {
  696. _lstAsciiMsgs.AddLast(text + _newLine);//存进list中等待处理
  697. }
  698. }
  699. }
  700. }
  701. public bool SendMessage(string message)
  702. {
  703. //专注数据的发送 此处对数据进行加校验位、加末位处理
  704. if (string.IsNullOrEmpty(message))
  705. {
  706. LogObject.Warning(_lpname,"试图发送空消息");
  707. return false;
  708. }
  709. if (IsConnected)
  710. {
  711. message = "0000" + message;//加上头
  712. int _hexsum = 0;
  713. foreach (var _schar in message.ToCharArray())
  714. {
  715. //获取到的是每一个字符 将其转为Hex存入buffers 并累加 用于最后的计算
  716. int num = Convert.ToInt32(_schar); // 将字符转换为 ASCII 数值
  717. string hex = num.ToString("X"); // 将 ASCII 数值转换为十六进制字符串
  718. _hexsum += int.Parse(hex, System.Globalization.NumberStyles.HexNumber); // 将十六进制字符串转换为整数
  719. }
  720. string _name = _hexsum.ToString("X");
  721. //00 + 00 + Message + CSH + CSI + _newLine
  722. message = message + _name[_name.Length - 2] + _name[_name.Length - 1] + _newLine;
  723. LogObject.Info(_lpname, " send Message:" + message);
  724. int raw_length = Encoding.Default.GetBytes(message).Length;
  725. byte[] raw_buffer = Encoding.Default.GetBytes(message);
  726. byte[] send_buffer = new byte[raw_length + 1];
  727. send_buffer[0] = _newHeader;//加SOH
  728. raw_buffer.CopyTo(send_buffer, 1);//剩下的复制到send_buffer
  729. if (_serial.Write(send_buffer))
  730. {
  731. //_device_timer.Restart(_timeout);
  732. //通过串口发送
  733. LogObject.Info(_lpname, "===========发送的msg============" + message);
  734. return true;
  735. }
  736. else
  737. {
  738. LogObject.Error(_lpname,"Send Message failed.");
  739. return false;
  740. }
  741. }
  742. else
  743. {
  744. LogObject.Error(_lpname, "尚未建立连接或初始化!");
  745. return false;
  746. }
  747. }
  748. private void onErrorHappend(string obj)
  749. {
  750. LogObject.Error($"{_lpname}", $"Connect Error for:{obj}");
  751. }
  752. protected override bool fStartExecute(object[] param)
  753. {
  754. //执行逻辑 超时报警 返回错误 返回带参STAS除外都是有错的 ABS执行错误
  755. try
  756. {
  757. switch (param[0].ToString())
  758. {
  759. case "Unclamp":
  760. lock (_locker)
  761. {
  762. SendMessage("MOV:FCOP;");
  763. }
  764. break;
  765. case "Clamp":
  766. lock (_locker)
  767. {
  768. SendMessage("MOV:FCCL;");
  769. }
  770. break;
  771. case "MapWafer":
  772. //_serial.Write("");
  773. break;
  774. case "QueryState":
  775. IsQueryComplete = false;
  776. lock (_locker)
  777. {
  778. SendMessage("GET:STAS;");
  779. }
  780. break;
  781. default:
  782. break;
  783. }
  784. return true;
  785. }
  786. catch (Exception ex)
  787. {
  788. return false;
  789. }
  790. }
  791. protected override bool fMonitorExecuting(object[] param)
  792. {
  793. base.IsBusy = false;
  794. LogObject.Info(_lpname,$"{param[0].ToString()} excuted over");
  795. return true;
  796. }
  797. protected override bool fStartInit(object[] param)
  798. {
  799. //收到消息进入initilizing状态 需要先下发
  800. //初始化逻辑MOV:ORGN
  801. IsHomed = false;
  802. SendMessage("MOV:ORGN;");
  803. return true;
  804. }
  805. protected override bool fCompleteInit(object[] param)
  806. {
  807. //一些状态要置为false
  808. IsHomed = true;
  809. lock (_locker)
  810. {
  811. SendMessage("GET:STAS;");
  812. }
  813. return true;
  814. }
  815. protected override bool fStartReset(object[] param)
  816. {
  817. //SET:RSET
  818. lock (_locker)
  819. {
  820. SendMessage("SET:RSET;");
  821. }
  822. return true;
  823. }
  824. protected override bool fMonitorReset(object[] param)
  825. {
  826. MapError = false;
  827. IsError = false;
  828. base.IsBusy = false;
  829. return true;
  830. }
  831. protected override bool fStartLoad(object[] param)
  832. {
  833. //load操作
  834. lock (_locker)
  835. {
  836. SendMessage("MOV:FPML;");
  837. }
  838. return true;
  839. }
  840. protected override bool fCompleteLoad(object[] param)
  841. {
  842. base.IsBusy = false;
  843. _isLoaded = true;
  844. base.DockState = FoupDockState.Docked;
  845. base.ClampState = FoupClampState.Close;
  846. base.DoorState = FoupDoorState.Open;
  847. if (Name == "LP1")
  848. DeviceModel.TrigSafetytoSMIF1.SetTrigger(true, out _);
  849. if (Name == "LP2")
  850. DeviceModel.TrigSafetytoSMIF2.SetTrigger(true, out _);
  851. return true;
  852. }
  853. protected override bool fStartUnload(object[] param)
  854. {
  855. lock (_locker)
  856. {
  857. SendMessage("MOV:FPMU;");
  858. }
  859. return true;
  860. }
  861. protected override bool fMonitorUnload(object[] param)
  862. {
  863. base.IsBusy = false;
  864. _isLoaded = false;
  865. base.DockState = FoupDockState.Undocked;
  866. base.ClampState = FoupClampState.Close;
  867. base.DoorState = FoupDoorState.Close;
  868. if (Name == "LP1")
  869. DeviceModel.TrigSafetytoSMIF1.SetTrigger(false, out _);
  870. if (Name == "LP2")
  871. DeviceModel.TrigSafetytoSMIF2.SetTrigger(false, out _);
  872. return true;
  873. }
  874. protected override bool fStartWrite(object[] param)
  875. {
  876. //_serial.Write("");
  877. return true;
  878. }
  879. protected override bool fStartRead(object[] param)
  880. {
  881. //MOV:MAPR
  882. //_serial.Write("MOV:MAPR")
  883. return true ;
  884. }
  885. public override bool IsEnableTransferWafer(out string reason)
  886. {
  887. reason = "";
  888. //Trace.WriteLine("=============================================================");
  889. //Trace.WriteLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}");
  890. //Trace.WriteLine($" LP:{_lpname} State:{State}");
  891. //Trace.WriteLine($"The state of Present is {_isPresent}.");
  892. //Trace.WriteLine($"The state of Placed is {_isPlaced }.");
  893. //Trace.WriteLine($"The state of Ready is {IsReady() }.");
  894. //Trace.WriteLine($"The state of Mapped is {_isMapped }.");
  895. //Trace.WriteLine("=============================================================");
  896. if (_isPresent && _isPlaced && _isLoaded && IsReady() && _isMapped)
  897. {
  898. return true;
  899. }
  900. else
  901. {
  902. reason += $"The State of {_lpname} is {State}. ";
  903. reason += _isPresent ? $"The state of Present is {_isPresent}." : "";
  904. reason += _isPlaced ? $"The state of Placed is {_isPlaced }." : "";
  905. reason += _isLoaded ? $"The state of Loaded is {_isLoaded }." : "";
  906. reason += IsReady() ? $"The state of Ready is {IsReady() }." : "";
  907. reason += _isMapped ? $"The state of Mapped is {_isMapped }." : "";
  908. }
  909. return false;
  910. }
  911. public override bool IsEnableLoad(out string reason)
  912. {
  913. if (!_isPlaced)
  914. {
  915. reason = "No carrier placed";
  916. return false;
  917. }
  918. if (_isDocked)
  919. {
  920. reason = "Carrier is docked";
  921. return false;
  922. }
  923. if (!IsReady())
  924. {
  925. reason = "Not Ready";
  926. return false;
  927. }
  928. //SC的内容 建议直接
  929. //if (!IsCarrierEnabled)
  930. //{
  931. // reason = "CarrierNotEnabled";
  932. // return false;
  933. //}
  934. reason = "";
  935. return true;
  936. }
  937. }
  938. public enum HirataCommandType
  939. {
  940. SET,
  941. MOD,
  942. GET,
  943. MOV,
  944. TCH
  945. }
  946. public enum HirataCommand
  947. {
  948. //SET
  949. RSET,
  950. RTRY,
  951. STPP,
  952. PASE,
  953. ABOT,
  954. RESM,
  955. TYP1,
  956. TYP2,
  957. TYP3,
  958. TYP4,
  959. TYP5,
  960. MAPP,
  961. MAP1,
  962. MAP2,
  963. POSO,
  964. //GET,
  965. STAS,
  966. STA1,
  967. STA2,
  968. MDAT,
  969. MAPR,
  970. VERN,
  971. //MAPP,
  972. //MAP1,
  973. //MAP2,
  974. //POSO,
  975. POSD,
  976. MDAH,
  977. MDAP,
  978. MDTC,
  979. MDHS,
  980. MDPS,
  981. LEST,
  982. //MOV
  983. ORGN,
  984. ABGN,
  985. FPLD,
  986. FPML,
  987. FDOC,
  988. FDLD,
  989. FDML,
  990. FCLD,
  991. FCML,
  992. FPUL,
  993. FPMU,
  994. FVOF,
  995. FVUL,
  996. FUDC,
  997. FUMD,
  998. //MAPP,
  999. RMAP,
  1000. Z_MP ,
  1001. }
  1002. }