BrooksMag7RobotSimulator.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.Timers;
  5. using MECF.Framework.Simulator.Core.SubstrateTrackings;
  6. namespace MECF.Framework.Simulator.Core.Robots
  7. {
  8. public class BrooksMag7RobotSimulator : RobotSimulator
  9. {
  10. protected Random _rd = new Random();
  11. public bool Failed { get; set; }
  12. public string ErrorCode { get; set; }
  13. public bool EventChecked { get; set; }
  14. public string EventCode { get; set; }
  15. public override Dictionary<string, double> MoveTimes
  16. {
  17. get { return moveTimes; }
  18. set { moveTimes = value; }
  19. }
  20. public override ReadOnlyCollection<string> Arms
  21. {
  22. get { return arms; }
  23. }
  24. //private static string source = "BrooksMag7";
  25. private static string msgDone = "_RDY";
  26. private static string msgError = "_ERR";
  27. private readonly string armAPan1 = "VTM.ArmA.Left";
  28. private readonly string armAPan2 = "VTM.ArmA.Right";
  29. private readonly string armBPan1 = "VTM.ArmB.Left";
  30. private readonly string armBPan2 = "VTM.ArmB.Right";
  31. private System.Timers.Timer timer;
  32. private string currentStation;
  33. private string newLocation;
  34. private string currentArm;
  35. private string newArm = "";
  36. private string lastMsg;
  37. private Dictionary<string, double> moveTimes;
  38. private ReadOnlyCollection<string> arms;
  39. public BrooksMag7RobotSimulator(int port = 1102) : base(port, 0, "\r", ' ', 5)
  40. {
  41. List<string> armsList = new List<string>();
  42. armsList.Add(armAPan1);
  43. armsList.Add(armAPan2);
  44. armsList.Add(armBPan1);
  45. armsList.Add(armBPan2);
  46. arms = new ReadOnlyCollection<string>(armsList);
  47. // create the message handling dictionary
  48. AddCommandHandler("HOME", HandleHome);
  49. AddCommandHandler("PICK", HandlePick);
  50. AddCommandHandler("PLACE", HandlePlace);
  51. AddCommandHandler("GOTO", HandleGoto);
  52. AddCommandHandler("SWAP", HandleExchange);
  53. AddCommandHandler("RQ", HandleRequest);
  54. AddCommandHandler("Unknown", HandleUnknown);
  55. //AddCommandHandler("SVON", HandleSVON);
  56. // AddCommandHandler("SVOFF", HandleSVOFF);
  57. timer = new System.Timers.Timer();
  58. timer.Enabled = false;
  59. timer.AutoReset = false;
  60. timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
  61. // Default move times based on Brooks spreadsheet
  62. moveTimes = new Dictionary<string, double>();
  63. moveTimes["PickPlace"] = 2.8;
  64. moveTimes["Move90Degrees"] = 1.69;
  65. moveTimes["Move180Degrees"] = 2.11;
  66. moveTimes["HeightAdjust"] = 0.9;
  67. moveTimes["ExtendRetract"] = 1.3;
  68. moveTimes["WaferFactor"] = 1.0;
  69. moveTimes["SwapAtPM"] = 7.3;
  70. // Original default times based on Brooks log files
  71. //moveTimes["PickPlace"] = 3.2;
  72. //moveTimes["Move90Degrees"] = 1.5;
  73. //moveTimes["Move180Degrees"] = 1.9;
  74. //moveTimes["HeightAdjust"] = 0.9;
  75. //moveTimes["ExtendRetract"] = 1.2;
  76. //moveTimes["WaferFactor"] = 1.15;
  77. currentArm = "A";
  78. currentStation = "Unknown";
  79. }
  80. internal void HandleSVON(string msg)
  81. {
  82. if (ErrorMessage == "SVON Failed")
  83. {
  84. HandleError(ErrorMessage);
  85. return;
  86. }
  87. string[] cmdComponents = msg.Split(_msgDelimiter);
  88. if (cmdComponents.Length != 1)
  89. {
  90. HandleError("Invalid SVON command (arguments)");
  91. return;
  92. }
  93. HandleMove(RobotStateEnum.SVON, cmdComponents);
  94. }
  95. internal void HandleSVOFF(string msg)
  96. {
  97. if (ErrorMessage == "SVOFF Failed")
  98. {
  99. HandleError(ErrorMessage);
  100. return;
  101. }
  102. string[] cmdComponents = msg.Split(_msgDelimiter);
  103. if (cmdComponents.Length != 1)
  104. {
  105. HandleError("Invalid SVOFF command (arguments)");
  106. return;
  107. }
  108. HandleMove(RobotStateEnum.SVOFF, cmdComponents);
  109. }
  110. internal void HandleHome(string msg)
  111. {
  112. if (ErrorMessage == "Home Failed")
  113. {
  114. HandleError(ErrorMessage);
  115. return;
  116. }
  117. string[] cmdComponents = msg.Split(_msgDelimiter);
  118. if (cmdComponents.Length != 2)
  119. {
  120. HandleError("Invalid homing command (arguments)");
  121. return;
  122. }
  123. HandleMove(RobotStateEnum.Homing, cmdComponents);
  124. }
  125. internal void HandlePick(string msg)
  126. {
  127. msg = msg.Trim();
  128. if (ErrorMessage == "Pick Failed")
  129. {
  130. HandleError(ErrorMessage);
  131. return;
  132. }
  133. if (Failed && !string.IsNullOrEmpty(ErrorCode))
  134. {
  135. HandleError(ErrorMessage);
  136. return;
  137. }
  138. if (EventChecked && !string.IsNullOrEmpty(EventCode))
  139. {
  140. HandleEvent(EventCode);
  141. return;
  142. }
  143. string[] cmdComponents = msg.Split(_msgDelimiter);
  144. if (cmdComponents.Length != 6 && cmdComponents.Length != 8 && cmdComponents.Length != 10)
  145. {
  146. HandleError("Invalid pick command (arguments)");
  147. return;
  148. }
  149. RobotStateEnum rs = RobotStateEnum.Picking;
  150. if (cmdComponents.Length > 6 && cmdComponents[6] == "ENRT")
  151. rs = RobotStateEnum.Extending;
  152. else if (cmdComponents.Length > 6 && cmdComponents[6] == "STRT")
  153. rs = RobotStateEnum.Retracting;
  154. lastMsg = msg;
  155. HandleMove(rs, cmdComponents);
  156. }
  157. internal void HandlePlace(string msg)
  158. {
  159. msg = msg.Trim();
  160. if (ErrorMessage == "Place Failed")
  161. {
  162. HandleError(ErrorMessage);
  163. return;
  164. }
  165. if (Failed && !string.IsNullOrEmpty(ErrorCode))
  166. {
  167. HandleError(ErrorMessage);
  168. return;
  169. }
  170. if (EventChecked && !string.IsNullOrEmpty(EventCode))
  171. {
  172. HandleEvent(EventCode);
  173. return;
  174. }
  175. string[] cmdComponents = msg.Split(_msgDelimiter);
  176. if (cmdComponents.Length != 6 && cmdComponents.Length != 8 && cmdComponents.Length != 10)
  177. {
  178. HandleError("Invalid place command (arguments)");
  179. return;
  180. }
  181. RobotStateEnum rs = RobotStateEnum.Placing;
  182. if (cmdComponents.Length > 6 && cmdComponents[6] == "ENRT")
  183. rs = RobotStateEnum.Extending;
  184. else if (cmdComponents.Length > 6 && cmdComponents[6] == "STRT")
  185. rs = RobotStateEnum.Retracting;
  186. lastMsg = msg;
  187. HandleMove(rs, cmdComponents);
  188. }
  189. internal void HandleExchange(string msg)
  190. {
  191. if (ErrorMessage == "Swap Failed" || ErrorMessage == "Place Failed" || ErrorMessage == "Pick Failed")
  192. {
  193. HandleError(ErrorMessage);
  194. return;
  195. }
  196. string[] cmdComponents = msg.Split(_msgDelimiter);
  197. if (cmdComponents.Length != 4)
  198. {
  199. HandleError("Invalid swap command (arguments)");
  200. return;
  201. }
  202. lastMsg = msg;
  203. HandleMove(RobotStateEnum.Exchanging, cmdComponents);
  204. }
  205. internal void HandleRequest(string msg)
  206. {
  207. string[] components = msg.Split(_msgDelimiter);
  208. string reply = components[1];
  209. if (components[1] == "WAFER" && components[2] == "PRESENT")
  210. reply += " " + components[2] + GetArmStates();
  211. else if (components[1] == "ERRMSG")
  212. reply = LookupError(components[2]);
  213. OnWriteMessage(reply);
  214. OnWriteMessage(msgDone);
  215. }
  216. internal void HandleUnknown(string msg)
  217. {
  218. OnWriteMessage(msgDone);
  219. }
  220. internal void HandleGoto(string msg)
  221. {
  222. string[] cmdComponents = msg.Split(_msgDelimiter);
  223. if (cmdComponents.Length != 11)
  224. {
  225. HandleError("Invalid move command (arguments)");
  226. return;
  227. }
  228. HandleMove(RobotStateEnum.Approaching, cmdComponents);
  229. }
  230. private bool HandleMove(RobotStateEnum action, string[] cmdComponents)
  231. {
  232. if (robotStateArgs.State != RobotStateEnum.Idle &&
  233. (action == RobotStateEnum.Homing && robotStateArgs.State != RobotStateEnum.Errored)) // allow homes when in error, but not other moves
  234. {
  235. HandleError("Already moving");
  236. return false;
  237. }
  238. newLocation = "Unknown";
  239. switch (action)
  240. {
  241. case RobotStateEnum.Picking:
  242. case RobotStateEnum.Placing:
  243. case RobotStateEnum.Approaching:
  244. case RobotStateEnum.Extending:
  245. case RobotStateEnum.Retracting:
  246. case RobotStateEnum.Exchanging:
  247. case RobotStateEnum.SVON:
  248. case RobotStateEnum.SVOFF:
  249. break;
  250. default:
  251. break;
  252. }
  253. if (ErrorMessage != "Pick Failed" && ErrorMessage != "Place Failed" && ErrorMessage != "Home Failed" &&
  254. ErrorMessage != "Swap Failed" && !string.IsNullOrEmpty(ErrorMessage))
  255. {
  256. HandleError(ErrorMessage);
  257. return false;
  258. }
  259. double delay = GetMoveTime(action);
  260. timer.Interval = delay * 1000;
  261. timer.Enabled = true;
  262. return true;
  263. }
  264. private double GetMoveTime(RobotStateEnum action)
  265. {
  266. double rotationTime = 0;
  267. double zMoveTime = 0;
  268. if (newLocation != currentStation)
  269. {
  270. if (currentStation == "LL1" || currentStation == "LL2")
  271. rotationTime = newLocation == "PM2" ? moveTimes["Move180Degrees"] : moveTimes["Move90Degrees"];
  272. else
  273. rotationTime = currentStation == "PM2" ? moveTimes["Move180Degrees"] : moveTimes["Move90Degrees"];
  274. double factor = 1.0;
  275. if (WaferTrack.Instance.IsOccupied(armAPan1) || WaferTrack.Instance.IsOccupied(armAPan2) ||
  276. WaferTrack.Instance.IsOccupied(armBPan1) || WaferTrack.Instance.IsOccupied(armBPan2))
  277. {
  278. factor = moveTimes["WaferFactor"];
  279. }
  280. rotationTime *= factor;
  281. }
  282. else if (newArm != currentArm)
  283. zMoveTime = moveTimes["HeightAdjust"];
  284. switch (action)
  285. {
  286. case RobotStateEnum.Approaching:
  287. if (newLocation == currentStation)
  288. return moveTimes["HeightAdjust"];
  289. return rotationTime;
  290. case RobotStateEnum.Extending:
  291. case RobotStateEnum.Retracting:
  292. return moveTimes["ExtendRetract"] + rotationTime + zMoveTime;
  293. case RobotStateEnum.Picking:
  294. return moveTimes["PickPlace"] + zMoveTime;
  295. case RobotStateEnum.Placing:
  296. if (newLocation.StartsWith("PM"))
  297. return moveTimes["PickPlace"] + zMoveTime;
  298. else
  299. return moveTimes["ExtendRetract"] + rotationTime + zMoveTime;
  300. case RobotStateEnum.Exchanging:
  301. return moveTimes["SwapAtPM"];
  302. default:
  303. return moveTimes["Move90Degrees"];
  304. }
  305. }
  306. private void HandleError(string msg)
  307. {
  308. string errorCode = string.Format("0x{0}", lastError.ToString("x8"));
  309. lastError++;
  310. errorLookup[errorCode] = msg;
  311. OnWriteMessage(msgError + " " + ErrorCode);
  312. OnWriteMessage(msgDone);
  313. }
  314. private void HandleEvent(string msg)
  315. {
  316. // string errorCode = string.Format("0x{0}", lastError.ToString("x8"));
  317. //lastError++;
  318. //errorLookup[errorCode] = msg;
  319. OnWriteMessage(msg);
  320. OnWriteMessage(msgDone);
  321. }
  322. private string GetArmStates()
  323. {
  324. return " N N";
  325. }
  326. private void timer_Elapsed(object sender, ElapsedEventArgs e)
  327. {
  328. currentStation = newLocation;
  329. currentArm = newArm;
  330. if (robotStateArgs.State == RobotStateEnum.Picking || robotStateArgs.State == RobotStateEnum.Placing ||
  331. robotStateArgs.State == RobotStateEnum.Extending || robotStateArgs.State == RobotStateEnum.Exchanging)
  332. {
  333. lastMsg = "";
  334. }
  335. SetRobotState(RobotStateEnum.Idle);
  336. timer.Enabled = false;
  337. OnWriteMessage(msgDone);
  338. }
  339. }
  340. }