TransporterPickUpFromRoutine.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. using Aitex.Core.RT.Device;
  2. using Aitex.Core.RT.Log;
  3. using Aitex.Core.RT.Routine;
  4. using Aitex.Core.RT.SCCore;
  5. using Aitex.Core.Util;
  6. using MECF.Framework.Common.Beckhoff.Station;
  7. using MECF.Framework.Common.Equipment;
  8. using MECF.Framework.Common.Layout;
  9. using MECF.Framework.Common.Routine;
  10. using MECF.Framework.Common.Utilities;
  11. using MECF.Framework.Common.WaferHolder;
  12. using CyberX8_Core;
  13. using CyberX8_RT.Devices.AXIS;
  14. using CyberX8_RT.Devices.AXIS.CANOpen;
  15. using CyberX8_RT.Devices.Facilities;
  16. using CyberX8_RT.Devices.Loader;
  17. using CyberX8_RT.Devices.TransPorter;
  18. using CyberX8_RT.Modules.Loader;
  19. using System;
  20. using System.Collections.Generic;
  21. using System.Linq;
  22. using System.Text;
  23. using System.Threading.Tasks;
  24. using CyberX8_RT.Devices.Rinse;
  25. using CyberX8_RT.Devices.Metal;
  26. using Aitex.Core.Common;
  27. namespace CyberX8_RT.Modules.Transporter
  28. {
  29. public class TransporterPickUpFromRoutine : RoutineBase, IRoutine
  30. {
  31. private enum PickUpStep
  32. {
  33. CheckPreCondition,
  34. TargetCellUnclamp,
  35. TargetCellUnclampWait,
  36. VerticalLow,
  37. VerticalLowWait,
  38. SafeMoveTo,
  39. CheckMoveToStatus,
  40. GantryPosition,
  41. GantryPoisitiolWait,
  42. UnlockTransporterClamp,
  43. UnlockTransporterClampWait,
  44. CellClampRetract,
  45. //CellClampRetractWait,
  46. LoopPickupRetry,
  47. LoopRetryUnlock,
  48. LoopRetryUnlockWait,
  49. LoopRetryBackToLow,
  50. LoopRetryBackToLowWait,
  51. ElevatorPosition,
  52. ElevatorPositionWait,
  53. Delay,
  54. ReadyToLockCheck,
  55. LockTransporterClamp,
  56. LockTransporterClampWait,
  57. LoopPickupRetryEnd,
  58. CalculateLiftupSpeed,
  59. PickupDelay,
  60. VerticalUp,
  61. VerticalUpWait,
  62. UpdateWaferHolder,
  63. CheckWHPresentAndLock,
  64. //ReadBarcodeConfirm,
  65. End
  66. }
  67. #region 内部变量
  68. private string _cellName;
  69. private JetAxisBase _gantryAxis;
  70. private JetAxisBase _elevatorAxis;
  71. private LoaderEntity _loaderEntity;
  72. private JetAxisBase _loaderRotationAxis;
  73. private SystemFacilities _facilities;
  74. private TransporterUnlockRoutine _unlockRoutine;
  75. private TransporterLockRoutine _lockRoutine;
  76. private TransporterConflictRoutine _conflictRoutine;
  77. private TransporterCommon _transporterCommon;
  78. private LoaderPreTransferUnclampRoutine _preTransferUnclampRoutine;
  79. private LoaderCommonDevice _loaderCommonDevice;
  80. ProcessLayoutCellItem _cellItem;
  81. private int _pickupTime;
  82. private int _pickupDelayTime;
  83. private int _velocity;
  84. private int _acceleration;
  85. private bool _bypassWaferHolderPresent;
  86. private int _pickMaxRetries = 2;
  87. #endregion
  88. /// <summary>
  89. /// 构造函数
  90. /// </summary>
  91. /// <param name="module"></param>
  92. public TransporterPickUpFromRoutine(string module) : base(module)
  93. {
  94. }
  95. /// <summary>
  96. /// 中止
  97. /// </summary>
  98. public void Abort()
  99. {
  100. Runner.Stop("Manual Abort");
  101. }
  102. /// <summary>
  103. /// 监控
  104. /// </summary>
  105. /// <returns></returns>
  106. public RState Monitor()
  107. {
  108. Runner.Run(PickUpStep.CheckPreCondition, CheckStartPreConfition, _delay_1ms)
  109. //确认cell clamp Retracted
  110. .Run(PickUpStep.TargetCellUnclamp, TargetCellUnclamp, _delay_1ms)
  111. .WaitWithStopCondition(PickUpStep.TargetCellUnclampWait, TargetCellUnclampEndStatus, TargetCellUnclampStopStatus)
  112. .Run(PickUpStep.VerticalLow, ElevatorGotoLow, _delay_1ms)
  113. .WaitWithStopCondition(PickUpStep.VerticalLowWait, CheckVerticalPositionStatus, CheckVerticalPositionRunStop)
  114. //1.2 Move to 安全
  115. .Run(PickUpStep.SafeMoveTo, SafeMoveTo, _delay_1ms)
  116. .WaitWithStopCondition(PickUpStep.CheckMoveToStatus, () => CommonFunction.CheckRoutineEndState(_conflictRoutine),
  117. CheckSafeMoveToStopStatus)
  118. //1.2 Gantry 移动
  119. .Run(PickUpStep.GantryPosition, GantryPositionToCell, _delay_1ms)
  120. .WaitWithStopCondition(PickUpStep.GantryPoisitiolWait, CheckGantryPositionStatus, CheckGantryPositionRunStop)
  121. //1.3 Unlock Transporter clamp
  122. .Run(PickUpStep.UnlockTransporterClamp, () => { return _unlockRoutine.Start(null) == RState.Running; }, NullFun, _delay_1ms)
  123. .WaitWithStopCondition(PickUpStep.UnlockTransporterClampWait, () => CommonFunction.CheckRoutineEndState(_unlockRoutine),
  124. CheckUnlockRoutineStopStatus)
  125. //.WaitWithStopCondition(PickUpStep.CellClampRetractWait,CheckCellRetractRoutineEndState,CheckGantryPositionRunStop)
  126. .LoopRetryStart(PickUpStep.LoopPickupRetry,"Pick up loop retry",_pickMaxRetries,NullFun,_delay_1ms)
  127. .LoopRetrySecondRun(PickUpStep.LoopRetryUnlock, () => { return _unlockRoutine.Start(null) == RState.Running; }, NullFun, _delay_1ms)
  128. .LoopRetrySecondRunWithStopStatus(PickUpStep.LoopRetryUnlockWait, () => CommonFunction.CheckRoutineEndState(_unlockRoutine),
  129. CheckUnlockRoutineStopStatus)
  130. .LoopRetrySecondRun(PickUpStep.LoopRetryBackToLow,ElevatorGotoLow,NullFun,_delay_1ms)
  131. .LoopRetrySecondRunWithStopStatus(PickUpStep.LoopRetryBackToLowWait, CheckVerticalPositionStatus, CheckVerticalPositionRunStop)
  132. //1.4 Elevator 移动至cell
  133. .LoopRetryRun(PickUpStep.ElevatorPosition, () => { return VerticalPositionToCell(); }, NullFun, _delay_1ms)
  134. .LoopRetryRunWithStopStatus(PickUpStep.ElevatorPositionWait, CheckVerticalPositionStatus, CheckVerticalPositionRunStop)
  135. .LoopRetryDelay(PickUpStep.Delay,500)
  136. //1.5 确认Ready to Lock Sensor
  137. .LoopRetryWaitBack(PickUpStep.ReadyToLockCheck,CheckReadyToLock,_delay_1s)
  138. //1.6 Unlock Transporter clamp
  139. .LoopRetryRun(PickUpStep.LockTransporterClamp, () => { return _lockRoutine.Start(null) == RState.Running; }, NullFun, _delay_1ms)
  140. .LoopRetryRunWithStopStatusBack(PickUpStep.LockTransporterClampWait, () => { return CommonFunction.CheckRoutineEndState(_lockRoutine); },
  141. CheckLockRoutineStopStatus)
  142. .LoopRetryEnd(PickUpStep.LoopPickupRetryEnd, _delay_1ms)
  143. //1.7 确认Elevator lift speed
  144. .Run(PickUpStep.CalculateLiftupSpeed,CalculateLiftupSpeed,_delay_1ms)
  145. //1.8 Pickup delay
  146. .Delay(PickUpStep.PickupDelay,_pickupDelayTime*1000)
  147. //1.9 Elevator goto Up
  148. .Run(PickUpStep.VerticalUp, ElevatorGotoUP, 100)
  149. .WaitWithStopCondition(PickUpStep.VerticalUpWait, CheckVerticalPositionStatus, CheckVerticalPositionRunStop)
  150. //2.0 Material Tracking Update
  151. .Run(PickUpStep.UpdateWaferHolder, WaferHolderTransfer,_delay_1ms)
  152. //2.0 确认WSPresent与Lock
  153. .Wait(PickUpStep.CheckWHPresentAndLock,CheckWHPresentAndLock,_delay_2s)
  154. //2.1 Read Barcode 确认与Material Tracking的转移是否一致
  155. //.Run(PickUpStep.ReadBarcodeConfirm,ReadBarcode,_delay_1ms)
  156. .End(PickUpStep.End,NullFun,100);
  157. return Runner.Status;
  158. }
  159. /// <summary>
  160. /// 目标cell unclamp
  161. /// </summary>
  162. /// <returns></returns>
  163. private bool TargetCellUnclamp()
  164. {
  165. if (_cellName == "Loader")
  166. {
  167. bool result= _preTransferUnclampRoutine.Start() == RState.Running;
  168. if(!result)
  169. {
  170. NotifyError(eEvent.ERR_TRANSPORTER, "Loader Unclamp failed",0);
  171. }
  172. return result;
  173. }
  174. else
  175. {
  176. _cellItem = ProcessLayoutManager.Instance.GetProcessLayoutCellItemByModuleName(_cellName);
  177. if(_cellItem!=null)
  178. {
  179. bool result = false;
  180. if(Enum.TryParse(_cellItem.ModuleName,out ModuleName cellModuleName))
  181. {
  182. if (ModuleHelper.IsRinse(cellModuleName))
  183. {
  184. RinseDevice rinseDevice = DEVICE.GetDevice<RinseDevice>(_cellItem.ModuleName);
  185. if (rinseDevice != null)
  186. {
  187. result= rinseDevice.WaferHolderClampValveOff();
  188. if(!result)
  189. {
  190. NotifyError(eEvent.ERR_TRANSPORTER, $"{_cellItem.ModuleName} Clamp off failed", 0);
  191. }
  192. return result;
  193. }
  194. }
  195. else if (ModuleHelper.IsMetal(cellModuleName))
  196. {
  197. MetalCellDevice metalCellDevice = DEVICE.GetDevice<MetalCellDevice>(_cellItem.ModuleName);
  198. if (metalCellDevice != null)
  199. {
  200. result= metalCellDevice.WaferHolderClampOff();
  201. if (!result)
  202. {
  203. NotifyError(eEvent.ERR_TRANSPORTER, $"{_cellItem.ModuleName} Clamp off failed",0);
  204. }
  205. return result;
  206. }
  207. }
  208. }
  209. }
  210. }
  211. return true;
  212. }
  213. /// <summary>
  214. /// 目标Cell Unclamp状态
  215. /// </summary>
  216. /// <returns></returns>
  217. private bool TargetCellUnclampEndStatus()
  218. {
  219. if (_cellName == "Loader")
  220. {
  221. return CommonFunction.CheckRoutineEndState(_preTransferUnclampRoutine);
  222. }
  223. else
  224. {
  225. _cellItem = ProcessLayoutManager.Instance.GetProcessLayoutCellItemByModuleName(_cellName);
  226. if (_cellItem != null)
  227. {
  228. if (Enum.TryParse(_cellItem.ModuleName, out ModuleName cellModuleName))
  229. {
  230. if (ModuleHelper.IsRinse(cellModuleName))
  231. {
  232. RinseDevice rinseDevice = DEVICE.GetDevice<RinseDevice>(_cellItem.ModuleName);
  233. if (rinseDevice != null)
  234. {
  235. return !rinseDevice.RinseData.WaferHolderClamp;
  236. }
  237. }
  238. else if (ModuleHelper.IsMetal(cellModuleName))
  239. {
  240. MetalCellDevice metalCellDevice = DEVICE.GetDevice<MetalCellDevice>(_cellItem.ModuleName);
  241. if (metalCellDevice != null)
  242. {
  243. return metalCellDevice.ClampOff;
  244. }
  245. }
  246. }
  247. }
  248. }
  249. return true;
  250. }
  251. /// <summary>
  252. /// 目标Cell Unclamp运行中止状态
  253. /// </summary>
  254. /// <returns></returns>
  255. private bool TargetCellUnclampStopStatus()
  256. {
  257. if (_cellName == "Loader")
  258. {
  259. bool result= CommonFunction.CheckRoutineStopState(_preTransferUnclampRoutine);
  260. if (result)
  261. {
  262. NotifyError(eEvent.ERR_TRANSPORTER, "Loader Unclamp failed", 0);
  263. }
  264. return result;
  265. }
  266. return false;
  267. }
  268. /// <summary>
  269. /// Elevator运动至LOW
  270. /// </summary>
  271. /// <returns></returns>
  272. private bool ElevatorGotoLow()
  273. {
  274. bool result = _elevatorAxis.PositionStation("LOW");
  275. if(!result)
  276. {
  277. NotifyError(eEvent.ERR_TRANSPORTER, "Elevator goto LOW failed",0);
  278. }
  279. return result;
  280. }
  281. /// <summary>
  282. /// 安全避障移动
  283. /// </summary>
  284. /// <returns></returns>
  285. private bool SafeMoveTo()
  286. {
  287. _cellItem = ProcessLayoutManager.Instance.GetProcessLayoutCellItemByModuleName(_cellName);
  288. string stationName = _cellName;
  289. if (_cellItem != null)
  290. {
  291. if (_cellName.ToLower() != "loader" && _cellName.ToLower() != "park")
  292. {
  293. stationName = $"Cell{_cellItem.CellId}";
  294. }
  295. }
  296. else
  297. {
  298. NotifyError(eEvent.ERR_TRANSPORTER, $"{_cellName} not in layout", 0);
  299. return false;
  300. }
  301. var result = _gantryAxis.GetPositionByStation(stationName);
  302. if(result.success)
  303. {
  304. bool isPositive = false;
  305. if(_gantryAxis.MotionData.MotorPosition<result.position)
  306. {
  307. isPositive = true;
  308. }
  309. return _conflictRoutine.Start(result.position, isPositive) == RState.Running;
  310. }
  311. else
  312. {
  313. NotifyError(eEvent.ERR_TRANSPORTER, $"{_cellName} not in station list",0);
  314. return false;
  315. }
  316. }
  317. /// <summary>
  318. /// 检验安全避让异常结束状态
  319. /// </summary>
  320. /// <returns></returns>
  321. private bool CheckSafeMoveToStopStatus()
  322. {
  323. bool result = CommonFunction.CheckRoutineStopState(_conflictRoutine);
  324. if (result)
  325. {
  326. NotifyError(eEvent.ERR_TRANSPORTER, "Safe Move failed", 0);
  327. }
  328. return result;
  329. }
  330. /// <summary>
  331. /// Gantry Position To cell
  332. /// </summary>
  333. /// <returns></returns>
  334. private bool GantryPositionToCell()
  335. {
  336. _cellItem= ProcessLayoutManager.Instance.GetProcessLayoutCellItemByModuleName(_cellName);
  337. bool result = false;
  338. if (_cellItem != null)
  339. {
  340. if (_cellName.ToLower() != "loader"&&_cellName.ToLower()!="park")
  341. {
  342. result= _gantryAxis.PositionStation($"Cell{_cellItem.CellId}", false);
  343. }
  344. else
  345. {
  346. result= _gantryAxis.PositionStation(_cellName,false);
  347. }
  348. if (!result)
  349. {
  350. NotifyError(eEvent.ERR_TRANSPORTER, "gantry axis motion failed", 0);
  351. }
  352. return result;
  353. }
  354. else
  355. {
  356. NotifyError(eEvent.ERR_TRANSPORTER, $"{_cellName} not in layout", 0);
  357. return false;
  358. }
  359. }
  360. /// <summary>
  361. /// Elevator Position to cell
  362. /// </summary>
  363. /// <returns></returns>
  364. private bool VerticalPositionToCell()
  365. {
  366. bool result = false;
  367. if( _cellItem != null )
  368. {
  369. if (_cellName.ToLower()!="loader")
  370. {
  371. result= _elevatorAxis.PositionStation($"Cell{_cellItem.CellId}", false);
  372. }
  373. else
  374. {
  375. result= _elevatorAxis.PositionStation(_cellName, false);
  376. }
  377. if (!result)
  378. {
  379. NotifyError(eEvent.ERR_TRANSPORTER, "elevator axis motion failed", 0);
  380. }
  381. return result;
  382. }
  383. else
  384. {
  385. NotifyError(eEvent.ERR_TRANSPORTER, $"{_cellName} not in layout",0);
  386. return false;
  387. }
  388. }
  389. /// <summary>
  390. /// 检验Vertical移动状态
  391. /// </summary>
  392. /// <returns></returns>
  393. private bool CheckVerticalPositionStatus()
  394. {
  395. return _elevatorAxis.Status == RState.End;
  396. }
  397. /// <summary>
  398. /// 检验Vertical是否还在运动
  399. /// </summary>
  400. /// <returns></returns>
  401. private bool CheckVerticalPositionRunStop()
  402. {
  403. bool result = _elevatorAxis.Status == RState.Failed || _elevatorAxis.Status == RState.Timeout ;
  404. if (result)
  405. {
  406. NotifyError(eEvent.ERR_TRANSPORTER, "elevator axis motion failed",0);
  407. }
  408. return result;
  409. }
  410. /// <summary>
  411. /// 检验Gantry移动状态
  412. /// </summary>
  413. /// <returns></returns>
  414. private bool CheckGantryPositionStatus()
  415. {
  416. return _gantryAxis.Status == RState.End;
  417. }
  418. /// <summary>
  419. /// 检验Gantry是否还在运动
  420. /// </summary>
  421. /// <returns></returns>
  422. private bool CheckGantryPositionRunStop()
  423. {
  424. bool result= _gantryAxis.Status == RState.Failed||_gantryAxis.Status==RState.Timeout;
  425. if(result)
  426. {
  427. NotifyError(eEvent.ERR_TRANSPORTER, "Gantry Motion failed", 0);
  428. }
  429. return result;
  430. }
  431. /// <summary>
  432. /// 检验Unlock异常状态
  433. /// </summary>
  434. /// <returns></returns>
  435. private bool CheckUnlockRoutineStopStatus()
  436. {
  437. bool result = CommonFunction.CheckRoutineStopState(_unlockRoutine);
  438. if (result)
  439. {
  440. NotifyError(eEvent.ERR_TRANSPORTER, "unlock failed", 0);
  441. }
  442. return result;
  443. }
  444. /// <summary>
  445. /// 检验Ready to lock
  446. /// </summary>
  447. /// <returns></returns>
  448. private bool CheckReadyToLock()
  449. {
  450. if(! _transporterCommon.TransporterData.ReadyToLock1)
  451. {
  452. NotifyError(eEvent.WARN_TRANSPORTER, $"{Module} Ready to lock1 is off",0);
  453. return false;
  454. }
  455. if (!_transporterCommon.TransporterData.ReadyToLock2)
  456. {
  457. NotifyError(eEvent.WARN_TRANSPORTER, $"{Module} Ready to lock2 is off",0);
  458. return false;
  459. }
  460. return true;
  461. }
  462. /// <summary>
  463. /// 检验Lock Routine异常状态
  464. /// </summary>
  465. /// <returns></returns>
  466. private bool CheckLockRoutineStopStatus()
  467. {
  468. bool result = CommonFunction.CheckRoutineStopState(_lockRoutine);
  469. if(result)
  470. {
  471. NotifyError(eEvent.WARN_TRANSPORTER, "lock failed", 0);
  472. }
  473. return result;
  474. }
  475. /// <summary>
  476. /// 计算提升速度
  477. /// </summary>
  478. /// <returns></returns>
  479. private bool CalculateLiftupSpeed()
  480. {
  481. if(_pickupTime==0)
  482. {
  483. return true;
  484. }
  485. BeckhoffStationAxis stationAxis = BeckhoffStationLocationManager.Instance.GetStationAxis(Module, "Elevator", 0);
  486. Station upStation = stationAxis.Stations.Find(O => O.Name.EndsWith("UP"));
  487. Station cellStation = null;
  488. if (_cellName == "Loader")
  489. {
  490. cellStation = stationAxis.Stations.Find(O => O.Name.EndsWith("Loader"));
  491. }
  492. else
  493. {
  494. cellStation = stationAxis.Stations.Find(O => O.Name.EndsWith($"Cell{_cellItem.CellId}"));
  495. }
  496. if(upStation==null)
  497. {
  498. NotifyError(eEvent.ERR_TRANSPORTER, "UP is not in Station List",0);
  499. return false;
  500. }
  501. if(cellStation==null)
  502. {
  503. NotifyError(eEvent.ERR_TRANSPORTER, $"Cell{_cellItem.CellId} is not in Station List",0);
  504. return false;
  505. }
  506. if(!double.TryParse(cellStation.Position,out double cellStationPosition))
  507. {
  508. NotifyError(eEvent.ERR_TRANSPORTER, $"Cell{_cellItem.CellId} Station Position is invalid",0);
  509. return false;
  510. }
  511. if (!double.TryParse(upStation.Position, out double upStationPosition))
  512. {
  513. NotifyError(eEvent.ERR_TRANSPORTER, $"Cell{_cellItem.CellId} Station Position is invalid", 0);
  514. return false;
  515. }
  516. int distance =(int)Math.Round(Math.Abs(cellStationPosition - upStationPosition));
  517. double tmpVelocity = (double) distance/ _pickupTime;
  518. _velocity = _elevatorAxis.CalculateMultiplySpeedRatio(_elevatorAxis.CalculateValueMultiplyScale(tmpVelocity));
  519. double tmpAccelaration = (double)(2 * distance) / Math.Pow(_pickupTime, 2);
  520. _acceleration = _elevatorAxis.CalculateMultiplyAccelerationRatio(_elevatorAxis.CalculateValueMultiplyScale(tmpAccelaration));
  521. LOG.WriteBackgroundLog(eEvent.INFO_TRANSPORTER, Module, "adjust profile speed");
  522. return true;
  523. }
  524. /// <summary>
  525. /// Elevator运动至UP
  526. /// </summary>
  527. /// <returns></returns>
  528. private bool ElevatorGotoUP()
  529. {
  530. bool result= _elevatorAxis.PositionStation("UP", false, _velocity, _acceleration, _acceleration);
  531. if(!result)
  532. {
  533. NotifyError(eEvent.ERR_TRANSPORTER, "elevator goto up failed",0);
  534. }
  535. return result;
  536. }
  537. /// <summary>
  538. /// 更新WaferHolder移动信息
  539. /// </summary>
  540. /// <returns></returns>
  541. private bool WaferHolderTransfer()
  542. {
  543. bool isMetal = false;
  544. DateTime lastMetalRecipeTime = DateTime.Now;
  545. if(Enum.TryParse(_cellName,out ModuleName moduleName)&&ModuleHelper.IsMetal(moduleName))
  546. {
  547. isMetal = true;
  548. WaferHolderInfo info = WaferHolderManager.Instance.GetWaferHolder(_cellName);
  549. if (info != null)
  550. {
  551. lastMetalRecipeTime = info.LastMetalRecipeCompleteTime;
  552. }
  553. }
  554. bool result= WaferHolderManager.Instance.TransferWaferHolder(Module,_cellName, Module);
  555. if (!result)
  556. {
  557. NotifyError(eEvent.ERR_TRANSPORTER, "tranfer waferHolder message failed", 0);
  558. }
  559. else
  560. {
  561. if (!Singleton<RouteManager>.Instance.IsAutoRunning)
  562. {
  563. return true;
  564. }
  565. WaferHolderInfo waferHolderInfo = WaferHolderManager.Instance.GetWaferHolder(Module);
  566. if (waferHolderInfo == null)
  567. {
  568. return true;
  569. }
  570. string strTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
  571. waferHolderInfo.SchedulerModules.Add($"{strTime} {_cellName} => {Module}");
  572. if (isMetal)
  573. {
  574. int waferShuttleSoakMaxTime = SC.GetValue<int>("Metal.WaferShuttleSoakMaxTime");
  575. double soakTime = Math.Round(DateTime.Now.Subtract(lastMetalRecipeTime).TotalMinutes,2);
  576. if (soakTime > waferShuttleSoakMaxTime)
  577. {
  578. LOG.WriteLog(eEvent.WARN_METAL, _cellName, $"time of {waferHolderInfo.Id} soak in metal is {soakTime} minute over {waferShuttleSoakMaxTime}");
  579. }
  580. else
  581. {
  582. LOG.WriteLog(eEvent.INFO_METAL, _cellName, $"time of {waferHolderInfo.Id} soak in metal is {soakTime} minute");
  583. }
  584. }
  585. }
  586. return result;
  587. }
  588. /// <summary>
  589. /// 检验WHPresent与Lock状态
  590. /// </summary>
  591. /// <returns></returns>
  592. private bool CheckWHPresentAndLock()
  593. {
  594. bool locked = _transporterCommon.TransporterData.Locked1 && _transporterCommon.TransporterData.Locked2;
  595. bool whPresent= _transporterCommon.TransporterData.WhPresent1 && _transporterCommon.TransporterData.WhPresent2;
  596. bool result= locked && (whPresent||_bypassWaferHolderPresent);
  597. if (!result)
  598. {
  599. NotifyError(eEvent.ERR_TRANSPORTER, "check wafer Shuttle present and locked failed", 0);
  600. }
  601. return result;
  602. }
  603. /// <summary>
  604. /// 读取条码
  605. /// </summary>
  606. /// <returns></returns>
  607. private bool ReadBarcode()
  608. {
  609. string str=_transporterCommon.ReaderBarcode();
  610. str = str.Trim();
  611. if(!string.IsNullOrEmpty(str))
  612. {
  613. TransporterEntity transporterEntity = Singleton<RouteManager>.Instance.GetModule<TransporterEntity>(Module.ToString());
  614. if (transporterEntity == null)
  615. {
  616. return true;
  617. }
  618. WaferHolderInfo waferHolderInfo = transporterEntity.WaferHolderInfo;
  619. if (waferHolderInfo == null)
  620. {
  621. return true;
  622. }
  623. if (waferHolderInfo.Id == str)
  624. {
  625. return true;
  626. }
  627. WaferHolderManager.Instance.SwitchWaferHolderId(waferHolderInfo,Module,str);
  628. return true;
  629. }
  630. return true;
  631. }
  632. /// <summary>
  633. /// 启动
  634. /// </summary>
  635. /// <param name="objs"></param>
  636. /// <returns></returns>
  637. public RState Start(params object[] objs)
  638. {
  639. _cellName = objs[0].ToString();
  640. _elevatorAxis = DEVICE.GetDevice<JetAxisBase>($"{Module}.Elevator");
  641. _gantryAxis = DEVICE.GetDevice<JetAxisBase>($"{Module}.Gantry");
  642. _loaderEntity = Singleton<RouteManager>.Instance.GetModule<LoaderEntity>(ModuleName.Loader1.ToString());
  643. _loaderRotationAxis = DEVICE.GetDevice<JetAxisBase>($"{ModuleName.Loader1}.Rotation");
  644. _facilities = DEVICE.GetDevice<SystemFacilities>("System.Facilities");
  645. _unlockRoutine = new TransporterUnlockRoutine(Module);
  646. _lockRoutine = new TransporterLockRoutine(Module);
  647. _conflictRoutine = new TransporterConflictRoutine(Module);
  648. _transporterCommon = DEVICE.GetDevice<TransporterCommon>($"{Module}.Common");
  649. _loaderCommonDevice = DEVICE.GetDevice<LoaderCommonDevice>($"{ModuleName.Loader1}.Common");
  650. _bypassWaferHolderPresent = SC.GetValue<bool>("Transporter.BypassWaferHolderPresent");
  651. _preTransferUnclampRoutine = new LoaderPreTransferUnclampRoutine(ModuleName.Loader1.ToString());
  652. _velocity = 0;
  653. _acceleration = 0;
  654. _pickMaxRetries = SC.GetValue<int>("Transporter.MaxPickTries");
  655. string preConfig = SC.GetConfigPreContent(_cellName);
  656. if (SC.ContainsItem($"{preConfig}.PickTimeSeconds"))
  657. {
  658. _pickupTime = SC.GetValue<int>($"{preConfig}.PickTimeSeconds");
  659. }
  660. if (SC.ContainsItem($"{preConfig}.PickDelaySeconds"))
  661. {
  662. _pickupDelayTime = SC.GetValue<int>($"{preConfig}.PickDelaySeconds");
  663. }
  664. return Runner.Start(Module, $"PickUpFrom {_cellName}");
  665. }
  666. /// <summary>
  667. /// 启动校验条件
  668. /// </summary>
  669. /// <returns></returns>
  670. private bool CheckStartPreConfition()
  671. {
  672. bool result = CheckPreCondition();
  673. if(!result)
  674. {
  675. return false;
  676. }
  677. double elevatorPosition = _elevatorAxis.MotionData.MotorPosition;
  678. if (!_elevatorAxis.CheckPositionIsInStation(elevatorPosition, "Up") &&
  679. !_elevatorAxis.CheckPositionIsInStation(elevatorPosition, "Low"))
  680. {
  681. NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} elevator axis {elevatorPosition} is not in Up or Low station",-1);
  682. return false;
  683. }
  684. if (!_loaderEntity.IsHomed)
  685. {
  686. NotifyError(eEvent.ERR_TRANSPORTER, $"{ModuleName.Loader1} is not homed",-1);
  687. return false;
  688. }
  689. if (_cellName == "Loader")
  690. {
  691. double loaderRotationPosition = _loaderRotationAxis.MotionData.MotorPosition;
  692. if (!_loaderRotationAxis.CheckPositionIsInStation(loaderRotationPosition, "TRNPA") &&
  693. !_loaderRotationAxis.CheckPositionIsInStation(loaderRotationPosition, "TRNPB"))
  694. {
  695. NotifyError(eEvent.ERR_TRANSPORTER, $"{ModuleName.Loader1} rotation axis {loaderRotationPosition} is not int TRNPA or TRNPB station",-1);
  696. return false;
  697. }
  698. }
  699. if (!WaferHolderManager.Instance.HasWaferHolder(_cellName))
  700. {
  701. NotifyError(eEvent.ERR_TRANSPORTER, $"{_cellName} does not has wafer Shuttle", -1);
  702. return false;
  703. }
  704. //检验Facilities
  705. var faciltiesResult = _facilities.CheckCDA();
  706. if (!faciltiesResult.result)
  707. {
  708. NotifyError(eEvent.ERR_TRANSPORTER, faciltiesResult.reason,-1);
  709. return false;
  710. }
  711. return true;
  712. }
  713. /// <summary>
  714. /// 检验前置条件
  715. /// </summary>
  716. /// <returns></returns>
  717. private bool CheckPreCondition()
  718. {
  719. if (!_gantryAxis.IsSwitchOn)
  720. {
  721. NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} gantry axis is not switch on ", -1);
  722. return false;
  723. }
  724. if (!_gantryAxis.IsHomed)
  725. {
  726. NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} gantry axis is not homed ",-1);
  727. return false;
  728. }
  729. if (!_elevatorAxis.IsSwitchOn)
  730. {
  731. NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} elevator axis is not switch on ", -1);
  732. return false;
  733. }
  734. if (!_elevatorAxis.IsHomed)
  735. {
  736. NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} elevator axis is not homed ",-1);
  737. return false;
  738. }
  739. return true;
  740. }
  741. }
  742. }