GM201LVPRobot.cs 112 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487
  1. using Aitex.Core.Common;
  2. using Aitex.Core.RT.DataCenter;
  3. using Aitex.Core.RT.Device;
  4. using Aitex.Core.RT.Device.Unit;
  5. using Aitex.Core.RT.Event;
  6. using Aitex.Core.RT.Log;
  7. using Aitex.Core.RT.OperationCenter;
  8. using Aitex.Core.RT.SCCore;
  9. using Aitex.Core.Util;
  10. using MECF.Framework.Common.CommonData;
  11. using MECF.Framework.Common.Communications;
  12. using MECF.Framework.Common.Equipment;
  13. using MECF.Framework.Common.SubstrateTrackings;
  14. using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts.LoadPortBase;
  15. using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot;
  16. using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotBase;
  17. using System;
  18. using System.Collections.Generic;
  19. using System.Diagnostics;
  20. using System.Linq;
  21. using System.Text;
  22. using System.Threading;
  23. using EventType = Aitex.Core.RT.Event.EventType;
  24. namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.HRC100Robots.GM201LVPRobot
  25. {
  26. public class YaskawaRobotMessage : AsciiMessage
  27. {
  28. public int UNo { get; set; }
  29. public int SeqNo { get; set; }
  30. public string Status { get; set; }
  31. public string Ackcd { get; set; }
  32. public string Command { get; set; }
  33. public string[] Data { get; set; }
  34. public string ErrorCode { get; set; }
  35. public string EvNo { get; set; }
  36. public string EvDate { get; set; }
  37. public string EvData { get; set; }
  38. }
  39. public class GM201LVPRobot : RobotBaseDevice, IConnection
  40. {
  41. //public int UnitNumber
  42. //{
  43. // get; private set;
  44. //}
  45. private bool isSimulatorMode;
  46. private string _scRoot;
  47. private bool _isError;
  48. public GM201LVPTokenGenerator SeqnoGenerator { get; private set; }
  49. public bool IsEnableSeqNo { get; private set; }
  50. public bool IsEnableCheckSum { get; private set; }
  51. public int CurrentSeqNo { get; set; }
  52. public string PortName;
  53. private string _address;
  54. private bool _enableLog;
  55. private GM201LVPRobotConnection _connection;
  56. private R_TRIG _trigError = new R_TRIG();
  57. private R_TRIG _trigCommunicationError = new R_TRIG();
  58. private R_TRIG _trigRetryConnect = new R_TRIG();
  59. public string Address => _address;
  60. private PeriodicJob _thread;
  61. private object _locker = new object();
  62. private LinkedList<HandlerBase> _lstHandlers = new LinkedList<HandlerBase>();
  63. private LinkedList<HandlerBase> _lstMonitorHandler = new LinkedList<HandlerBase>();
  64. private IoSensor _diRobotReady = null; //Normal ON
  65. private IoSensor _diRobotBlade1WaferOn = null; //Off when wafer present
  66. private IoSensor _diRobotBlade2WaferOn = null;
  67. private IoSensor _diRobotError = null; //Normal ON
  68. private IoSensor _diTPinUse = null;
  69. private IoTrigger _doRobotHold = null; // Normal ON
  70. public ModuleName CurrentInteractiveModule { get; private set; }
  71. public bool IsConnected => throw new NotImplementedException();
  72. public float CurrentThetaPosition { get; private set; }
  73. public float CurrentExtensionPosition { get; private set; }
  74. public float CurrentArm1Position { get; private set; }
  75. public float CurrentArm2Position { get; private set; }
  76. public float CurrentZPosition { get; private set; }
  77. public float CommandThetaPosition { get; private set; }
  78. public float CommandExtensionPosition { get; private set; }
  79. public float CommandArm1Position { get; private set; }
  80. public float CommandArm2Position { get; private set; }
  81. public float CommandZPosition { get; private set; }
  82. public int SpeedLevel { get; private set; }
  83. public int SpeedLevelSetting => SC.GetValue<int>($"{Name}.RobotSpeed");
  84. public string ReadMemorySpec { get; private set; }
  85. public string ReadTransferStation { get; private set; }
  86. public int ReadSlotNumber { get; private set; }
  87. public string ReadArmPosture { get; private set; }
  88. public RobotArmEnum ReadBladeNo { get; private set; }
  89. public GM201LVPPositonEnum ReadPositionType { get; private set; }
  90. public float ReadThetaPosition { get; private set; }
  91. public float ReadExtensionPosition { get; private set; }
  92. public float ReadArm1Position { get; private set; }
  93. public float ReadArm2Position { get; private set; }
  94. public float ReadZPosition { get; private set; }
  95. public Dictionary<string, string> ReadStationItemValues { get; private set; } = new Dictionary<string, string>();
  96. public Dictionary<string, string> ReadStationItemContents { get; private set; } = new Dictionary<string, string>();
  97. public string ReadParameterType { get; private set; }
  98. public string ReadParameterNo { get; private set; }
  99. public string ReadParameterValue { get; private set; }
  100. public bool IsManipulatorBatteryLow { get; private set; }
  101. public bool IsCommandExecutionReady { get; private set; }
  102. public bool IsServoON { get; private set; }
  103. public bool IsErrorOccurred { get; private set; }
  104. public bool IsControllerBatteryLow { get; private set; }
  105. public bool IsCheckInterlockWaferPresenceOnBlade1 { get; private set; }
  106. public bool IsCheckInterlockWaferPresenceOnBlade2 { get; private set; }
  107. public bool IsCheckInterlockWaferPresenceOnBlade3 { get; private set; }
  108. public bool IsCheckInterlockWaferPresenceOnBlade4 { get; private set; }
  109. public bool IsCheckInterlockWaferPresenceOnBlade5 { get; private set; }
  110. public string RobotSoftwareVersion { get; private set; }
  111. public string ReadMappingTransferStation { get; private set; }
  112. public int ReadMappingSlotNumbers { get; private set; }
  113. public string ReadSlotMap { get; private set; }
  114. public MaterialType _MaterialType { get; set; }
  115. private int _timeLimitPick => SC.GetValue<int>($"{Name}.PickTimeout");
  116. private int _timeLimitPlace => SC.GetValue<int>($"{Name}.PlaceTimeout");
  117. private int _timeLimitHome => SC.GetValue<int>($"{Name}.HomeTimeout");
  118. private int _timeLimitMotion => SC.GetValue<int>($"{Name}.MotionTimeout");
  119. public Dictionary<string, float> ReadMappingCalibrationResult { get; private set; }
  120. public Dictionary<string, string> ReadRobotParameterResult { get; private set; } = new Dictionary<string, string>();
  121. public enum MaterialType
  122. {
  123. Carrier,
  124. Wafer
  125. }
  126. private Dictionary<string, string> _moduleAssociateStationDic;
  127. public override Dictionary<string, string> ModuleAssociateStationDic
  128. {
  129. get
  130. {
  131. return _moduleAssociateStationDic;
  132. }
  133. set
  134. {
  135. _moduleAssociateStationDic = value;
  136. }
  137. }
  138. private Dictionary<string, string> _moduleAssociateHandDic;
  139. public Dictionary<string, string> ModuleAssociateHandDic
  140. {
  141. get
  142. {
  143. return _moduleAssociateHandDic;
  144. }
  145. set
  146. {
  147. _moduleAssociateHandDic = value;
  148. }
  149. }
  150. private IoAlarmSignal _tpStatus = null;
  151. public GM201LVPRobot(string module, string name, string scRoot, MaterialType material, IoSensor[] dis, IoTrigger[] dos) : base(module, name)
  152. {
  153. Module = module;
  154. Name = name;
  155. _MaterialType = material;
  156. isSimulatorMode = SC.ContainsItem("System.IsSimulatorMode") ? SC.GetValue<bool>("System.IsSimulatorMode") : false;
  157. _scRoot = scRoot;
  158. _address = SC.GetStringValue($"{Name}.Address");
  159. _enableLog = SC.GetValue<bool>($"{Name}.EnableLogMessage");
  160. //UnitNumber = SC.GetValue<int>($"{_scRoot}.{Name}.UnitNumber");
  161. //IsEnableCheckSum = SC.GetValue<bool>($"{_scRoot}.{Name}.EnableCheckSum");
  162. //IsEnableSeqNo = SC.GetValue<bool>($"{_scRoot}.{Name}.EnableSeqNo");
  163. //SpeedLevelSetting = SC.GetValue<int>($"{Name}.SpeedLevel");
  164. _connection = new GM201LVPRobotConnection(this, _address);
  165. _connection.EnableLog(_enableLog);
  166. //SeqnoGenerator = new GM201LVPTokenGenerator($"{_scRoot}.{Name}.CommunicationToken");
  167. if (dis != null && dis.Length >= 5)
  168. {
  169. _diRobotReady = dis[0];
  170. _diRobotBlade1WaferOn = dis[1];
  171. _diRobotBlade2WaferOn = dis[2];
  172. _diRobotError = dis[3];
  173. _diTPinUse = dis[4];
  174. _diRobotError.OnSignalChanged += _diRobotError_OnSignalChanged;
  175. _diTPinUse.OnSignalChanged += _diTPinUse_OnSignalChanged;
  176. }
  177. if (dos != null && dos.Length >= 1)
  178. {
  179. _doRobotHold = dos[0];
  180. }
  181. ConnectionManager.Instance.Subscribe($"{Name}", _connection);
  182. _thread = new PeriodicJob(10, OnTimer, $"{Module}.{Name} MonitorHandler", true);
  183. ReadStationItemContents.Add("00", "Upward offset");
  184. ReadStationItemContents.Add("01", "Downward offset");
  185. ReadStationItemContents.Add("02", "Grip position offset");
  186. ReadStationItemContents.Add("06", "G2/P3 offset in the extending direction");
  187. ReadStationItemContents.Add("08", "Put downward offset");
  188. ReadStationItemContents.Add("70", "Get operation Movet_grip function yes/no");
  189. ReadStationItemContents.Add("71", "Get operation rising pattern");
  190. ReadStationItemContents.Add("80", "Put operation Move_grip function yes/no");
  191. ReadStationItemContents.Add("81", "Put operation dropping pattern");
  192. ReadStationItemContents.Add("50", "Slot Numbers");
  193. ReadStationItemContents.Add("30", "Slot pitch(Left elbow,Blade1)");
  194. ReadStationItemContents.Add("31", "Slot pitch(Left elbow,Blade2)");
  195. ReadStationItemContents.Add("32", "Slot pitch(Right elbow,Blade1)");
  196. ReadStationItemContents.Add("33", "Slot pitch(Right elbow,Blade2)");
  197. if (Name == "CarrierRobot")
  198. {
  199. _tpStatus = DEVICE.GetDevice<IoAlarmSignal>($"PM1.AlarmSignaFOUPRobotTPStatusWarning");
  200. }
  201. else
  202. {
  203. _tpStatus = DEVICE.GetDevice<IoAlarmSignal>($"PM1.AlarmSignaWaferRobotTPStatusWarning");
  204. }
  205. ResetPropertiesAndResponses();
  206. RegisterSpecialData();
  207. RegisterAlarm();
  208. }
  209. protected override void SubscribeWaferLocation()
  210. {
  211. }
  212. private void RegisterAlarm()
  213. {
  214. EV.Subscribe(new EventItem("Alarm", $"{Name}Error040", $"{Name} Robot Occurred Error:机械手在 TP 模式中,命令被拒绝。", "机械手在 TP 模式中,命令被拒绝。"));
  215. EV.Subscribe(new EventItem("Alarm", $"{Name}Error041", $"{Name} Robot Occurred Error:机械手在空模式中,命令被拒绝。", "机械手在空模式中,命令被拒绝。"));
  216. EV.Subscribe(new EventItem("Alarm", $"{Name}Error055", $"{Name} Robot Occurred Error:设定无法访问的工位。", "指定了不可访问的工位类型。"));
  217. EV.Subscribe(new EventItem("Alarm", $"{Name}Error057", $"{Name} Robot Occurred Error:运动失败。", "伺服电机执行运动程序失败。"));
  218. EV.Subscribe(new EventItem("Alarm", $"{Name}Error070", $"{Name} Robot Occurred Error:位置未记录完整。", "命令被拒绝,因为此工位没有示教,未记录位置信息。"));
  219. EV.Subscribe(new EventItem("Alarm", $"{Name}Error072", $"{Name} Robot Occurred Error:层数超限。", "机械手运行位置已超出工位层数上限。"));
  220. EV.Subscribe(new EventItem("Alarm", $"{Name}Error073", $"{Name} Robot Occurred Error:禁止轴动作。", "当前轴动作可能会导致碰撞。"));
  221. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*00", $"{Name} Robot Occurred Error:伺服报警。", "控制器判断驱动器有报警。"));
  222. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*01", $"{Name} Robot Occurred Error:伺服警告。", "控制器判断驱动器警告。"));
  223. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*02", $"{Name} Robot Occurred Error:伺服驱动器参数错误1", "伺服单元的参数有误差。"));
  224. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*03", $"{Name} Robot Occurred Error:主回路错误。", "主电路的检测数据有错误。"));
  225. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*04", $"{Name} Robot Occurred Error:伺服驱动器参数错误2。", "伺服参数异常。"));
  226. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*05", $"{Name} Robot Occurred Error:结合误差1。", "连接不支持的设备。"));
  227. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*07", $"{Name} Robot Occurred Error:结合误差2。", "编码器类型不匹配。"));
  228. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*08", $"{Name} Robot Occurred Error:伺服驱动器参数错误3。", "伺服参数异常。"));
  229. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*10", $"{Name} Robot Occurred Error:溢出电流。", "过电流。"));
  230. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*30", $"{Name} Robot Occurred Error:检测到再生错误。", "检测再生电路错误。"));
  231. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*32", $"{Name} Robot Occurred Error:再生过载。", "发生再生过载。"));
  232. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*33", $"{Name} Robot Occurred Error:主电路电源接线错误。", "电源接线不正确。"));
  233. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*40", $"{Name} Robot Occurred Error:过电压。", "驱动器电压过高。"));
  234. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*41", $"{Name} Robot Occurred Error:欠电压。", "驱动器电压过底。"));
  235. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*50", $"{Name} Robot Occurred Error:碰撞检出警报。", "检测到了碰撞发生。"));
  236. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*51", $"{Name} Robot Occurred Error:电机超速。", "电机转速过高。"));
  237. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*52", $"{Name} Robot Occurred Error:振动报警。", "电机转速出现异常振荡。"));
  238. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*55", $"{Name} Robot Occurred Error:伺服驱动器参数错误4。", "伺服参数异常。"));
  239. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*71", $"{Name} Robot Occurred Error:瞬时过载(电机)。", "电机被施加了很大程度上超过额定值的转矩。"));
  240. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*72", $"{Name} Robot Occurred Error:连续过载(电机)。", "一个大大超过额定值的转矩被连续施加。"));
  241. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*73", $"{Name} Robot Occurred Error:动态制动过载。", "超过动态制动电阻容量。"));
  242. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*74", $"{Name} Robot Occurred Error:浪涌限流电阻过载。", "主电路电源经常被打开和关闭。"));
  243. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*7A", $"{Name} Robot Occurred Error:控制器风机停止。", "控制器风扇停止运行。"));
  244. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*7B", $"{Name} Robot Occurred Error:温度传感器电路错误。", "温度传感器电路错误。"));
  245. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*81", $"{Name} Robot Occurred Error:绝对编码器备份错误。", "绝对编码器电池被移除过,位置数据被清除。"));
  246. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*82", $"{Name} Robot Occurred Error:绝对编码器校验错误", "编码器内存的校验和结果有错误。"));
  247. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*83", $"{Name} Robot Occurred Error:绝对编码器的电池电压低。", "绝对值编码器备用电池电压低。"));
  248. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*84", $"{Name} Robot Occurred Error:编码器数据误差。", "编码器内部数据错误。"));
  249. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*85", $"{Name} Robot Occurred Error:编码器速度过快。", "通电时编码器高速旋转。"));
  250. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*86", $"{Name} Robot Occurred Error:编码器过热。", "编码器过热。"));
  251. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*B3", $"{Name} Robot Occurred Error:电流检测错误。", "电流检测电路错误。"));
  252. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*B6", $"{Name} Robot Occurred Error:伺服 M-III 通信错误。", "MECHATROLINK 通信出现错误。"));
  253. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*BF", $"{Name} Robot Occurred Error:系统报警。", "伺服单元内部程序错误。"));
  254. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*C1", $"{Name} Robot Occurred Error:电机失控。", "伺服电机失控。"));
  255. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*C2", $"{Name} Robot Occurred Error:相位信息不匹配。", "相位信息不匹配。"));
  256. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*C5", $"{Name} Robot Occurred Error:极性检测失败。", "极性检测错误。"));
  257. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*C8", $"{Name} Robot Occurred Error:编码器复位错误。", "多回合数据未正确清除或设置。"));
  258. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*C9", $"{Name} Robot Occurred Error:编码器通信错误。", "编码器与伺服单元通信错误。"));
  259. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*CA", $"{Name} Robot Occurred Error:编码器参数错误1。", "编码器中的参数已损坏。"));
  260. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*CB", $"{Name} Robot Occurred Error:编码器参数错误2。", "与编码器通信的内容不正确。"));
  261. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*CC", $"{Name} Robot Occurred Error:编码器参数错误3。", "编码器与驱动器数据不一致。"));
  262. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*D0", $"{Name} Robot Occurred Error:位置偏差错误。", "位置偏差脉冲超过设定值。"));
  263. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*D3", $"{Name} Robot Occurred Error:位置数据溢出。", "反馈数据超过+1,879,048,192。"));
  264. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*D8", $"{Name} Robot Occurred Error:转矩检测异常。", "检测到异常转矩。"));
  265. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*E0", $"{Name} Robot Occurred Error:伺服 M-III 通信错误 2。", "MECHATROLINK 与伺服单元通信时发生同步错误。"));
  266. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*E4", $"{Name} Robot Occurred Error:伺服 M-III 通信错误 3。", "MECHATROLINK 通信设置不正确。"));
  267. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*E5", $"{Name} Robot Occurred Error:伺服 M-III 通信错误 4。", "MECHATROLINK 与伺服单元通信时发生同步错误。"));
  268. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*E6", $"{Name} Robot Occurred Error:伺服 M-III 通信错误 5。", "MECHATROLINK 通信出现错误。"));
  269. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*ED", $"{Name} Robot Occurred Error:伺服 M-III 通信错误 6。", "MECHATROLINK 通信出现错误。"));
  270. EV.Subscribe(new EventItem("Alarm", $"{Name}Error*F1", $"{Name} Robot Occurred Error:相位损失。", "电源缺相。"));
  271. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorE*E", $"{Name} Robot Occurred Error:通信错误(内部控制器)。", "控制器内部通信故障。"));
  272. EV.Subscribe(new EventItem("Alarm", $"{Name}Error930", $"{Name} Robot Occurred Error:未定义的命令收到。", "从主机接收到未定义的命令。"));
  273. EV.Subscribe(new EventItem("Alarm", $"{Name}Error940", $"{Name} Robot Occurred Error:消息参数错误。", "从主机接收的命令附加的参数无效。"));
  274. EV.Subscribe(new EventItem("Alarm", $"{Name}Error950", $"{Name} Robot Occurred Error:机械手在运动中,命令被拒绝。", "命令被拒绝,控制器正在执行一个运动命令。"));
  275. EV.Subscribe(new EventItem("Alarm", $"{Name}Error970", $"{Name} Robot Occurred Error:分隔符错误。", "没有分隔符。"));
  276. EV.Subscribe(new EventItem("Alarm", $"{Name}Error971", $"{Name} Robot Occurred Error:结束符错误。", "结束符不正确。"));
  277. EV.Subscribe(new EventItem("Alarm", $"{Name}Error972", $"{Name} Robot Occurred Error:指令长度错误。", "指令长度不正确。"));
  278. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorA10", $"{Name} Robot Occurred Error:外部急停。", "I/O 启用外部紧急停止(EXESP)功能。"));
  279. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorA20", $"{Name} Robot Occurred Error:T.P 紧急停。", "教学挂件上的急停按钮被按下。"));
  280. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorA30", $"{Name} Robot Occurred Error:急停。", "主机发出紧急停止命令。"));
  281. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorA31", $"{Name} Robot Occurred Error:碰撞检出。", "机械手发生碰撞。"));
  282. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorA45", $"{Name} Robot Occurred Error:单元风扇1错误。", "主机风扇1故障。"));
  283. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorA47", $"{Name} Robot Occurred Error:机械手风扇1错误。", "机械手风扇故障。"));
  284. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorA4F", $"{Name} Robot Occurred Error:控制器电池报警。", "控制器内存备用电池电量不足。"));
  285. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorA60", $"{Name} Robot Occurred Error:F47 连续错误。", "重新检测到供电电压下降。"));
  286. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorAE0", $"{Name} Robot Occurred Error:主机模式切换错误。", "模式切换到“HOST”,同时从示教器控制。"));
  287. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorAE1", $"{Name} Robot Occurred Error:教模式切换错误。", "在主机控制下切换为“TEACH”模式。"));
  288. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorAE8", $"{Name} Robot Occurred Error:伺服使能开关错误。", "示教器操作时松开使能开关。"));
  289. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorAF0", $"{Name} Robot Occurred Error:互锁故障1。", "检测到安全模块错误。"));
  290. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorAF1", $"{Name} Robot Occurred Error:互锁故障2。", "检测到安全模块错误。"));
  291. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorAF2", $"{Name} Robot Occurred Error:互锁故障3。", "检测到安全模块错误。"));
  292. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorAF3", $"{Name} Robot Occurred Error:互锁故障4。", "检测到安全模块错误。"));
  293. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorAF4", $"{Name} Robot Occurred Error:互锁故障5。", "检测到安全模块错误。"));
  294. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorAF5", $"{Name} Robot Occurred Error:互锁故障6。", "检测到安全模块错误。"));
  295. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorAF6", $"{Name} Robot Occurred Error:互锁故障7。", "检测到安全模块错误。"));
  296. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorAF8", $"{Name} Robot Occurred Error:互锁故障8。", "检测到安全模块错误。"));
  297. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorAF9", $"{Name} Robot Occurred Error:互锁故障9。", "检测到安全模块错误。"));
  298. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorAFA", $"{Name} Robot Occurred Error:互锁故障10。", "检测到安全模块错误。"));
  299. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorAFB", $"{Name} Robot Occurred Error:互锁故障11。", "检测到安全模块错误。"));
  300. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorAFC", $"{Name} Robot Occurred Error:互锁故障12。", "检测到安全模块错误。"));
  301. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB20", $"{Name} Robot Occurred Error:轴1正(+)方向软件限位检测1。", "正方向超过Axis-1运动范围。"));
  302. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB21", $"{Name} Robot Occurred Error:轴2正(+)方向软件限位检测1。", "正方向超过Axis-3运动范围。."));
  303. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB22", $"{Name} Robot Occurred Error:轴3正(+)方向软件限位检测1。", "正方向超过Axis-3运动范围。"));
  304. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB23", $"{Name} Robot Occurred Error:轴4正(+)方向软件限位检测1。", "正方向超过Axis-4运动范围。"));
  305. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB24", $"{Name} Robot Occurred Error:轴5正(+)方向软件限位检测1。", "正方向超过Axis-5运动范围。"));
  306. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB25", $"{Name} Robot Occurred Error:轴6正(+)方向软件限位检测1。", "正方向超过Axis-6运动范围。"));
  307. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB28", $"{Name} Robot Occurred Error:轴1正(+)方向限位检测。", "正方向超过Axis-1运动范围。"));
  308. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB29", $"{Name} Robot Occurred Error:轴2正(+)方向限位检测。", "正方向超过Axis-2运动范围。"));
  309. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB2A", $"{Name} Robot Occurred Error:轴3正(+)方向限位检测。", "正方向超过Axis-3运动范围。"));
  310. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB2B", $"{Name} Robot Occurred Error:轴4正(+)方向限位检测。", "正方向超过Axis-4运动范围。"));
  311. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB2C", $"{Name} Robot Occurred Error:轴5正(+)方向限位检测。", "正方向超过Axis-5运动范围。"));
  312. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB2D", $"{Name} Robot Occurred Error:轴6正(+)方向限位检测。", "正方向超过Axis-6运动范围。"));
  313. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB30", $"{Name} Robot Occurred Error:轴1负(-)方向软件限位检测1。", "负方向超过Axis-1运动范围。"));
  314. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB31", $"{Name} Robot Occurred Error:轴2负(-)方向软件限位检测1。", "负方向超过Axis-2运动范围。"));
  315. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB32", $"{Name} Robot Occurred Error:轴3负(-)方向软件限位检测1。", "负方向超过Axis-3运动范围。"));
  316. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB33", $"{Name} Robot Occurred Error:轴4负(-)方向软件限位检测1。", "负方向超过Axis-4运动范围。"));
  317. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB34", $"{Name} Robot Occurred Error:轴5负(-)方向软件限位检测1。", "负方向超过Axis-5运动范围。"));
  318. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB35", $"{Name} Robot Occurred Error:轴6负(-)方向软件限位检测1。", "负方向超过Axis-6运动范围。"));
  319. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB38", $"{Name} Robot Occurred Error:轴1负(-)方向限位检测。", "负方向超过Axis-1运动范围。"));
  320. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB39", $"{Name} Robot Occurred Error:轴2负(-)方向限位检测。", "负方向超过Axis-2运动范围。"));
  321. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB3A", $"{Name} Robot Occurred Error:轴3负(-)方向限位检测。", "负方向超过Axis-3运动范围。"));
  322. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB3B", $"{Name} Robot Occurred Error:轴4负(-)方向限位检测。", "负方向超过Axis-4运动范围。"));
  323. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB3C", $"{Name} Robot Occurred Error:轴5负(-)方向限位检测。", "负方向超过Axis-5运动范围。"));
  324. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB3D", $"{Name} Robot Occurred Error:轴6负(-)方向限位检测。", "负方向超过Axis-6运动范围。"));
  325. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB88", $"{Name} Robot Occurred Error:手爪传感器ON超时错误1。", "取片时手爪传感器1没有在规定时间内ON。"));
  326. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB89", $"{Name} Robot Occurred Error:手爪传感器ON超时错误2。", "取片时手爪传感器2没有在规定时间内ON。"));
  327. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB8A", $"{Name} Robot Occurred Error:手爪传感器OFF超时错误1。", "放片时手爪传感器1没有在规定时间内OFF。"));
  328. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorB8B", $"{Name} Robot Occurred Error:手爪传感器OFF超时错误2。", "放片时手爪传感器2没有在规定时间内OFF。"));
  329. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorBA8", $"{Name} Robot Occurred Error:手爪传感器OFF状态错误1。", "取片时手爪传感器1状态应该为OFF但当前状态未符合。"));
  330. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorBA9", $"{Name} Robot Occurred Error:手爪传感器OFF状态错误2。", "取片时手爪传感器2状态应该为OFF但当前状态未符合。"));
  331. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorBAA", $"{Name} Robot Occurred Error:手爪传感器ON状态错误1。", "放片时手爪传感器1状态应该为ON但当前状态未符合。"));
  332. EV.Subscribe(new EventItem("Alarm", $"{Name}ErrorBAB", $"{Name} Robot Occurred Error:手爪传感器ON状态错误2。", "放片时手爪传感器 2 状态应该为 ON 但当前状态未符合。"));
  333. }
  334. public void NotifyAlarmByErrorCode(string errorcode)
  335. {
  336. EV.Notify($"{Name}Error{errorcode}");
  337. }
  338. private void _diTPinUse_OnSignalChanged(IoSensor arg1, bool arg2)
  339. {
  340. SetMaintenanceMode(!arg1.Value);
  341. }
  342. private void _diRobotError_OnSignalChanged(IoSensor arg1, bool arg2)
  343. {
  344. if (arg1.Value == false)
  345. {
  346. lock (_locker)
  347. {
  348. _lstHandlers.AddLast(new GM201LVPRobotReadHandler(this, "RSTS"));
  349. }
  350. OnError("RobotError");
  351. }
  352. }
  353. private void ResetPropertiesAndResponses()
  354. {
  355. }
  356. private void RegisterSpecialData()
  357. {
  358. if (Name != "CarrierRobot")
  359. {
  360. DATA.Subscribe($"{Name}.CurrentArm1Position", () => CurrentArm1Position);
  361. DATA.Subscribe($"{Name}.CurrentArm2Position", () => CurrentArm2Position);
  362. DATA.Subscribe($"{Name}.CurrentZPosition", () => CurrentZPosition);
  363. DATA.Subscribe($"{Name}.IsWaferPresenceOnBlade2", () => IsWaferPresenceOnBlade2);
  364. DATA.Subscribe($"{Name}.IsWaferPresenceOnBlade3", () => IsWaferPresenceOnBlade3);
  365. DATA.Subscribe($"{Name}.IsWaferPresenceOnBlade4", () => IsWaferPresenceOnBlade4);
  366. DATA.Subscribe($"{Name}.IsWaferPresenceOnBlade5", () => IsWaferPresenceOnBlade5);
  367. }
  368. DATA.Subscribe($"{Name}.TPStatus", () => _tpStatus != null && _tpStatus.Value);
  369. DATA.Subscribe($"{Name}.CurrentExtensionPosition", () => CurrentExtensionPosition);
  370. DATA.Subscribe($"{Name}.CurrentThetaPosition", () => CurrentThetaPosition);
  371. DATA.Subscribe($"{Name}.IsManipulatorBatteryLow", () => IsManipulatorBatteryLow);
  372. DATA.Subscribe($"{Name}.IsCommandExecutionReady", () => IsCommandExecutionReady);
  373. DATA.Subscribe($"{Name}.IsServoON", () => IsServoON);
  374. DATA.Subscribe($"{Name}.IsErrorOccurred", () => IsErrorOccurred);
  375. DATA.Subscribe($"{Name}.IsControllerBatteryLow", () => IsControllerBatteryLow);
  376. DATA.Subscribe($"{Name}.IsWaferPresenceOnBlade1", () => IsWaferPresenceOnBlade1);
  377. DATA.Subscribe($"{Name}.MappingResult", () => ReadSlotMap);
  378. DATA.Subscribe($"{Name}.ReadRobotParameterResultDict", () => ReadRobotParameterResult);
  379. DATA.Subscribe($"{Name}.ErrorCode", () => ErrorCode);
  380. DATA.Subscribe($"{Name}.RobotSpeed", () => SpeedLevelSetting.ToString());
  381. OP.Subscribe($"{Name}.SetSpeed", InvokeSetSpeed);
  382. }
  383. private bool OnTimer()
  384. {
  385. try
  386. {
  387. _connection.MonitorTimeout();
  388. if (!_connection.IsConnected || _connection.IsCommunicationError)
  389. {
  390. lock (_locker)
  391. {
  392. _lstHandlers.Clear();
  393. _lstMonitorHandler.Clear();
  394. }
  395. _trigRetryConnect.CLK = !_connection.IsConnected;
  396. if (_trigRetryConnect.Q)
  397. {
  398. if (!_connection.Connect())
  399. {
  400. EV.PostAlarmLog(RobotModuleName.ToString(), $"Can not connect with {_connection.Address}, {Name}");
  401. }
  402. else
  403. {
  404. //_lstHandler.AddLast(new RobotHirataR4QueryPinHandler(this, _deviceAddress));
  405. //_lstHandler.AddLast(new RobotHirataR4SetCommModeHandler(this, _deviceAddress, EnumRfPowerCommunicationMode.Host));
  406. }
  407. }
  408. return true;
  409. }
  410. HandlerBase handler = null;
  411. lock (_locker)
  412. {
  413. if (!_connection.IsBusy)
  414. {
  415. if (_lstHandlers.Count > 0)
  416. {
  417. handler = _lstHandlers.First.Value;
  418. _connection.Execute(handler);
  419. _lstHandlers.RemoveFirst();
  420. }
  421. else
  422. {
  423. if (_lstMonitorHandler.Count > 0)
  424. {
  425. handler = _lstMonitorHandler.First.Value;
  426. _connection.Execute(handler);
  427. _lstMonitorHandler.RemoveFirst();
  428. }
  429. }
  430. }
  431. else
  432. {
  433. _connection.MonitorTimeout();
  434. _trigCommunicationError.CLK = _connection.IsCommunicationError;
  435. if (_trigCommunicationError.Q)
  436. {
  437. _lstHandlers.Clear();
  438. _lstMonitorHandler.Clear();
  439. //EV.PostAlarmLog(RobotModuleName.ToString(), $"{Module}.{Name} communication error, {_connection.LastCommunicationError}");
  440. OnError($"{Name} communication error, {_connection.LastCommunicationError}");
  441. //_trigActionDone.CLK = true;
  442. }
  443. }
  444. }
  445. }
  446. catch (Exception ex)
  447. {
  448. LOG.Write(ex);
  449. }
  450. return true;
  451. }
  452. public bool Connect()
  453. {
  454. return _connection.Connect();
  455. }
  456. public bool Disconnect()
  457. {
  458. return _connection.Disconnect();
  459. }
  460. public override bool IsReady()
  461. {
  462. //if (_diRobotReady!=null && !_diRobotReady.Value)
  463. // return false;
  464. if (_diRobotError != null && !_diRobotError.Value)
  465. return false;
  466. if (_diTPinUse != null && !_diTPinUse.Value)
  467. return false;
  468. return RobotState == RobotStateEnum.Idle && !IsBusy && !_connection.IsBusy && _lstHandlers.Count == 0 && !_connection.IsCommunicationError && _connection.IsConnected;
  469. }
  470. public override bool IsReady(out string reason)
  471. {
  472. reason = "";
  473. //if (_diRobotReady!=null && !_diRobotReady.Value)
  474. // return false;
  475. if (_diRobotError != null && !_diRobotError.Value)
  476. return false;
  477. if (_diTPinUse != null && !_diTPinUse.Value)
  478. return false;
  479. var ret = RobotState == RobotStateEnum.Idle && !IsBusy && !_connection.IsBusy && _lstHandlers.Count == 0 && !_connection.IsCommunicationError && _connection.IsConnected;
  480. if (!ret)
  481. {
  482. if (RobotState != RobotStateEnum.Idle)
  483. reason = "RobotState != RobotStateEnum.Idle";
  484. if (IsBusy)
  485. reason = "IsBusy";
  486. if (_lstHandlers.Count != 0)
  487. reason = "_lstHandlers.Count != 0";
  488. if (_connection.IsCommunicationError)
  489. reason = "_connection.IsCommunicationError";
  490. if (!_connection.IsConnected)
  491. reason = "!_connection.IsConnected";
  492. }
  493. return ret;
  494. }
  495. public bool ParseReadData(string _command, string[] rdata)
  496. {
  497. try
  498. {
  499. if (_command == "RSTS")
  500. {
  501. return ((rdata.Length == 3 || rdata.Length == 2) && ParseRSTSStatus(rdata));
  502. }
  503. if (_command == "RSLV") //Read the speed level
  504. {
  505. return (rdata.Length == 3 && ParseSpeedLevel(rdata[2]));
  506. }
  507. if (_command == "RPOS") //Reference current postion
  508. {
  509. return (rdata.Length > 1 && ParsePositionData(rdata));
  510. }
  511. if (_command == "RSTP") //Reference registered position, read the save postion for station
  512. {
  513. if (rdata.Length == 5)
  514. {
  515. return ParsePositionAxisDataV2(rdata);
  516. }
  517. if (rdata.Length == 7)
  518. {
  519. return ParsePositionAxisData(rdata);
  520. }
  521. // return (rdata.Length > 6 && ParseRegisteredPositionData(rdata));
  522. }
  523. if (_command == "RSTR") //Reference station item value
  524. {
  525. return (rdata.Length == 4 && ParseStationData(rdata));
  526. }
  527. if (_command == "RPRM") //Reference the parameter values of the specified unit
  528. {
  529. return (rdata.Length == 3 && ParseParameterData(rdata));
  530. }
  531. if (_command == "RMSK") //Reference the interlock information
  532. {
  533. return (rdata.Length == 1 && ParseInterlockInfo(rdata));
  534. }
  535. if (_command == "RVER") //Reference the software version
  536. {
  537. return (rdata.Length == 2 && ParseSoftwareVersion(rdata));
  538. }
  539. if (_command == "RMAP") //Reference the slot map
  540. {
  541. return (rdata.Length > 2 && ParseSlotMap(rdata));
  542. }
  543. if (_command == "RMPD") //reference the mapping data
  544. {
  545. return (rdata.Length > 1 && ParseMappingData(rdata));
  546. }
  547. if (_command == "RMCA") // Reference the mapping calibration result
  548. {
  549. return (rdata.Length > 1 && ParseMappingCalibrationResult(rdata));
  550. }
  551. if (_command == "RERR") // Request ERR
  552. {
  553. return (rdata.Length > 2 && ParseERR(rdata));
  554. }
  555. return true;
  556. }
  557. catch (Exception ex)
  558. {
  559. LOG.Write(ex);
  560. return true;
  561. }
  562. }
  563. public bool ParseRSTSStatus(string[] status)
  564. {
  565. try
  566. {
  567. if (status.Length > 2)
  568. {
  569. //wafer robot
  570. int intstatus = Convert.ToInt16(status[2].Substring(5, 2), 16);
  571. IsWaferPresenceOnBlade5 = (((intstatus >> 4) & 0x1) == 0x1);
  572. IsWaferPresenceOnBlade4 = (((intstatus >> 3) & 0x1) == 0x1);
  573. IsWaferPresenceOnBlade3 = (((intstatus >> 2) & 0x1) == 0x1);
  574. IsWaferPresenceOnBlade2 = (((intstatus >> 1) & 0x1) == 0x1);
  575. IsWaferPresenceOnBlade1 = (((intstatus >> 0) & 0x1) == 0x1);
  576. }
  577. else
  578. {
  579. //foup robot
  580. int intstatus = Convert.ToInt16(status[1].Substring(5, 2), 16);
  581. IsWaferPresenceOnBlade5 = (((intstatus >> 4) & 0x1) == 0x1);
  582. IsWaferPresenceOnBlade4 = (((intstatus >> 3) & 0x1) == 0x1);
  583. IsWaferPresenceOnBlade3 = (((intstatus >> 2) & 0x1) == 0x1);
  584. IsWaferPresenceOnBlade2 = (((intstatus >> 1) & 0x1) == 0x1);
  585. IsWaferPresenceOnBlade1 = (((intstatus >> 0) & 0x1) == 0x1);
  586. }
  587. return true;
  588. }
  589. catch (Exception ex)
  590. {
  591. LOG.Write(ex);
  592. return true;
  593. }
  594. }
  595. public bool ParseSpeedLevel(string speedlevel)
  596. {
  597. try
  598. {
  599. int level = Convert.ToInt32(speedlevel);
  600. if (level < 1 || level > 100) return false;
  601. SpeedLevel = level;
  602. return true;
  603. }
  604. catch (Exception ex)
  605. {
  606. LOG.Write(ex);
  607. return false;
  608. }
  609. }
  610. public bool ParsePositionData(string[] pdata)
  611. {
  612. try
  613. {
  614. if (pdata[1] == "R" || pdata[1] == "F")
  615. {
  616. CommandZPosition = Convert.ToSingle(pdata[1]) / 1000;
  617. CommandThetaPosition = Convert.ToSingle(pdata[2]) / 1000;
  618. CommandExtensionPosition = Convert.ToSingle(pdata[3]) / 1000;
  619. return true;
  620. }
  621. return false;
  622. }
  623. catch (Exception ex)
  624. {
  625. LOG.Write(ex);
  626. return false;
  627. }
  628. }
  629. public bool ParsePositionAxisData(string[] pdata)
  630. {
  631. try
  632. {
  633. ReadMemorySpec = pdata[0];
  634. ReadTransferStation = pdata[1];
  635. if (ReadStationItemValues.ContainsKey(pdata[2]))
  636. ReadStationItemValues.Remove(pdata[2]);
  637. ReadStationItemValues.Add(pdata[2], pdata[3]);
  638. if (ReadRobotParameterResult.ContainsKey(ReadTransferStation))
  639. {
  640. ReadRobotParameterResult[ReadTransferStation] = $"{pdata[2]},{pdata[3]},{pdata[4]},{pdata[5]},{pdata[6]}";
  641. }
  642. else
  643. {
  644. ReadRobotParameterResult.Add(ReadTransferStation, $"{pdata[2]},{pdata[3]},{pdata[4]},{pdata[5]},{pdata[6]}");
  645. }
  646. return true;
  647. }
  648. catch (Exception ex)
  649. {
  650. LOG.Write(ex);
  651. return false;
  652. }
  653. }
  654. public bool ParsePositionAxisDataV2(string[] pdata)
  655. {
  656. try
  657. {
  658. ReadMemorySpec = pdata[0];
  659. ReadTransferStation = pdata[1];
  660. if (ReadStationItemValues.ContainsKey(pdata[2]))
  661. ReadStationItemValues.Remove(pdata[2]);
  662. ReadStationItemValues.Add(pdata[2], pdata[3]);
  663. if (ReadRobotParameterResult.ContainsKey(ReadTransferStation))
  664. {
  665. ReadRobotParameterResult[ReadTransferStation] = $"{pdata[2]},{pdata[3]},{pdata[4]}";
  666. }
  667. else
  668. {
  669. ReadRobotParameterResult.Add(ReadTransferStation, $"{pdata[2]},{pdata[3]},{pdata[4]}");
  670. }
  671. return true;
  672. }
  673. catch (Exception ex)
  674. {
  675. LOG.Write(ex);
  676. return false;
  677. }
  678. }
  679. public bool ParseRegisteredPositionData(string[] pdata)
  680. {
  681. try
  682. {
  683. ReadMemorySpec = pdata[0];
  684. ReadTransferStation = pdata[1];
  685. ReadSlotNumber = Convert.ToInt16(pdata[2]);
  686. ReadArmPosture = pdata[3];
  687. ReadBladeNo = (RobotArmEnum)(Convert.ToInt16(pdata[4]) - 1);
  688. if (pdata[5] == "S")
  689. ReadPositionType = GM201LVPPositonEnum.RegisteredPosition;
  690. if (pdata[5] == "R")
  691. ReadPositionType = GM201LVPPositonEnum.ReadyPosition;
  692. if (pdata[5] == "M")
  693. ReadPositionType = GM201LVPPositonEnum.IntermediatePosition;
  694. if (pdata[5] == "B")
  695. ReadPositionType = GM201LVPPositonEnum.MappingStartPosition;
  696. if (pdata[5] == "E")
  697. ReadPositionType = GM201LVPPositonEnum.MappingFinishPosition;
  698. return true;
  699. }
  700. catch (Exception ex)
  701. {
  702. LOG.Write(ex);
  703. return false;
  704. }
  705. }
  706. public bool ParseStationData(string[] pdata)
  707. {
  708. try
  709. {
  710. ReadMemorySpec = pdata[0];
  711. ReadTransferStation = pdata[1];
  712. if (ReadStationItemValues.ContainsKey(pdata[2]))
  713. ReadStationItemValues.Remove(pdata[2]);
  714. ReadStationItemValues.Add(pdata[2], pdata[3]);
  715. if (ReadRobotParameterResult.ContainsKey(ReadTransferStation))
  716. {
  717. ReadRobotParameterResult[ReadTransferStation] = $"{pdata[2]},{pdata[3]}";
  718. }
  719. else
  720. {
  721. ReadRobotParameterResult.Add(ReadTransferStation, $"{pdata[2]},{pdata[3]}");
  722. }
  723. return true;
  724. }
  725. catch (Exception ex)
  726. {
  727. LOG.Write(ex);
  728. return false;
  729. }
  730. }
  731. public bool ParseParameterData(string[] pdata)
  732. {
  733. try
  734. {
  735. ReadParameterType = pdata[0];
  736. ReadParameterNo = pdata[1];
  737. ReadParameterValue = pdata[2];
  738. if (ReadRobotParameterResult.ContainsKey(ReadParameterNo))
  739. {
  740. ReadRobotParameterResult[ReadParameterNo] = ReadParameterValue;
  741. }
  742. else
  743. {
  744. ReadRobotParameterResult.Add(ReadParameterNo, ReadParameterValue);
  745. }
  746. return true;
  747. }
  748. catch (Exception ex)
  749. {
  750. LOG.Write(ex);
  751. return false;
  752. }
  753. }
  754. public bool ParseInterlockInfo(string[] pdata)
  755. {
  756. try
  757. {
  758. int intdata = Convert.ToInt16(pdata[1]);
  759. IsCheckInterlockWaferPresenceOnBlade1 = (intdata & 0x1) == 0;
  760. IsCheckInterlockWaferPresenceOnBlade2 = (intdata & 0x2) == 0;
  761. IsCheckInterlockWaferPresenceOnBlade3 = (intdata & 0x4) == 0;
  762. IsCheckInterlockWaferPresenceOnBlade4 = (intdata & 0x8) == 0;
  763. IsCheckInterlockWaferPresenceOnBlade5 = (intdata & 0x16) == 0;
  764. return true;
  765. }
  766. catch (Exception ex)
  767. {
  768. LOG.Write(ex);
  769. return false;
  770. }
  771. }
  772. public bool ParseSoftwareVersion(string[] pdata)
  773. {
  774. try
  775. {
  776. //RobotSystemVersion = pdata[0];
  777. RobotSoftwareVersion = pdata[1];
  778. return true;
  779. }
  780. catch (Exception ex)
  781. {
  782. LOG.Write(ex);
  783. return false;
  784. }
  785. }
  786. public bool ParseERR(string[] pdata)
  787. {
  788. try
  789. {
  790. var index = pdata[1];
  791. var code = pdata[2];
  792. if (code != "000")
  793. {
  794. EV.Notify($"{Name}Error{code}");
  795. LOG.Write($"{Name} Error {index} {code}");
  796. _isError = true;
  797. }
  798. else
  799. {
  800. _isError = false;
  801. }
  802. return true;
  803. }
  804. catch (Exception ex)
  805. {
  806. LOG.Write(ex);
  807. return false;
  808. }
  809. }
  810. public bool ParseSlotMap(string[] pdata)
  811. {
  812. try
  813. {
  814. ReadMappingTransferStation = pdata[1];
  815. ReadMappingSlotNumbers = pdata[2].Length - 1;
  816. StringBuilder sb = new StringBuilder();
  817. for (int i = 1; i < pdata[2].Length; i++)
  818. {
  819. string value = pdata[2][i].ToString();
  820. switch (value)
  821. {
  822. case "0":
  823. sb.Append("0");
  824. break;
  825. case "1":
  826. sb.Append("1");
  827. break;
  828. case "C":
  829. sb.Append("C");
  830. break;
  831. case "D":
  832. sb.Append("D");
  833. break;
  834. }
  835. }
  836. SlotMap = ReadSlotMap = sb.ToString();
  837. NotifySlotMapResult(CurrentInteractiveModule, ReadSlotMap);
  838. return true;
  839. }
  840. catch (Exception ex)
  841. {
  842. LOG.Write(ex);
  843. return false;
  844. }
  845. }
  846. public bool ParseMappingData(string[] pdata)
  847. {
  848. try
  849. {
  850. ReadMappingTransferStation = pdata[0];
  851. List<string> lstupdata = new List<string>();
  852. List<string> lstdowndata = new List<string>();
  853. for (int i = 0; i < (pdata.Length - 1) / 2; i++)
  854. {
  855. lstupdata.Add(pdata[2 * i + 1].Remove(0, 3));
  856. lstdowndata.Add(pdata[2 * i + 2]);
  857. }
  858. ReadMappingDownData = lstdowndata.ToArray();
  859. ReadMappingUpData = lstupdata.ToArray();
  860. return true;
  861. }
  862. catch (Exception ex)
  863. {
  864. LOG.Write(ex);
  865. return false;
  866. }
  867. }
  868. public bool ParseMappingCalibrationResult(string[] pdata)
  869. {
  870. try
  871. {
  872. ReadMappingTransferStation = pdata[0];
  873. ReadMappingCalibrationResult.Clear();
  874. ReadMappingCalibrationResult.Add("LowestLaySlotPosition", Convert.ToInt32(pdata[1]) / 1000);
  875. ReadMappingCalibrationResult.Add("HighestLaySlotPosition", Convert.ToInt32(pdata[2]) / 1000);
  876. ReadMappingCalibrationResult.Add("WaferWidth", Convert.ToInt32(pdata[3]) / 1000);
  877. ReadMappingCalibrationResult.Add("ThreshhholdValueofDoubleInsertion", Convert.ToInt32(pdata[4]) / 1000);
  878. ReadMappingCalibrationResult.Add("ThreshhholdValueofSlantingInsertion1", Convert.ToInt32(pdata[5]) / 1000);
  879. ReadMappingCalibrationResult.Add("ThreshhholdValueofSlantingInsertion2", Convert.ToInt32(pdata[6]) / 1000);
  880. return true;
  881. }
  882. catch (Exception ex)
  883. {
  884. LOG.Write(ex);
  885. return false;
  886. }
  887. }
  888. protected override bool fClear(object[] param)
  889. {
  890. if (!_connection.IsConnected)
  891. {
  892. EV.PostAlarmLog(RobotModuleName.ToString(), $"{RobotModuleName} clear failed for not connect with {_connection.Address}");
  893. return false;
  894. }
  895. lock (_locker)
  896. {
  897. _lstHandlers.Clear();
  898. _connection.ForceClear();
  899. //_lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, "CCLR", "E"));
  900. string strpara = "1,1,N";
  901. _lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, "INIT", strpara));
  902. _lstHandlers.AddLast(new GM201LVPRobotReadHandler(this, "RSTS"));
  903. }
  904. return true;
  905. }
  906. protected override bool fStartReadData(object[] param)
  907. {
  908. if (!_connection.IsConnected)
  909. {
  910. EV.PostAlarmLog(RobotModuleName.ToString(), $"{RobotModuleName} read data failed for not connect with {_connection.Address}");
  911. return false;
  912. }
  913. if (param.Length < 1) return false;
  914. string readcommand = param[0].ToString();
  915. switch (readcommand)
  916. {
  917. case "CurrentStatus":
  918. lock (_locker)
  919. {
  920. _lstHandlers.AddLast(new GM201LVPRobotReadHandler(this, "RSTS"));
  921. //_lstHandlers.AddLast(new GM201LVPRobotReadHandler(this, "RPOS", "F"));
  922. //_lstHandlers.AddLast(new GM201LVPRobotReadHandler(this, "RPOS", "R"));
  923. }
  924. break;
  925. case "CurrentRobotParameters":
  926. lock (_locker)
  927. {
  928. var parameters = param[1].ToString().Split(';').ToList();
  929. foreach (var item in parameters)
  930. {
  931. _lstMonitorHandler.AddLast(new GM201LVPRobotReadHandler(this, "RPRM", item));
  932. }
  933. }
  934. break;
  935. case "CurrentRobotPositionConfig":
  936. lock (_locker)
  937. {
  938. var parameters = param[1].ToString().Split(';').ToList();
  939. foreach (var item in parameters)
  940. {
  941. _lstMonitorHandler.AddLast(new GM201LVPRobotReadHandler(this, "RSTR", item));
  942. }
  943. }
  944. break;
  945. case "CurrentRobotPositionAxis":
  946. lock (_locker)
  947. {
  948. var parameters = param[1].ToString().Split(';').ToList();
  949. foreach (var item in parameters)
  950. {
  951. _lstMonitorHandler.AddLast(new GM201LVPRobotReadHandler(this, "RSTP", item));
  952. }
  953. }
  954. break;
  955. default:
  956. break;
  957. }
  958. return true;
  959. }
  960. protected override bool fMonitorReadData(object[] param)
  961. {
  962. IsBusy = false;
  963. return _lstHandlers.Count == 0 && !_connection.IsBusy;
  964. }
  965. private void ExecuteHandler(HandlerBase handler)
  966. {
  967. _connection.Execute(handler);
  968. }
  969. private string Checksum(byte[] bytes)
  970. {
  971. int sum = 0;
  972. foreach (byte code in bytes)
  973. {
  974. sum += code;
  975. }
  976. string hex = String.Format("{0:X2}", sum % 256);
  977. return hex;
  978. }
  979. private Stopwatch _timerActionMonitor = new Stopwatch();
  980. protected override bool fStartSetParameters(object[] param)
  981. {
  982. if (!_connection.IsConnected)
  983. {
  984. EV.PostAlarmLog(RobotModuleName.ToString(), $"{RobotModuleName} set parameter failed for not connect with {_connection.Address}");
  985. return false;
  986. }
  987. try
  988. {
  989. string strParameter;
  990. string setcommand = param[0].ToString();
  991. switch (setcommand)
  992. {
  993. case "SetSpeed": // SSPD Set the motion speed
  994. int speedLevel = Convert.ToInt32(param[1]);
  995. if (speedLevel > 100) speedLevel = 100;
  996. if (speedLevel < 1) speedLevel = 1;
  997. lock (_locker)
  998. {
  999. _lstHandlers.AddLast(new GM201LVPRobotSetHandler(this, "SSLV", $"1,{SpeedLevelSetting.ToString("D3")}"));
  1000. }
  1001. break;
  1002. case "SetParameter": // SPRM
  1003. lock (_locker)
  1004. {
  1005. var data = param[1].ToString().Split(';').ToList();
  1006. foreach (var item in data)
  1007. {
  1008. if (!string.IsNullOrEmpty(item))
  1009. {
  1010. _lstMonitorHandler.AddLast(new GM201LVPRobotSetHandler(this, "SPRM", item));
  1011. }
  1012. }
  1013. }
  1014. break;
  1015. case "SetPositionConfig": //SSTR,C01,000,00000000025
  1016. lock (_locker)
  1017. {
  1018. var data = param[1].ToString().Split(';').ToList();
  1019. foreach (var item in data)
  1020. {
  1021. if (!string.IsNullOrEmpty(item))
  1022. {
  1023. _lstMonitorHandler.AddLast(new GM201LVPRobotSetHandler(this, "SSTR", item));
  1024. }
  1025. }
  1026. }
  1027. break;
  1028. case "SetPositionAxis": //SABS,C01,00000100000,00000090000,00000000000,00000450000,00000010000
  1029. lock (_locker)
  1030. {
  1031. var data = param[1].ToString().Split(';').ToList();
  1032. foreach (var item in data)
  1033. {
  1034. if (!string.IsNullOrEmpty(item))
  1035. {
  1036. _lstMonitorHandler.AddLast(new GM201LVPRobotSetHandler(this, "SABS", item));
  1037. }
  1038. }
  1039. }
  1040. break;
  1041. case "EnableInterLock": //SMSK
  1042. int smskValid = Convert.ToInt16(param[1].ToString());
  1043. lock (_locker)
  1044. {
  1045. _lstHandlers.AddLast(new GM201LVPRobotSetHandler(this, "SPRM", smskValid.ToString("D4")));
  1046. }
  1047. break;
  1048. }
  1049. _timerActionMonitor.Restart();
  1050. }
  1051. catch (Exception)
  1052. {
  1053. string reason = "";
  1054. if (param != null)
  1055. {
  1056. foreach (var para in param)
  1057. {
  1058. reason += para.ToString() + ",";
  1059. }
  1060. }
  1061. EV.PostAlarmLog(Name, "Set command parameter invalid:" + reason);
  1062. return false;
  1063. }
  1064. return true;
  1065. }
  1066. protected override bool fMonitorSetParamter(object[] param)
  1067. {
  1068. IsBusy = false;
  1069. if (_timerActionMonitor.IsRunning && _timerActionMonitor.Elapsed > TimeSpan.FromSeconds(_timeLimitMotion))
  1070. {
  1071. _timerActionMonitor.Stop();
  1072. OnError("SetParameterTimeOut");
  1073. return true;
  1074. }
  1075. if (_lstHandlers.Count == 0 && !_connection.IsBusy)
  1076. {
  1077. //EV.PostInfoLog(Name, "SetParameter complete");
  1078. return true;
  1079. }
  1080. return false;
  1081. }
  1082. protected override bool fStartTransferWafer(object[] param)
  1083. {
  1084. return false;
  1085. }
  1086. protected override bool fStartUnGrip(object[] param)
  1087. {
  1088. if (!_connection.IsConnected)
  1089. {
  1090. EV.PostAlarmLog(RobotModuleName.ToString(), $"{RobotModuleName} ungrip failed for not connect with {_connection.Address}");
  1091. return false;
  1092. }
  1093. lock (_locker)
  1094. {
  1095. RobotArmEnum arm = (RobotArmEnum)param[0];
  1096. string strpara = (arm == RobotArmEnum.Both ? "F" : ((int)arm + 1).ToString()) + ",0,0";
  1097. _lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, "CSOL", strpara));
  1098. }
  1099. _timerActionMonitor.Restart();
  1100. return true;
  1101. }
  1102. protected override bool fMonitorUnGrip(object[] param)
  1103. {
  1104. IsBusy = false;
  1105. if (_timerActionMonitor.IsRunning && _timerActionMonitor.Elapsed > TimeSpan.FromSeconds(_timeLimitMotion))
  1106. {
  1107. _timerActionMonitor.Stop();
  1108. OnError("UngripTimeOut");
  1109. return true;
  1110. }
  1111. if (_lstHandlers.Count == 0 && !_connection.IsBusy)
  1112. {
  1113. //EV.PostInfoLog(Name, "Ungrip complete");
  1114. return true;
  1115. }
  1116. return false;
  1117. }
  1118. protected override bool fStartGrip(object[] param)
  1119. {
  1120. if (!_connection.IsConnected)
  1121. {
  1122. EV.PostAlarmLog(RobotModuleName.ToString(), $"{RobotModuleName} grip failed for not connect with {_connection.Address}");
  1123. return false;
  1124. }
  1125. lock (_locker)
  1126. {
  1127. RobotArmEnum arm = (RobotArmEnum)param[0];
  1128. string strpara = (arm == RobotArmEnum.Both ? "F" : ((int)arm + 1).ToString()) + ",1,0";
  1129. _lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, "CSOL", strpara));
  1130. }
  1131. return true;
  1132. }
  1133. protected override bool fMonitorGrip(object[] param)
  1134. {
  1135. IsBusy = false;
  1136. if (_timerActionMonitor.IsRunning && _timerActionMonitor.Elapsed > TimeSpan.FromSeconds(_timeLimitMotion))
  1137. {
  1138. _timerActionMonitor.Stop();
  1139. OnError("GripTimeOut");
  1140. return true;
  1141. }
  1142. if (_lstHandlers.Count == 0 && !_connection.IsBusy)
  1143. {
  1144. //EV.PostInfoLog(Name, "Grip complete");
  1145. return true;
  1146. }
  1147. return false;
  1148. }
  1149. protected override bool fStartInit(object[] param)
  1150. {
  1151. if (!_connection.IsConnected)
  1152. {
  1153. EV.PostAlarmLog(RobotModuleName.ToString(), $"{RobotModuleName} init failed for not connect with {_connection.Address}");
  1154. return false;
  1155. }
  1156. lock (_locker)
  1157. {
  1158. if (_doRobotHold != null)
  1159. {
  1160. _doRobotHold.SetTrigger(true, out _);
  1161. Thread.Sleep(100);
  1162. }
  1163. //ExecuteHandler(new GM201LVPRobotReadHandler(this, "RERR", "001"));
  1164. if (_isError)
  1165. {
  1166. string strparaReset = "1,1,N";
  1167. _lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, "INIT", strparaReset));
  1168. _isError = false;
  1169. }
  1170. string strpara = "1,1,G";
  1171. if (RobotModuleName == ModuleName.CarrierRobot)
  1172. {
  1173. strpara = "1,1,S";
  1174. }
  1175. _lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, "INIT", strpara));
  1176. if (SpeedLevelSetting >= 1 && SpeedLevelSetting <= 100)
  1177. _lstHandlers.AddLast(new GM201LVPRobotSetHandler(this, "SSLV", $"1,{SpeedLevelSetting.ToString("D3")}"));
  1178. _lstHandlers.AddLast(new GM201LVPRobotReadHandler(this, "RSTS"));
  1179. }
  1180. _timerActionMonitor.Restart();
  1181. return true;
  1182. }
  1183. protected override bool fMonitorInit(object[] param)
  1184. {
  1185. IsBusy = false;
  1186. if (_timerActionMonitor.IsRunning && _timerActionMonitor.Elapsed > TimeSpan.FromSeconds(_timeLimitHome))
  1187. {
  1188. _timerActionMonitor.Stop();
  1189. OnError("InitTimeOut");
  1190. return true;
  1191. }
  1192. if (_lstHandlers.Count == 0 && !_connection.IsBusy)
  1193. {
  1194. BladeTarget = ModuleName.System;
  1195. Blade1Target = ModuleName.System;
  1196. Blade2Target = ModuleName.System;
  1197. CmdTarget = ModuleName.System;
  1198. MoveInfo = new RobotMoveInfo()
  1199. {
  1200. Action = RobotAction.Moving,
  1201. ArmTarget = CmdRobotArm == RobotArmEnum.Lower ? RobotArm.ArmA : RobotArm.ArmB,
  1202. BladeTarget = BuildBladeTarget(),
  1203. };
  1204. //EV.PostInfoLog(Name, "Init complete");
  1205. return true;
  1206. }
  1207. return false;
  1208. }
  1209. protected override bool fStartHome(object[] param)
  1210. {
  1211. if (!_connection.IsConnected)
  1212. {
  1213. EV.PostAlarmLog(RobotModuleName.ToString(), $"{RobotModuleName} init failed for not connect with {_connection.Address}");
  1214. return false;
  1215. }
  1216. lock (_locker)
  1217. {
  1218. if (_doRobotHold != null)
  1219. {
  1220. _doRobotHold.SetTrigger(true, out _);
  1221. Thread.Sleep(100);
  1222. }
  1223. //ExecuteHandler(new GM201LVPRobotReadHandler(this, "RERR", "001"));
  1224. if (_isError)
  1225. {
  1226. string strparaReset = "1,1,N";
  1227. _lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, "INIT", strparaReset));
  1228. _isError = false;
  1229. }
  1230. string strpara = "1,1,G";
  1231. if (RobotModuleName == ModuleName.CarrierRobot)
  1232. {
  1233. strpara = "1,1,S";
  1234. }
  1235. _lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, "INIT", strpara, _timeLimitHome));
  1236. if (SpeedLevelSetting >= 1 && SpeedLevelSetting <= 100)
  1237. _lstHandlers.AddLast(new GM201LVPRobotSetHandler(this, "SSLV", $"1,{SpeedLevelSetting.ToString("D3")}"));
  1238. _lstHandlers.AddLast(new GM201LVPRobotReadHandler(this, "RSTS"));
  1239. }
  1240. _timerActionMonitor.Restart();
  1241. return true;
  1242. }
  1243. protected override bool fMonitorHome(object[] param)
  1244. {
  1245. IsBusy = false;
  1246. if (_timerActionMonitor.IsRunning && _timerActionMonitor.Elapsed > TimeSpan.FromSeconds(_timeLimitHome))
  1247. {
  1248. _timerActionMonitor.Stop();
  1249. OnError("HomeTimeOut");
  1250. return true;
  1251. }
  1252. if (_lstHandlers.Count == 0 && !_connection.IsBusy)
  1253. {
  1254. BladeTarget = ModuleName.System;
  1255. Blade1Target = ModuleName.System;
  1256. Blade2Target = ModuleName.System;
  1257. CmdTarget = ModuleName.System;
  1258. MoveInfo = new RobotMoveInfo()
  1259. {
  1260. Action = RobotAction.Moving,
  1261. ArmTarget = CmdRobotArm == RobotArmEnum.Lower ? RobotArm.ArmA : RobotArm.ArmB,
  1262. BladeTarget = BuildBladeTarget(),
  1263. };
  1264. //EV.PostInfoLog(Name, "Home complete");
  1265. return true;
  1266. }
  1267. return false;
  1268. }
  1269. protected override bool fStartGoTo(object[] param)
  1270. {
  1271. if (!_connection.IsConnected)
  1272. {
  1273. EV.PostAlarmLog(RobotModuleName.ToString(), $"{RobotModuleName} move failed for not connect with {_connection.Address}");
  1274. return false;
  1275. }
  1276. try
  1277. {
  1278. RobotArmEnum arm = (RobotArmEnum)param[0];
  1279. ModuleName module = (ModuleName)Enum.Parse(typeof(ModuleName), param[1].ToString());
  1280. BladeTarget = module;
  1281. Blade1Target = module;
  1282. Blade2Target = module;
  1283. int slot = (int)param[2] + 1;
  1284. //RobotPostionEnum postype = (RobotPostionEnum)param[3];
  1285. RobotPostionEnum postype = (RobotPostionEnum)Enum.Parse(typeof(RobotPostionEnum), param[3].ToString());
  1286. string strpara = string.Empty;
  1287. //bool isFromOriginal = (bool)param[8];
  1288. //bool isJumpToNextMotion = (bool)param[9];
  1289. //if ((int)postype >= 0 && (int)postype < 10)
  1290. //{
  1291. // strpara = "G";
  1292. //}
  1293. //if ((int)postype >= 10 && (int)postype < 20)
  1294. //{
  1295. // strpara = "P";
  1296. //}
  1297. //if ((int)postype >= 20 && (int)postype < 30)
  1298. //{
  1299. // strpara = "E";
  1300. //}
  1301. string trsSt = GetStationsName(module);
  1302. if (string.IsNullOrEmpty(trsSt))
  1303. {
  1304. LOG.Write("invalid transfer paramter");
  1305. return false;
  1306. }
  1307. string TrsPnt = string.Empty;
  1308. if (postype == RobotPostionEnum.PickReady)
  1309. {
  1310. TrsPnt = "G";
  1311. }
  1312. if (postype == RobotPostionEnum.PlaceReady)
  1313. {
  1314. TrsPnt = "P";
  1315. }
  1316. //strCmd = "MTCH";
  1317. if (_MaterialType == MaterialType.Wafer)
  1318. {
  1319. int bladeNo = (arm == RobotArmEnum.Blade1 || arm == RobotArmEnum.Lower) ? 4 : 31;
  1320. strpara += $"{TrsPnt},{trsSt},{slot:D3},{bladeNo:D3}";
  1321. }
  1322. else if (_MaterialType == MaterialType.Carrier)
  1323. {
  1324. //strpara = $"{TrsPnt},{trsSt},001,000";
  1325. string strHand = GetHandsName(module);
  1326. if (string.IsNullOrEmpty(strHand))
  1327. {
  1328. LOG.Write("Invalid Paramter.");
  1329. return false;
  1330. }
  1331. strpara = $"{TrsPnt},{trsSt},001,{strHand},001";
  1332. }
  1333. lock (_locker)
  1334. {
  1335. {
  1336. _lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, "MTCH", strpara));
  1337. _lstHandlers.AddLast(new GM201LVPRobotReadHandler(this, "RSTS"));
  1338. }
  1339. }
  1340. _timerActionMonitor.Restart();
  1341. return true;
  1342. }
  1343. catch (Exception ex)
  1344. {
  1345. LOG.Write(ex);
  1346. return false;
  1347. }
  1348. }
  1349. protected override bool fMonitorGoTo(object[] param)
  1350. {
  1351. if (_timerActionMonitor.IsRunning && _timerActionMonitor.Elapsed > TimeSpan.FromSeconds(_timeLimitMotion))
  1352. {
  1353. _timerActionMonitor.Stop();
  1354. OnError("GotoTimeOut");
  1355. return true;
  1356. }
  1357. if (_lstHandlers.Count != 0 || _connection.IsBusy) return false;
  1358. IsBusy = false;
  1359. return true;
  1360. }
  1361. protected override bool fGoToComplete(object[] param)
  1362. {
  1363. try
  1364. {
  1365. if (_lstHandlers.Count > 0) return false;
  1366. RobotArmEnum arm = (RobotArmEnum)CurrentParamter[0];
  1367. ModuleName sourcemodule = (ModuleName)Enum.Parse(typeof(ModuleName), CurrentParamter[1].ToString());
  1368. int SourceslotIndex = (int)CurrentParamter[2];
  1369. RobotPostionEnum postype = (RobotPostionEnum)CurrentParamter[3];
  1370. //bool isFromOriginal = (bool)CurrentParamter[8];
  1371. //bool isJumpToNextMotion = (bool)CurrentParamter[9];
  1372. }
  1373. catch (Exception ex)
  1374. {
  1375. LOG.Write(ex);
  1376. }
  1377. return base.fGoToComplete(param);
  1378. }
  1379. protected override bool fStop(object[] param)
  1380. {
  1381. lock (_locker)
  1382. {
  1383. if (_doRobotHold != null)
  1384. _doRobotHold.SetTrigger(false, out _);
  1385. _lstHandlers.Clear();
  1386. _connection.ForceClear();
  1387. //ExecuteHandler(new GM201LVPRobotMotionHandler(this, "CSTP", "E"));
  1388. }
  1389. return true; ;
  1390. }
  1391. protected override bool fMonitorStop(object[] param)
  1392. {
  1393. return true;
  1394. }
  1395. protected override bool fStartMove(object[] param)
  1396. {
  1397. if (!_connection.IsConnected)
  1398. {
  1399. EV.PostAlarmLog(RobotModuleName.ToString(), $"{RobotModuleName} move failed for not connect with {_connection.Address}");
  1400. return false;
  1401. }
  1402. try
  1403. {
  1404. string strCmd = param[0].ToString();
  1405. string strpara = string.Empty;
  1406. for (int i = 1; i < param.Length; i++)
  1407. {
  1408. if (i == 1)
  1409. strpara += param[i].ToString();
  1410. else
  1411. strpara += "," + param[i].ToString();
  1412. }
  1413. lock (_locker)
  1414. {
  1415. _lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, strCmd, strpara));
  1416. _lstHandlers.AddLast(new GM201LVPRobotReadHandler(this, "RPOS", "F"));
  1417. }
  1418. _timerActionMonitor.Restart();
  1419. return true;
  1420. }
  1421. catch (Exception ex)
  1422. {
  1423. LOG.Write(ex);
  1424. return false;
  1425. }
  1426. }
  1427. private string GetStationsName(ModuleName chamber)
  1428. {
  1429. if (!_moduleAssociateStationDic.ContainsKey(chamber.ToString()))
  1430. {
  1431. LOG.Error($"not define teach position {chamber}");
  1432. return "";
  1433. }
  1434. var moduleIndex = _moduleAssociateStationDic[chamber.ToString()];
  1435. return moduleIndex.ToString();
  1436. }
  1437. private string GetHandsName(ModuleName chamber)
  1438. {
  1439. if (!_moduleAssociateHandDic.ContainsKey(chamber.ToString()))
  1440. {
  1441. LOG.Error($"not define teach position {chamber}");
  1442. return "";
  1443. }
  1444. var moduleIndex = _moduleAssociateHandDic[chamber.ToString()];
  1445. return moduleIndex.ToString();
  1446. }
  1447. private int GetSlotsNumber(ModuleName module)
  1448. {
  1449. try
  1450. {
  1451. if (ModuleHelper.IsLoadPort(module))
  1452. {
  1453. return DEVICE.GetDevice<LoadPortBaseDevice>(module.ToString()).ValidSlotsNumber;
  1454. }
  1455. return SC.GetValue<int>($"CarrierInfo.{module}SlotsNumber");
  1456. }
  1457. catch (Exception ex)
  1458. {
  1459. LOG.Write(ex);
  1460. return -1;
  1461. }
  1462. }
  1463. private bool _isNeedMappignData
  1464. {
  1465. get
  1466. {
  1467. if (SC.ContainsItem($"Robot.{RobotModuleName}.NeedReadMapData"))
  1468. return SC.GetValue<bool>($"Robot.{RobotModuleName}.NeedReadMapData");
  1469. return true;
  1470. }
  1471. }
  1472. protected override bool fStartMapWafer(object[] param)
  1473. {
  1474. if (!_connection.IsConnected)
  1475. {
  1476. EV.PostAlarmLog(RobotModuleName.ToString(), $"{RobotModuleName} map failed for not connect with {_connection.Address}");
  1477. return false;
  1478. }
  1479. try
  1480. {
  1481. ReadSlotMap = "";
  1482. //RobotArmEnum pickarm = (RobotArmEnum)param[0];
  1483. ModuleName module = (ModuleName)Enum.Parse(typeof(ModuleName), param[0].ToString());
  1484. BladeTarget = module;
  1485. Blade1Target = module;
  1486. Blade2Target = module;
  1487. //int slotsNumber = GetSlotsNumber(module);
  1488. //if (slotsNumber == -1)
  1489. //{
  1490. // LOG.Write("Invalid mapping paramter slots number");
  1491. // return false;
  1492. //}
  1493. string TrsSt = GetStationsName(module);
  1494. if (string.IsNullOrEmpty(TrsSt))
  1495. {
  1496. LOG.Write("Invalid Paramter.");
  1497. return false;
  1498. }
  1499. string strpara = $"{TrsSt},1";
  1500. lock (_locker)
  1501. {
  1502. CurrentInteractiveModule = module;
  1503. _lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, "MMAP", strpara, _timeLimitMotion));
  1504. //if (_isNeedMappignData)
  1505. // _lstHandlers.AddLast(new GM201LVPRobotReadHandler(this, "RMPD", $"{GetStationsName(module)},025"));
  1506. _lstHandlers.AddLast(new GM201LVPRobotReadHandler(this, "RMAP", $"{GetStationsName(module)}"));
  1507. }
  1508. _timerActionMonitor.Restart();
  1509. return true;
  1510. }
  1511. catch (Exception ex)
  1512. {
  1513. LOG.Write(ex);
  1514. return false;
  1515. }
  1516. }
  1517. protected override bool fMonitorMap(object[] param)
  1518. {
  1519. if (_timerActionMonitor.IsRunning && _timerActionMonitor.Elapsed > TimeSpan.FromSeconds(_timeLimitMotion))
  1520. {
  1521. _timerActionMonitor.Stop();
  1522. OnError("PlaceTimeOut");
  1523. return true;
  1524. }
  1525. if (_lstHandlers.Count != 0 || _connection.IsBusy) return false;
  1526. IsBusy = false;
  1527. BladeTarget = ModuleName.System;
  1528. Blade1Target = ModuleName.System;
  1529. Blade2Target = ModuleName.System;
  1530. CmdTarget = ModuleName.System;
  1531. MoveInfo = new RobotMoveInfo()
  1532. {
  1533. Action = RobotAction.Moving,
  1534. ArmTarget = CmdRobotArm == RobotArmEnum.Lower ? RobotArm.ArmA : RobotArm.ArmB,
  1535. BladeTarget = BuildBladeTarget(),
  1536. };
  1537. return true;
  1538. }
  1539. protected override bool fStartSwapWafer(object[] param)
  1540. {
  1541. if (!_connection.IsConnected)
  1542. {
  1543. EV.PostAlarmLog(RobotModuleName.ToString(), $"{RobotModuleName} move failed for not connect with {_connection.Address}");
  1544. return false;
  1545. }
  1546. try
  1547. {
  1548. RobotArmEnum arm = (RobotArmEnum)param[0];
  1549. ModuleName module = (ModuleName)Enum.Parse(typeof(ModuleName), param[1].ToString());
  1550. BladeTarget = module;
  1551. Blade1Target = module;
  1552. Blade2Target = module;
  1553. if (ModuleHelper.IsLoadPort(module))
  1554. {
  1555. var lp = DEVICE.GetDevice<LoadPortBaseDevice>(module.ToString());
  1556. if (lp != null)
  1557. lp.NoteTransferStart();
  1558. }
  1559. int slot = (int)param[2] + 1;
  1560. float x = 0, y = 0, z = 0, w = 0;
  1561. if (param.Length > 3)
  1562. {
  1563. x = (float)param[3];
  1564. y = (float)param[4];
  1565. z = (float)param[5];
  1566. w = (float)param[6];
  1567. }
  1568. int intXvalue = (int)(x * 1000);
  1569. int intYvalue = (int)(y * 1000);
  1570. int intZvalue = (int)(z * 1000);
  1571. int intWvalue = (int)(w * 1000);
  1572. string TrsSt = GetStationsName(module);
  1573. if (string.IsNullOrEmpty(TrsSt))
  1574. {
  1575. LOG.Write("Invalid Paramter.");
  1576. return false;
  1577. }
  1578. string strpara = $"E,{TrsSt},{slot:D2},A,{(arm == RobotArmEnum.Both ? "F" : ((int)arm + 1).ToString())},P4";
  1579. if (x != 0 || y != 0 || z != 0)
  1580. {
  1581. strpara += $",{intXvalue:D8},{intYvalue:D8},{intZvalue:D8}";
  1582. }
  1583. if (w != 0)
  1584. {
  1585. strpara += $",{intWvalue:D8}";
  1586. }
  1587. lock (_locker)
  1588. {
  1589. if (_lstHandlers.Count == 0 && !_connection.IsBusy)
  1590. {
  1591. ExecuteHandler(new GM201LVPRobotMotionHandler(this, "MTRS", strpara, _timeLimitMotion));
  1592. }
  1593. else
  1594. {
  1595. _lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, "MTRS", strpara));
  1596. }
  1597. }
  1598. return true;
  1599. }
  1600. catch (Exception ex)
  1601. {
  1602. LOG.Write(ex);
  1603. return false;
  1604. }
  1605. }
  1606. protected override bool fSwapComplete(object[] param)
  1607. {
  1608. RobotArmEnum arm = (RobotArmEnum)CurrentParamter[0];
  1609. ModuleName sourcemodule;
  1610. if (!Enum.TryParse(CurrentParamter[1].ToString(), out sourcemodule)) return false;
  1611. int Sourceslotindex;
  1612. if (!int.TryParse(CurrentParamter[2].ToString(), out Sourceslotindex)) return false;
  1613. int delayCount = 0;
  1614. if (arm == RobotArmEnum.Lower)
  1615. {
  1616. //WaferManager.Instance.WaferMoved(sourcemodule, Sourceslotindex, RobotModuleName, 0);
  1617. //WaferManager.Instance.WaferMoved(RobotModuleName, 1, sourcemodule, Sourceslotindex);
  1618. while (!isSimulatorMode && !(GetWaferState(RobotArmEnum.Lower) == RobotArmWaferStateEnum.Present
  1619. && GetWaferState(RobotArmEnum.Upper) == RobotArmWaferStateEnum.Absent))
  1620. {
  1621. delayCount++;
  1622. Thread.Sleep(50);
  1623. LOG.Write($"{RobotModuleName} delay {delayCount} time to detect wafer");
  1624. if (delayCount > 100)
  1625. {
  1626. OnError("Wafer detect error");
  1627. return true;
  1628. }
  1629. }
  1630. WaferManager.Instance.WaferMoved(sourcemodule, Sourceslotindex, RobotModuleName, 0);
  1631. WaferManager.Instance.WaferMoved(RobotModuleName, 1, sourcemodule, Sourceslotindex);
  1632. }
  1633. if (arm == RobotArmEnum.Upper)
  1634. {
  1635. //WaferManager.Instance.WaferMoved(sourcemodule, Sourceslotindex, RobotModuleName, 1);
  1636. //WaferManager.Instance.WaferMoved(RobotModuleName, 0, sourcemodule, Sourceslotindex);
  1637. delayCount = 0;
  1638. while (!isSimulatorMode && !(GetWaferState(RobotArmEnum.Upper) == RobotArmWaferStateEnum.Present &&
  1639. GetWaferState(RobotArmEnum.Lower) == RobotArmWaferStateEnum.Absent))
  1640. {
  1641. delayCount++;
  1642. Thread.Sleep(50);
  1643. LOG.Write($"{RobotModuleName} delay {delayCount} time to detect wafer");
  1644. if (delayCount > 100)
  1645. {
  1646. OnError("Wafer detect error");
  1647. return true;
  1648. }
  1649. }
  1650. WaferManager.Instance.WaferMoved(sourcemodule, Sourceslotindex, RobotModuleName, 1);
  1651. WaferManager.Instance.WaferMoved(RobotModuleName, 0, sourcemodule, Sourceslotindex);
  1652. }
  1653. return base.fSwapComplete(param);
  1654. }
  1655. protected override bool fStartPlaceWafer(object[] param)
  1656. {
  1657. if (!_connection.IsConnected)
  1658. {
  1659. EV.PostAlarmLog(RobotModuleName.ToString(), $"{RobotModuleName} place failed for not connect with {_connection.Address}");
  1660. return false;
  1661. }
  1662. try
  1663. {
  1664. RobotArmEnum arm = (RobotArmEnum)param[0];
  1665. ModuleName module = (ModuleName)Enum.Parse(typeof(ModuleName), param[1].ToString());
  1666. if (ModuleHelper.IsLoadPort(module))
  1667. {
  1668. var lp = DEVICE.GetDevice<LoadPortBaseDevice>(module.ToString());
  1669. if (lp != null)
  1670. lp.NoteTransferStart();
  1671. }
  1672. BladeTarget = module;
  1673. Blade1Target = module;
  1674. Blade2Target = module;
  1675. int slot = (int)param[2] + 1;
  1676. string TrsSt = GetStationsName(module);
  1677. if (string.IsNullOrEmpty(TrsSt))
  1678. {
  1679. LOG.Write("Invalid Parameter.");
  1680. return false;
  1681. }
  1682. string strpara = "";
  1683. if (_MaterialType == MaterialType.Wafer)
  1684. {
  1685. int bladeNo = (arm == RobotArmEnum.Blade1 || arm == RobotArmEnum.Lower) ? 4 : 31;
  1686. strpara = $"P,{TrsSt},{slot:D3},{bladeNo:D3}";
  1687. }
  1688. else if (_MaterialType == MaterialType.Carrier)
  1689. {
  1690. string strHand = GetHandsName(module);
  1691. if (string.IsNullOrEmpty(strHand))
  1692. {
  1693. LOG.Write("Invalid Paramter.");
  1694. return false;
  1695. }
  1696. strpara = $"P,{TrsSt},001,{strHand}";
  1697. }
  1698. lock (_locker)
  1699. {
  1700. {
  1701. _lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, "MTRS", strpara, _timeLimitPlace));
  1702. _lstHandlers.AddLast(new GM201LVPRobotReadHandler(this, "RSTS"));
  1703. }
  1704. }
  1705. CmdTarget = module;
  1706. MoveInfo = new RobotMoveInfo()
  1707. {
  1708. Action = RobotAction.Moving,
  1709. ArmTarget = CmdRobotArm == RobotArmEnum.Lower ? RobotArm.ArmA : RobotArm.ArmB,
  1710. BladeTarget = BuildBladeTarget(),
  1711. };
  1712. _timerActionMonitor.Restart();
  1713. return true;
  1714. }
  1715. catch (Exception ex)
  1716. {
  1717. LOG.Write(ex);
  1718. return false;
  1719. }
  1720. }
  1721. protected override bool fMonitorPlace(object[] param)
  1722. {
  1723. IsBusy = false;
  1724. if (_timerActionMonitor.IsRunning && _timerActionMonitor.Elapsed > TimeSpan.FromSeconds(_timeLimitPlace))
  1725. {
  1726. _timerActionMonitor.Stop();
  1727. OnError("PlaceTimeOut");
  1728. return true;
  1729. }
  1730. if (_lstHandlers.Count == 0 && !_connection.IsBusy)
  1731. {
  1732. _timerActionMonitor.Stop();
  1733. //EV.PostInfoLog(Name, "Place complete");
  1734. fPlaceComplete(param);
  1735. BladeTarget = ModuleName.System;
  1736. Blade1Target = ModuleName.System;
  1737. Blade2Target = ModuleName.System;
  1738. CmdTarget = ModuleName.System;
  1739. MoveInfo = new RobotMoveInfo()
  1740. {
  1741. Action = RobotAction.Moving,
  1742. ArmTarget = CmdRobotArm == RobotArmEnum.Lower ? RobotArm.ArmA : RobotArm.ArmB,
  1743. BladeTarget = BuildBladeTarget(),
  1744. };
  1745. return true;
  1746. }
  1747. return false;
  1748. }
  1749. protected override bool fPlaceComplete(object[] param)
  1750. {
  1751. if (_isError)
  1752. {
  1753. OnError("RobotError");
  1754. return true;
  1755. }
  1756. if (_lstHandlers.Count > 0) return false;
  1757. RobotArmEnum arm = (RobotArmEnum)CurrentParamter[0];
  1758. ModuleName sourcemodule;
  1759. if (!Enum.TryParse(CurrentParamter[1].ToString(), out sourcemodule)) return false;
  1760. int Sourceslotindex;
  1761. if (!int.TryParse(CurrentParamter[2].ToString(), out Sourceslotindex)) return false;
  1762. int delayCount = 0;
  1763. if (arm == RobotArmEnum.Lower || arm == RobotArmEnum.Blade1)
  1764. {
  1765. //WaferManager.Instance.WaferMoved(RobotModuleName, 0, sourcemodule, Sourceslotindex);
  1766. while (!isSimulatorMode && GetWaferState(arm) != RobotArmWaferStateEnum.Absent)
  1767. {
  1768. delayCount++;
  1769. Thread.Sleep(50);
  1770. LOG.Write($"{RobotModuleName} delay {delayCount} time to detect wafer");
  1771. if (delayCount > 100)
  1772. {
  1773. OnError("Wafer detect error");
  1774. return true;
  1775. }
  1776. }
  1777. if (_MaterialType == MaterialType.Wafer)
  1778. {
  1779. WaferManager.Instance.WaferMoved(RobotModuleName, 2, sourcemodule, Sourceslotindex);
  1780. }
  1781. else if (_MaterialType == MaterialType.Carrier)
  1782. {
  1783. if (CarrierManager.Instance.CheckHasCarrier(RobotModuleName.ToString(), 0))
  1784. {
  1785. CarrierManager.Instance.CarrierMoved(RobotModuleName.ToString(), sourcemodule.ToString(), true);
  1786. for (int i = 0; i < WaferManager.Instance.GetWafers(RobotModuleName).Length; i++)
  1787. {
  1788. if (WaferManager.Instance.CheckHasWafer(RobotModuleName, i))
  1789. WaferManager.Instance.WaferMoved(RobotModuleName, i, sourcemodule, i, false);
  1790. }
  1791. }
  1792. }
  1793. }
  1794. if (arm == RobotArmEnum.Upper || arm == RobotArmEnum.Blade2)
  1795. {
  1796. //WaferManager.Instance.WaferMoved(RobotModuleName, 1, sourcemodule, Sourceslotindex);
  1797. delayCount = 0;
  1798. while (!isSimulatorMode && GetWaferState(arm) != RobotArmWaferStateEnum.Absent)
  1799. {
  1800. delayCount++;
  1801. Thread.Sleep(50);
  1802. LOG.Write($"{RobotModuleName} delay {delayCount} time to detect wafer");
  1803. if (delayCount > 100)
  1804. {
  1805. OnError("Wafer detect error");
  1806. return true;
  1807. }
  1808. }
  1809. WaferManager.Instance.WaferMoved(RobotModuleName, 1, sourcemodule, Sourceslotindex);
  1810. }
  1811. if (arm == RobotArmEnum.Both)
  1812. {
  1813. //WaferManager.Instance.WaferMoved(RobotModuleName, 0, sourcemodule, Sourceslotindex);
  1814. //WaferManager.Instance.WaferMoved(RobotModuleName, 1, sourcemodule, Sourceslotindex);
  1815. while (!isSimulatorMode && GetWaferState(arm) != RobotArmWaferStateEnum.Absent)
  1816. {
  1817. delayCount++;
  1818. Thread.Sleep(50);
  1819. LOG.Write($"{RobotModuleName} delay {delayCount} time to detect wafer");
  1820. if (delayCount > 100)
  1821. {
  1822. OnError("Wafer detect error");
  1823. return true;
  1824. }
  1825. }
  1826. WaferManager.Instance.WaferMoved(RobotModuleName, 0, sourcemodule, Sourceslotindex);
  1827. WaferManager.Instance.WaferMoved(RobotModuleName, 1, sourcemodule, Sourceslotindex + 1);
  1828. WaferManager.Instance.WaferMoved(RobotModuleName, 2, sourcemodule, Sourceslotindex + 2);
  1829. WaferManager.Instance.WaferMoved(RobotModuleName, 3, sourcemodule, Sourceslotindex + 3);
  1830. WaferManager.Instance.WaferMoved(RobotModuleName, 4, sourcemodule, Sourceslotindex + 4);
  1831. }
  1832. return base.fPlaceComplete(param);
  1833. }
  1834. protected override bool fStartPickWafer(object[] param)
  1835. {
  1836. if (!_connection.IsConnected)
  1837. {
  1838. EV.PostAlarmLog(RobotModuleName.ToString(), $"{RobotModuleName} move failed for not connect with {_connection.Address}");
  1839. return false;
  1840. }
  1841. try
  1842. {
  1843. RobotArmEnum arm = (RobotArmEnum)param[0];
  1844. ModuleName module = (ModuleName)Enum.Parse(typeof(ModuleName), param[1].ToString());
  1845. if (ModuleHelper.IsLoadPort(module))
  1846. {
  1847. var lp = DEVICE.GetDevice<LoadPortBaseDevice>(module.ToString());
  1848. if (lp != null)
  1849. lp.NoteTransferStart();
  1850. }
  1851. BladeTarget = module;
  1852. Blade1Target = module;
  1853. Blade2Target = module;
  1854. int slot = (int)param[2] + 1;
  1855. string TrsSt = GetStationsName(module);
  1856. if (string.IsNullOrEmpty(TrsSt))
  1857. {
  1858. LOG.Write("Invalid Paramter.");
  1859. return false;
  1860. }
  1861. string strpara = "";
  1862. if (_MaterialType == MaterialType.Wafer)
  1863. {
  1864. int bladeNo = (arm == RobotArmEnum.Blade1 || arm == RobotArmEnum.Lower) ? 4 : 31;
  1865. strpara = $"G,{TrsSt},{slot:D3},{bladeNo:D3}";
  1866. }
  1867. else if (_MaterialType == MaterialType.Carrier)
  1868. {
  1869. string strHand = GetHandsName(module);
  1870. if (string.IsNullOrEmpty(strHand))
  1871. {
  1872. LOG.Write("Invalid Paramter.");
  1873. return false;
  1874. }
  1875. strpara = $"G,{TrsSt},001,{strHand}";
  1876. }
  1877. lock (_locker)
  1878. {
  1879. _lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, "MTRS", strpara, _timeLimitPick));
  1880. _lstHandlers.AddLast(new GM201LVPRobotReadHandler(this, "RSTS"));
  1881. }
  1882. CmdTarget = module;
  1883. MoveInfo = new RobotMoveInfo()
  1884. {
  1885. Action = RobotAction.Moving,
  1886. ArmTarget = CmdRobotArm == RobotArmEnum.Lower ? RobotArm.ArmA : RobotArm.ArmB,
  1887. BladeTarget = BuildBladeTarget(),
  1888. };
  1889. _timerActionMonitor.Restart();
  1890. return true;
  1891. }
  1892. catch (Exception ex)
  1893. {
  1894. LOG.Write(ex);
  1895. return false;
  1896. }
  1897. }
  1898. protected override bool fMonitorPick(object[] param)
  1899. {
  1900. IsBusy = false;
  1901. if (_timerActionMonitor.IsRunning && _timerActionMonitor.Elapsed > TimeSpan.FromSeconds(_timeLimitPick))
  1902. {
  1903. _timerActionMonitor.Stop();
  1904. OnError("PickTimeOut");
  1905. return true;
  1906. }
  1907. if (_lstHandlers.Count == 0 && !_connection.IsBusy)
  1908. {
  1909. _timerActionMonitor.Stop();
  1910. //EV.PostInfoLog(Name, "Pick complete");
  1911. fPickComplete(param);
  1912. BladeTarget = ModuleName.System;
  1913. Blade1Target = ModuleName.System;
  1914. Blade2Target = ModuleName.System;
  1915. CmdTarget = ModuleName.System;
  1916. MoveInfo = new RobotMoveInfo()
  1917. {
  1918. Action = RobotAction.Moving,
  1919. ArmTarget = CmdRobotArm == RobotArmEnum.Lower ? RobotArm.ArmA : RobotArm.ArmB,
  1920. BladeTarget = BuildBladeTarget(),
  1921. };
  1922. return true;
  1923. }
  1924. return false;
  1925. }
  1926. protected override bool fPickComplete(object[] param)
  1927. {
  1928. if (_isError)
  1929. {
  1930. OnError("RobotError");
  1931. return true;
  1932. }
  1933. RobotArmEnum arm = (RobotArmEnum)CurrentParamter[0];
  1934. ModuleName module = (ModuleName)Enum.Parse(typeof(ModuleName), CurrentParamter[1].ToString());
  1935. ModuleName sourcemodule;
  1936. if (!Enum.TryParse(CurrentParamter[1].ToString(), out sourcemodule)) return false;
  1937. int SourceslotIndex;
  1938. if (!int.TryParse(CurrentParamter[2].ToString(), out SourceslotIndex)) return false;
  1939. int delayCount = 0;
  1940. if (arm == RobotArmEnum.Lower || arm == RobotArmEnum.Blade1)
  1941. {
  1942. //WaferManager.Instance.WaferMoved(sourcemodule, SourceslotIndex, RobotModuleName, 0);
  1943. while (!isSimulatorMode && GetWaferState(arm) != RobotArmWaferStateEnum.Present)
  1944. {
  1945. delayCount++;
  1946. LOG.Write($"{RobotModuleName} delay {delayCount} time to detect wafer");
  1947. Thread.Sleep(50);
  1948. if (delayCount > 100)
  1949. {
  1950. OnError("Wafer detect error");
  1951. return true;
  1952. }
  1953. }
  1954. if (_MaterialType == MaterialType.Wafer)
  1955. {
  1956. WaferManager.Instance.WaferMoved(sourcemodule, SourceslotIndex, RobotModuleName, 2);
  1957. }
  1958. else if (_MaterialType == MaterialType.Carrier)
  1959. {
  1960. if (CarrierManager.Instance.CheckHasCarrier(sourcemodule.ToString(), 0))
  1961. {
  1962. CarrierManager.Instance.CarrierMoved(sourcemodule.ToString(), RobotModuleName.ToString(), true);
  1963. for (int i = 0; i < WaferManager.Instance.GetWafers(sourcemodule).Length; i++)
  1964. {
  1965. if (WaferManager.Instance.CheckHasWafer(sourcemodule, i))
  1966. WaferManager.Instance.WaferMoved(sourcemodule, i, RobotModuleName, i, false);
  1967. }
  1968. }
  1969. }
  1970. }
  1971. if (arm == RobotArmEnum.Upper || arm == RobotArmEnum.Blade2)
  1972. {
  1973. //WaferManager.Instance.WaferMoved(sourcemodule, SourceslotIndex, RobotModuleName, 1);
  1974. while (!isSimulatorMode && GetWaferState(arm) != RobotArmWaferStateEnum.Present)
  1975. {
  1976. delayCount++;
  1977. LOG.Write($"{RobotModuleName} delay {delayCount} time to detect wafer");
  1978. Thread.Sleep(50);
  1979. if (delayCount > 100)
  1980. {
  1981. OnError("Wafer detect error");
  1982. return true;
  1983. }
  1984. }
  1985. WaferManager.Instance.WaferMoved(sourcemodule, SourceslotIndex, RobotModuleName, 1);
  1986. }
  1987. if (arm == RobotArmEnum.Both)
  1988. {
  1989. //WaferManager.Instance.WaferMoved(sourcemodule, SourceslotIndex, RobotModuleName, 0);
  1990. //WaferManager.Instance.WaferMoved(sourcemodule, SourceslotIndex, RobotModuleName, 1);
  1991. while (!isSimulatorMode && GetWaferState(arm) != RobotArmWaferStateEnum.Present)
  1992. {
  1993. delayCount++;
  1994. LOG.Write($"{RobotModuleName} delay {delayCount} time to detect wafer");
  1995. Thread.Sleep(50);
  1996. if (delayCount > 100)
  1997. {
  1998. OnError("Wafer detect error");
  1999. return true;
  2000. }
  2001. }
  2002. WaferManager.Instance.WaferMoved(sourcemodule, SourceslotIndex, RobotModuleName, 0);
  2003. WaferManager.Instance.WaferMoved(sourcemodule, SourceslotIndex + 1, RobotModuleName, 1);
  2004. WaferManager.Instance.WaferMoved(sourcemodule, SourceslotIndex + 2, RobotModuleName, 2);
  2005. WaferManager.Instance.WaferMoved(sourcemodule, SourceslotIndex + 3, RobotModuleName, 3);
  2006. WaferManager.Instance.WaferMoved(sourcemodule, SourceslotIndex + 4, RobotModuleName, 4);
  2007. }
  2008. return base.fPickComplete(param);
  2009. }
  2010. protected override bool fResetToReady(object[] param)
  2011. {
  2012. if (_doRobotHold != null)
  2013. _doRobotHold.SetTrigger(true, out _);
  2014. return true;
  2015. }
  2016. protected override bool fReset(object[] param)
  2017. {
  2018. if (!_connection.IsConnected)
  2019. {
  2020. _address = SC.GetStringValue($"{Name}.Address");
  2021. _enableLog = SC.GetValue<bool>($"{Name}.EnableLogMessage");
  2022. _connection = new GM201LVPRobotConnection(this, _address);
  2023. _connection.EnableLog(_enableLog);
  2024. _connection.Connect();
  2025. }
  2026. var alarmSignaRobotAlarm = DEVICE.GetDevice<IoAlarmSignal>($"PM1.AlarmSignaFOUPRobotAlarm");
  2027. if (Name == "WaferRobot")
  2028. alarmSignaRobotAlarm = DEVICE.GetDevice<IoAlarmSignal>($"PM1.AlarmSignaWaferRobotAlarm");
  2029. if (_isError || (alarmSignaRobotAlarm != null && alarmSignaRobotAlarm.Value))
  2030. {
  2031. lock (_locker)
  2032. {
  2033. string strpara = "1,1,N";
  2034. _lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, "INIT", strpara));
  2035. }
  2036. _isError = false;
  2037. return true;
  2038. }
  2039. lock (_locker)
  2040. {
  2041. if (_doRobotHold != null)
  2042. _doRobotHold.SetTrigger(true, out _);
  2043. _lstHandlers.Clear();
  2044. _connection.ForceClear();
  2045. //_lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, "CCLR", "E", _timeLimitMotion));
  2046. //string strpara = "1,1,N";
  2047. //_lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, "INIT", strpara));
  2048. //string strpara = "1,0,N";
  2049. //_lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, "INIT", strpara, _timeLimitMotion));
  2050. //_lstHandlers.AddLast(new GM201LVPRobotReadHandler(this, "RSTS"));
  2051. _timerActionMonitor.Restart();
  2052. }
  2053. return true;
  2054. }
  2055. protected override bool fMonitorReset(object[] param)
  2056. {
  2057. IsBusy = false;
  2058. if (_timerActionMonitor.IsRunning && _timerActionMonitor.Elapsed > TimeSpan.FromSeconds(_timeLimitMotion))
  2059. {
  2060. _timerActionMonitor.Stop();
  2061. OnError("ResetTimeOut");
  2062. return true;
  2063. }
  2064. if (_lstHandlers.Count == 0 && !_connection.IsBusy)
  2065. {
  2066. return true;
  2067. }
  2068. return false;
  2069. }
  2070. protected override bool fError(object[] param)
  2071. {
  2072. return true;
  2073. }
  2074. protected override bool fStartExtendForPick(object[] param)
  2075. {
  2076. return false;
  2077. }
  2078. protected override bool fStartExtendForPlace(object[] param)
  2079. {
  2080. return false;
  2081. }
  2082. protected override bool fStartRetractFromPick(object[] param)
  2083. {
  2084. return false;
  2085. }
  2086. protected override bool fStartRetractFromPlace(object[] param)
  2087. {
  2088. return false;
  2089. }
  2090. public void CheckWaferPresentAndGrip()
  2091. {
  2092. if (GetWaferState(RobotArmEnum.Lower) == RobotArmWaferStateEnum.Present)
  2093. {
  2094. if (WaferManager.Instance.CheckNoWafer(RobotModuleName, 0))
  2095. {
  2096. EV.PostWarningLog($"{RobotModuleName}", $"System detec wafer on lower arm, will create wafer automatically.");
  2097. WaferManager.Instance.CreateWafer(RobotModuleName, 0, WaferStatus.Normal);
  2098. }
  2099. }
  2100. if (GetWaferState(RobotArmEnum.Lower) == RobotArmWaferStateEnum.Absent)
  2101. {
  2102. _lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, "CSOL", "1,0,0"));
  2103. if (WaferManager.Instance.CheckHasWafer(RobotModuleName, 0))
  2104. {
  2105. EV.PostWarningLog($"{RobotModuleName}", $"System didn't detect wafer on lower arm, but it has record.");
  2106. }
  2107. }
  2108. if (GetWaferState(RobotArmEnum.Upper) == RobotArmWaferStateEnum.Present)
  2109. {
  2110. if (WaferManager.Instance.CheckNoWafer(RobotModuleName, 1))
  2111. {
  2112. EV.PostWarningLog($"{RobotModuleName}", $"System detect wafer on upper arm, will create wafer automatically.");
  2113. WaferManager.Instance.CreateWafer(RobotModuleName, 1, WaferStatus.Normal);
  2114. }
  2115. }
  2116. if (GetWaferState(RobotArmEnum.Upper) == RobotArmWaferStateEnum.Absent)
  2117. {
  2118. _lstHandlers.AddLast(new GM201LVPRobotMotionHandler(this, "CSOL", "2,0,0"));
  2119. if (WaferManager.Instance.CheckHasWafer(RobotModuleName, 1))
  2120. {
  2121. EV.PostWarningLog($"{RobotModuleName}", $"System didn't detect wafer on upper arm, but it has record.");
  2122. }
  2123. }
  2124. }
  2125. public override RobotArmWaferStateEnum GetWaferState(RobotArmEnum arm)
  2126. {
  2127. if (arm == RobotArmEnum.Lower || arm == RobotArmEnum.Blade1)
  2128. {
  2129. if (_diRobotBlade1WaferOn != null)
  2130. {
  2131. if (_diRobotBlade1WaferOn.Value) return RobotArmWaferStateEnum.Absent;
  2132. else return RobotArmWaferStateEnum.Present;
  2133. }
  2134. var waferPresenceOnBlade1 = _MaterialType == MaterialType.Wafer ? IsWaferPresenceOnBlade3 : IsWaferPresenceOnBlade1;
  2135. return waferPresenceOnBlade1 ? RobotArmWaferStateEnum.Present : RobotArmWaferStateEnum.Absent;
  2136. }
  2137. if (arm == RobotArmEnum.Upper || arm == RobotArmEnum.Blade2)
  2138. {
  2139. if (_diRobotBlade2WaferOn != null)
  2140. {
  2141. if (_diRobotBlade2WaferOn.Value) return RobotArmWaferStateEnum.Absent;
  2142. else return RobotArmWaferStateEnum.Present;
  2143. }
  2144. return IsWaferPresenceOnBlade2 ? RobotArmWaferStateEnum.Present : RobotArmWaferStateEnum.Absent;
  2145. }
  2146. if (arm == RobotArmEnum.Both)
  2147. {
  2148. if (_diRobotBlade1WaferOn != null && _diRobotBlade2WaferOn != null)
  2149. {
  2150. if (_diRobotBlade2WaferOn.Value && _diRobotBlade1WaferOn.Value)
  2151. return RobotArmWaferStateEnum.Absent;
  2152. else if (!_diRobotBlade2WaferOn.Value && !_diRobotBlade1WaferOn.Value)
  2153. return RobotArmWaferStateEnum.Present;
  2154. else return RobotArmWaferStateEnum.Unknown;
  2155. }
  2156. if (IsWaferPresenceOnBlade1 && IsWaferPresenceOnBlade2 && IsWaferPresenceOnBlade3 && IsWaferPresenceOnBlade4 && IsWaferPresenceOnBlade5)
  2157. {
  2158. return RobotArmWaferStateEnum.Present;
  2159. }
  2160. if ((!IsWaferPresenceOnBlade1) && !IsWaferPresenceOnBlade2 && !IsWaferPresenceOnBlade3 && !IsWaferPresenceOnBlade4 && !IsWaferPresenceOnBlade5)
  2161. {
  2162. return RobotArmWaferStateEnum.Absent;
  2163. }
  2164. }
  2165. return RobotArmWaferStateEnum.Unknown;
  2166. }
  2167. public override void NoteError(string errortext)
  2168. {
  2169. _isError = true;
  2170. if (!string.IsNullOrEmpty(errortext))
  2171. OnError(errortext);
  2172. //lock (_locker)
  2173. {
  2174. _lstHandlers.Clear();
  2175. _connection.ForceClear();
  2176. if (_tpStatus != null && _tpStatus.Value)
  2177. {
  2178. //true是TP状态
  2179. //TP状态,不需要发
  2180. }
  2181. else
  2182. {
  2183. _lstHandlers.AddLast(new GM201LVPRobotReadHandler(this, "RERR", "001"));
  2184. }
  2185. }
  2186. }
  2187. //public void SenACK()
  2188. //{
  2189. // _connection.SendAck();
  2190. //}
  2191. public override bool OnActionDone(object[] param)
  2192. {
  2193. return true;
  2194. }
  2195. public override void Terminate()
  2196. {
  2197. _thread.Stop();
  2198. if (!SC.ContainsItem($"{Name}.CloseConnectionOnShutDown") || SC.GetValue<bool>($"{Name}.CloseConnectionOnShutDown"))
  2199. {
  2200. LOG.Write("Close connection for" + RobotModuleName.ToString());
  2201. _connection.Disconnect();
  2202. }
  2203. base.Terminate();
  2204. }
  2205. private string BuildBladeTarget()
  2206. {
  2207. return (CmdRobotArm == RobotArmEnum.Upper ? "ArmB" : "ArmA") + "." + CmdTarget;
  2208. }
  2209. public override void SetPauseResume(bool isPause)
  2210. {
  2211. _connection.SendMessage($"{(isPause ? "CSTP,H" : "CRSM")}\r");
  2212. if (_connection.ActiveHandler != null)
  2213. {
  2214. if (isPause)
  2215. {
  2216. _connection.ActiveHandler.TimerAck?.Stop();
  2217. _connection.ActiveHandler.TimerComplete?.Stop();
  2218. }
  2219. else
  2220. {
  2221. _connection.ActiveHandler.TimerAck?.Start();
  2222. _connection.ActiveHandler.TimerComplete?.Start();
  2223. }
  2224. }
  2225. }
  2226. public void NotePause(bool isPause)
  2227. {
  2228. IsPause = isPause;
  2229. }
  2230. }
  2231. public class GM201LVPTokenGenerator
  2232. {
  2233. private int _last = 0;
  2234. List<int> _pool = new List<int>();
  2235. SCConfigItem scToken = null;
  2236. public int CurrentToken => _last;
  2237. public GM201LVPTokenGenerator(string scName)
  2238. {
  2239. scToken = SC.GetConfigItem(scName);
  2240. if (scToken == null)
  2241. _last = scToken.IntValue;
  2242. Random r = new Random();
  2243. _last = r.Next() % 20;
  2244. }
  2245. public int create()
  2246. {
  2247. int first = _last;
  2248. int token = first;
  2249. do
  2250. {
  2251. token = (token + 1) % 100;
  2252. if (_pool.Contains(token))
  2253. continue;
  2254. _pool.Add(token);
  2255. _last = token;
  2256. scToken.IntValue = _last;
  2257. return _last;
  2258. } while (token != first);
  2259. throw (new ExcuteFailedException("Get token failed,pool is full"));
  2260. }
  2261. public void release(int token)
  2262. {
  2263. _pool.Remove(token);
  2264. }
  2265. public void release()
  2266. {
  2267. _last = 0;
  2268. _pool.Clear();
  2269. }
  2270. }
  2271. public enum GM201LVPPositonEnum
  2272. {
  2273. RegisteredPosition,
  2274. ReadyPosition,
  2275. IntermediatePosition,
  2276. MappingStartPosition,
  2277. MappingFinishPosition,
  2278. }
  2279. }