using Aitex.Core.RT.Log; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using MECF.Framework.Common.Communications; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.ModuleLibrary.VceModules; using System; using System.Collections.Generic; using System.IO.Ports; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using Venus_Core; namespace Venus_RT.Devices.PreAligner { public class HongHuVPA : IPreAlign { private AsyncSerialPort _serialport;//串口 private string _newLine = "\r";//结束符号 private object _locker = new object();//锁变量 private bool _IsAsciiMode = true; private PeriodicJob _thread; //private string _CurrentMsg; private RState _state; private Regex _catchErrorCode = new Regex(@"(?<=_ERR )(.*)"); private Regex _checkData = new Regex(@"(?<=DATA)(.*)"); private LinkedList _lstMessage = new LinkedList(); private ModuleName _module; private enum AlignerAction { Home, Align, AlignWithAngle, Reset, Scan, RsLT, ServeUp, } private Dictionary _ErrorCode2Msg = new Dictionary() { { 16 , "" }, }; private Dictionary _Command2Msg = new Dictionary() { //Action { AlignerAction.Align , "ALGN" },//旋转到预设的站点方向 { AlignerAction.AlignWithAngle, "MOVT REL" },//旋转到指定的角度 { AlignerAction.Home , "HOME" },//Home 初始化时 error时用 { AlignerAction.Reset , "RSET" },//重置 error时用 { AlignerAction.Scan , "SCAN" },//扫描整个Wafer参数 { AlignerAction.RsLT , "RSLT" }, //Read //{ "" , "RQCD" }, //{ "" , "RQCCDPOS" }, //{ "" , "RQID" }, //{ "" , "RQPS" }, //Set //{ "" , "" }, //Welding //{ "" , "SVCD" }, }; public ModuleName Module => _module; public bool IsConnect => _serialport.IsOpen(); public RState Status => _state;//状态 public bool IsError => _state == RState.Failed || _state == RState.Timeout; private int _ROffset = 0; private int _TOffset = 0; private bool _IsOverRange = false; public int ROffset => _ROffset; public int TOffset => _TOffset; public bool IsOverRange => _IsOverRange; public HongHuVPA(ModuleName module) { _module = module; string port = SC.GetStringValue($"{module}.AlignerPort"); _serialport = new AsyncSerialPort(port, 9600, 8, Parity.None, StopBits.One, _newLine, _IsAsciiMode); WaferManager.Instance.SubscribeLocation(ModuleName.Aligner1, 1); _serialport.Open(); _serialport.OnDataChanged += OnReceiveData; _state = RState.Init; _thread = new PeriodicJob(50, OnTimer, "OnTimer->Aligner1"); _thread.Start(); } //收到新消息时的处理 private void OnReceiveData(string obj) { lock (_locker) { if (string.IsNullOrEmpty(_newLine))//没有CR { _lstMessage.AddLast(obj);//将消息添加到最后 return; } string[] array = obj.Split(_newLine.ToCharArray());//按照cr分开通讯数据 foreach (string text in array) { if (!string.IsNullOrEmpty(text)) { _lstMessage.AddLast(text + _newLine);//存进list中等待处理 } } } } //定时器处理新信息为状态 private bool OnTimer() { //线程锁 lock (_locker) { //采用ascii码模式处理 if (_IsAsciiMode) { //存在尚未处理的信息 while (_lstMessage.Count > 0) { //获取头上的数据 string handlemsg = _lstMessage.First.Value; Handlemessage(handlemsg); _lstMessage.RemoveFirst(); } } //采用binary模式处理 else { } } return true; } //处理单条信息 private void Handlemessage(string handlemsg) { //需要按类型进行处理 Action需要将其error bool IsAction = true; handlemsg = handlemsg.Trim(); if (IsAction) { switch (handlemsg) { //正确执行 case "_RDY": _state = RState.End; break; //返回 default: if (_checkData.IsMatch(handlemsg)) { string[] data = handlemsg.Split(' '); _ROffset = Convert.ToInt32(data[2]); _TOffset = Convert.ToInt32(data[3]); if (data[5] == "Y") { _IsOverRange = true; LOG.Write(eEvent.WARN_DEVICE_INFO, Module, $"Wafer offset is over range"); } if (data[5] == "N") { _IsOverRange = false; LOG.Write(eEvent.EV_DEVICE_INFO, Module, $"Wafer offset is in range"); } LOG.Write(eEvent.EV_DEVICE_INFO, Module, $"Ro{_ROffset} To{_TOffset}"); } else { _state = RState.Failed; //分两种 1、不按格式的未知错误 2、有错误码的 if (_catchErrorCode.IsMatch(handlemsg)) { int errorcode = Convert.ToInt32(_catchErrorCode.Match(handlemsg).Value); if (_ErrorCode2Msg.ContainsKey(errorcode)) { LOG.Write(eEvent.ERR_DEVICE_INFO, Module, _ErrorCode2Msg[errorcode]); } else { LOG.Write(eEvent.ERR_DEVICE_INFO, Module, $"未知错误码{errorcode}"); } } else { LOG.Write(eEvent.ERR_DEVICE_INFO, Module, "未收录相关错误"); } } break; } } } //发送消息 private bool SendMessage(string msg, params string[] args) { _state = RState.Running; if (args.Length > 0)//含参 { foreach (string arg in args) msg = msg + " " + arg; LOG.WriteSingeLine(eEvent.EV_DEVICE_INFO, _module, $"Send Command to HongHu Aligner: {msg}"); return _serialport.Write(msg + _newLine); } else//空参 { LOG.WriteSingeLine(eEvent.EV_DEVICE_INFO, _module, $"Send Command to HongHu Aligner: {msg}"); return _serialport.Write(msg + _newLine); } } public bool Home() { return SendMessage(_Command2Msg[AlignerAction.Home]); } public bool Align() { if (!CanSendCommand()) return false; return SendMessage(_Command2Msg[AlignerAction.Align]); } public bool AlignWithAngle(float angle) { if (!CanSendCommand()) return false; int ang = (int)Math.Floor(angle);//不能用Convert.toInt32("angle") 其遵守四舍五入 此处需向上取整 return SendMessage(_Command2Msg[AlignerAction.AlignWithAngle], ang.ToString()); } public bool ReSet() { if (!IsError) return false; return SendMessage(_Command2Msg[AlignerAction.Reset]); } public bool SCAN() { if (!CanSendCommand()) return false; return SendMessage(_Command2Msg[AlignerAction.Scan]); } public bool QueryOffset() { if (!CanSendCommand()) return false; return SendMessage(_Command2Msg[AlignerAction.RsLT]); } public bool ServeUp() { _state = RState.End; return true; } public bool CanSendCommand() { if (Status == RState.Init) { LOG.Write(eEvent.ERR_DEVICE_INFO, _module, "Aligner is not homed, please home first."); return false; } else if (Status == RState.Running) { LOG.Write(eEvent.ERR_DEVICE_INFO, _module, "Aligner is busy, please wait a minute"); return false; } else if (Status == RState.Failed || Status == RState.Timeout) { LOG.Write(eEvent.ERR_DEVICE_INFO, _module, "Aligner has a error, please check and fix the hardware issue and home it"); return false; } return true; } } }