TransporterPickUpFromRoutine.cs 29 KB

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