HirataLoadPort.cs 41 KB

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