using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Aitex.Sorter.Common; using athosRT.tool; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace athosRT.Devices.PA { public class RorzePreAligner : PreAligner { #region 私有变量 private string _address;//地址 private string _port;//端口 private readonly AsyncSocket _socket;//通讯socket private string _newLine = "\r"; private object _locker = new object(); private bool _isAsciiMode; private LinkedList _lstAsciiMsgs = new LinkedList(); private Regex catch_parameter = new Regex(@"(?<=\:)(.*)");//获取:后续参数 private bool _errorflag; private PeriodicJob _thread; private Dictionary cancelcode2msg = new Dictionary() { {"0001","Command not designated" }, {"0002","The designated target motion not equipped" }, {"0003","Too many/too few parameters (number of elements)" }, {"0004","Command not equipped" }, {"0005","Too many/too few parameters" }, {"0006","Abnormal range of the parameter" }, {"0007","Abnormal mode" }, {"0008","Abnormal data" }, {"0009","System in preparation" }, {"000A","Origin search not completed" }, {"000B","Moving/Processing" }, {"000C","No motion" }, {"000D","Abnormal flash memory" }, {"000E","Insufficient memory" }, {"000F","Error-occurred state" }, {"0010","Origin search is completed but the motion cannot be started due to interlock." }, {"0011","The emergency stop signal is turned on." }, {"0012","The temporarily stop signal is turned on." }, {"0013","Abnormal interlock signal" }, {"0014","Drive power is turned off." }, {"0015","Not excited" }, {"0016","Abnormal current position" }, {"0017","Abnormal target position" }, {"0018","Command processing" }, {"0019","Invalid substrate state" }, {"0020","Substrate yet to be aligned" }, {"FFFF","Fatal error is occurring.need to cycle the power." }, }; private Dictionary errorcode2msg = new Dictionary() { {"01","Motor stall" }, {"02","Limit" }, {"03","Limit" }, {"04","Command error" }, {"05","Communication error" }, {"06","Abnormal sensor" }, {"07","Driver EMS error" }, {"08","Substrate dropped error" }, {"0E","Abnormal driver" }, {"0F","Abnormal drive power" }, {"10","Abnormal control power" }, {"13","Abnormal temperature of driver" }, {"14","Driver FPGA error" }, {"15","Motor wire broken" }, {"16","Motor over load" }, {"17","Motor motion start error" }, {"18","Abnormal alignment sensor" }, {"19","Abnormal exhaust FAN state" }, {"1A","Alignment sensor detects obstacle" }, {"40","Internal error (abnormal device driver)" }, {"41","Internal error (abnormal driver control)" }, {"42","Internal error (task start failed)" }, {"45","Reading setting data failed" }, {"7E","CPU reset error" }, {"7F","Controller internal memory error" }, {"80","Intelock signal is abnormal" }, {"83","Origin search failed" }, {"84","Chucking error" }, {"90","Notch detection error" }, {"91","Alignment sensor detects obstacle" }, {"92","Retry over (alignment failed)" }, {"93","Shifting motion retry over" }, {"96","Sub o-flat location error" }, {"97","Substrate center deviation error" }, }; private PAStatus _status; #endregion #region 暴露变量 public override PAStatus Status => _status; public override bool IsConnected => _socket.IsConnected; public override bool Busy => _status != PAStatus.Idle && _status != PAStatus.Init ; public override bool Moving => base.Moving; public override bool Error => _errorflag; //public override bool WaferOnAligner => base.WaferOnAligner; public PAStatus AlignStatus => _status; #endregion /// /// PA的关键点 /// 通信方式:网口 /// 主要功能:1、旋转对齐 2、初始化位置HOME 3、除错 4、重置 5、中断 /// /// /// /// /// /// public RorzePreAligner(string module, string name, string display, string deviceId, string address) : base(module, name, display, deviceId, address) { base.Module = module; base.Name = name; _address = SC.GetStringValue($"{name}.Address");//从SC获取address _isAsciiMode = true; _socket = new AsyncSocket(_address, _newLine); _socket.OnDataChanged += OnReceiveMessage; _errorflag = false; _status = PAStatus.Init; Connect(); _thread = new PeriodicJob(50, OnTimer, $"{name}->RT", true); } /// /// 定时函数 用来监听最新收到的消息 并交给函数处理 /// /// private bool OnTimer() { //处理消息 lock (_locker) { if (_isAsciiMode)//按照ascii码处理 { while (_lstAsciiMsgs.Count > 0) { string value = _lstAsciiMsgs.First.Value; HandleAsciiData(value); _lstAsciiMsgs.RemoveFirst(); } } } return true; } //当收到新数据时 private void OnReceiveMessage(string RevMsg) { //处理粘包 按照newline拆开 lock (_locker) { if (string.IsNullOrEmpty(_newLine))//没有CR { _lstAsciiMsgs.AddLast(RevMsg);//将消息添加到最后 return; } string[] array = RevMsg.Split(_newLine.ToCharArray());//按照cr分开通讯数据 foreach (string text in array) { if (!string.IsNullOrEmpty(text)) { _lstAsciiMsgs.AddLast(text + _newLine);//存进list中等待处理 } } } } //利用定时器 对处理好的数据进行处理 private void HandleAsciiData(string msg) { try { //不是空的情况下 if (!string.IsNullOrEmpty(msg)) { //首先处理头 switch (msg[0]) { case 'n': //错误处理代码 LogObject.Error(Name, "传参不符合格式"); break; case 'c': //取消处理代码 string param_code = catch_parameter.Match(msg).Value; if (cancelcode2msg.ContainsKey(param_code)) { string cancel_reason = cancelcode2msg[param_code]; LogObject.Error(Name, cancel_reason); } else LogObject.Error(Name, "未定义相关cancel code"); break; case 'e': //大于7说明错误代码是存在的 if (msg.Length > 7) { //提取最后两位错误 作为索引 string errorcode = msg.Substring(msg.Length-2,2); if (errorcode2msg.ContainsKey(errorcode)) { string error_reason = errorcode2msg[errorcode]; LogObject.Error(Name, error_reason); } _errorflag = true; } break; case 'a': //正常结束 _status = PAStatus.Idle; break; default: break; } } } catch (Exception ex) { LogObject.Error(Name, ex); } } public override bool Connect() { _socket.Connect(_address); return _socket.IsConnected; } public override bool Disconnect() { _socket.Dispose(); return _socket.IsConnected; } public override bool Home(out string reason) { reason = ""; if (_socket.Write("oALN1.HOME"+_newLine) && _status != PAStatus.Home) _status = PAStatus.Home; return _status == PAStatus.Home; } public override bool Align(double angle, out string reason) { reason = ""; //1基板对齐 //7不吸附的对齐 //10双O基板对齐 //11双O基板亚O面对齐 if(_socket.Write($"oALN1.ALGN(1,{angle})"+_newLine)) _status = PAStatus.Align; return _status == PAStatus.Align; } public override bool Clear(out string reason) { //利用RSTA清错误 reason = ""; if(_socket.Write("oALN1.RSTA(1)"+_newLine)) _status = PAStatus.Reset; return _status == PAStatus.Reset; } public override bool Init(out string reason) { //初始化 reason = ""; return _socket.Write("oALN1.INIT" + _newLine); } public override void Reset() { //重置 _status = PAStatus.Reset; if (_socket.Write("oALN1.RSTA(1)" + _newLine)) _status = PAStatus.Reset; } public override bool Stop(out string reason) { //停止 reason = ""; return _socket.Write("oALN1.STOP" + _newLine); } public override void Terminate() { //暂停 _socket.Write("oALN1.PAUS" + _newLine); } public override bool QueryState(out string reason) { //查询设备状态 reason = ""; return _socket.Write("oALN1.STAT" + _newLine); } public override bool Initialize() { return true; } public override bool Grip(Hand hand, out string reason) { return base.Grip(hand, out reason); } public override bool Release(Hand hand, out string reason) { return base.Release(hand, out reason); } public override bool LiftDown(out string reason) { return base.LiftDown(out reason); } public override bool LiftUp(out string reason) { return base.LiftUp(out reason); } public override void Monitor() { base.Monitor(); } public override bool MoveToReady(out string reason) { return base.MoveToReady(out reason); } public override string ToString() { return base.ToString(); } public override bool Equals(object obj) { return base.Equals(obj); } public override int GetHashCode() { return base.GetHashCode(); } } }