Sic.Framework-Nanjing-Baishi/MECF.Framework.RT.Equipment.../HardwareUnits/Aligners/HiWinAligner/HwAlignerGuide.cs

611 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using MECF.Framework.Common.Communications;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Aligners.HiWinAligner.Handlers;
namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Aligners.HiWinAligner
{
public class HwAlignerGuide : BaseDevice, IConnection, IDevice
{
#region Variables
private enum CommandEnum
{
NULL,
SME11,
SME21,
SME31,
HOM,
DOC,
CVN,
MTM,
CCD,
BAL,
MVR,
CVF,
ERS,
STA,
//
SPS,
WSZ,
_WT,
GLM,
FWO,
};
private HwAlignerGuideConnection _connection;
private readonly bool _activeMonitorStatus;
private readonly R_TRIG _trigCommunicationError = new();
private readonly R_TRIG _trigRetryConnect = new();
private bool _bIsDisconnect = false;
private string _lastHandlerName;
private CommandEnum _iCurrentOper = CommandEnum.NULL;
private readonly LinkedList<HandlerBase> _lstHandler = new();
private readonly object _locker = new();
#endregion
#region Constructors
/// <summary>
/// 构造上银巡边器对象实例。
/// </summary>
/// <param name="module">所属模组名称。</param>
/// <param name="scRoot">系统配置定义了当前巡边器相关配置的节点。</param>
/// <param name="name">当前巡边器名称。</param>
public HwAlignerGuide(string module, string scRoot, string name) : base(module, name, name, name)
{
ScBasePath = scRoot;
_activeMonitorStatus = true;
}
#endregion
#region Properties
public bool HaveWafer { get; set; }
public string Address { get; set; }
public bool IsConnected => _connection is { IsConnected: true };
public bool AlarmStatus { get; set; }
public bool PositionComplete { get; set; }
public bool MotorBusy { get; set; }
public bool IsBusy
{
get
{
lock (_locker)
{
return _lstHandler.Count > 0 || _iCurrentOper != CommandEnum.NULL;
}
}
}
#endregion
#region Private Methods
private void InitData()
{
DATA.Subscribe($"{Module}.{Name}.HaveWafer", () => HaveWafer);
}
private void InitOp()
{
//参数保存
OP.Subscribe($"{Module}.{Name}.HwSaveParameters", (_, _) =>
{
Set("SPS");
return true;
});
//读取/设定晶圆尺寸
OP.Subscribe($"{Module}.{Name}.HwWaferSize", (_, param) =>
{
Set("WSZ" + " " + param[0]);
return true;
});
//晶圆种类
OP.Subscribe($"{Module}.{Name}.HwWaferType", (_, param) =>
{
Set("_WT" + " " + param[0]);
return true;
});
//寻边材质
OP.Subscribe($"{Module}.{Name}.HwWaferMaterial", (cmd, param) =>
{
Set("GLM" + " " + param[0]);
return true;
});
//晶圆方向
OP.Subscribe($"{Module}.{Name}.HwWaferOrientation", (cmd, param) =>
{
Set("FWO" + " " + param[0]);
return true;
});
//------------------------------------------------------------
//原点复归
OP.Subscribe($"{Module}.{Name}.HwHOM", (_, _) => MsgHome());
//晶圆确认
OP.Subscribe($"{Module}.{Name}.HwDOC", (_, _) => CheckWaferLoad());
//开启真空
OP.Subscribe($"{Module}.{Name}.HwCVN", (_, _) => OpenVacuum());
//寻边补正
OP.Subscribe($"{Module}.{Name}.HwBAL", (_, _) => MsgAliger());
//关闭真空
OP.Subscribe($"{Module}.{Name}.HwCVF", (_, _) => CloseVacuum());
//移至测量中心点
OP.Subscribe($"{Module}.{Name}.HwMTM", (_, _) => MoveToRobotPutPlace());
//清除报警
OP.Subscribe($"{Module}.{Name}.HwERS", (_, _) => ClearError());
//马达激磁
OP.Subscribe($"{Module}.{Name}.HwSME", (_, _) =>
{
InitMachine();
return true;
});
//相对位移
OP.Subscribe($"{Module}.{Name}.HwMVR", (cmd, param) =>
{
Set("MVR");
return true;
});
//
OP.Subscribe($"{Module}.{Name}.HwAbort", (cmd, param) =>
{
Abort();
return true;
});
}
private bool OnTimer()
{
try
{
_connection.MonitorTimeout();
//若断,重连
if ((!_connection.IsConnected) || _connection.IsCommunicationError || _bIsDisconnect)
{
_trigRetryConnect.CLK = _bIsDisconnect;
//重连机制要改timeout之后要是用心跳方式探测重连
_trigRetryConnect.CLK = _bIsDisconnect;
if (_connection.Connect())
{
_bIsDisconnect = false;
//
if (_trigRetryConnect.Q)
{
EV.PostInfoLog(Module, $"{Module}.{Name} connected");
LOG.Write($"{Module}.{Name} connected");
}
}
else
{
if (_trigRetryConnect.Q)
{
EV.PostInfoLog(Module,
$"Trying to connect {Module}.{Name} with address: {_connection.Address}");
LOG.Write($"Trying to connect {Module}.{Name} with address: {_connection.Address}");
}
}
}
//处理命令队列
HandlerBase handler = null;
if (!_connection.IsBusy)
{
lock (_locker)
{
if (_lstHandler.Count == 0 && _activeMonitorStatus && !IsBusy)
{
_lastHandlerName = "";
}
if (_lstHandler.Count > 0)
{
handler = _lstHandler.First.Value;
_lstHandler.RemoveFirst();
}
}
if (handler != null)
{
_lastHandlerName = handler.Name;
_connection.Execute(handler);
}
}
//
return true;
}
catch (Exception ex)
{
LOG.Write(ex);
}
return true;
}
internal void NoteError()
{
}
protected override void HandleMonitor()
{
try
{
_trigCommunicationError.CLK = _connection.IsCommunicationError;
if (_trigCommunicationError.Q)
{
EV.PostAlarmLog(Module,
$"{Module}.{Name} communication error, {_connection.LastCommunicationError}");
}
}
catch (Exception ex)
{
LOG.Write(ex);
}
}
#endregion
#region Methods
public bool Connect()
{
return true;
}
public bool Disconnect()
{
return true;
}
public bool Initialize()
{
// string portName = SC.GetStringValue($"{_scRoot}.{Module}.{Name}.Address");
var portName = SC.GetStringValue($"{ScBasePath}.Address");
Address = portName;
var scEnableLog = $"{ScBasePath}.EnableLogMessage";
var enableLog = SC.GetValue<bool>(scEnableLog);
SC.RegisterValueChangedCallback(scEnableLog, scValue =>
{
if (scValue is bool bEnableLog)
_connection.EnableLog(bEnableLog);
});
_connection = new HwAlignerGuideConnection(portName);
_connection.EnableLog(enableLog);
if (_connection.Connect())
{
EV.PostInfoLog(Module, $"{Module}.{Name} Connected");
}
var periodicJob = new PeriodicJob(200, OnTimer, $"{Name} MonitorHandler", true);
InitData();
InitOp();
ConnectionManager.Instance.Subscribe($"{Name}", this);
return true;
}
public void Abort()
{
}
/// <summary>
/// 初始化当前巡边器。
/// </summary>
public void InitMachine()
{
lock (_locker)
{
_lstHandler.Clear();
_lstHandler.AddLast(new HwAlignerGuideSetHandler(this, "SME11", "SME 11"));
_lstHandler.AddLast(new HwAlignerGuideSetHandler(this, "SME12", "SME 21"));
_lstHandler.AddLast(new HwAlignerGuideSetHandler(this, "SME13", "SME 31"));
}
}
/// <summary>
/// 开始巡边。
/// </summary>
public void Aligner()
{
lock (_locker)
{
_lstHandler.Clear();
_lstHandler.AddLast(new HwAlignerGuideSetHandler(this, "CVN", "CVN"));
_lstHandler.AddLast(new HwAlignerGuideSetHandler(this, "BAL", "BAL"));
_lstHandler.AddLast(new HwAlignerGuideSetHandler(this, "CVF", "CVF"));
}
}
/// <summary>
/// 回机械零点。
/// </summary>
/// <returns>
/// <value>True命令发送成功。</value>
/// <br/>
/// <value>False命令发送失败</value>
/// </returns>
public bool MsgHome()
{
//_lstHandler.Clear();
lock (_locker)
{
_lstHandler.AddLast(new HwAlignerGuideSetHandler(this, "HOM", "HOM", 30));
}
return true;
}
/// <summary>
/// 检测当前巡边器上是否有晶圆。
/// </summary>
/// <returns>
/// <value>True命令发送成功。</value>
/// <br/>
/// <value>False命令发送失败</value>
/// </returns>
public bool CheckWaferLoad()
{
lock (_locker)
{
_lstHandler.AddLast(new HwAlignerWaferCheckHandler(this));
}
return true;
}
/// <summary>
/// 打开当前巡边器的真空吸附。
/// </summary>
/// <returns>
/// <value>True命令发送成功。</value>
/// <br/>
/// <value>False命令发送失败</value>
/// </returns>
public bool OpenVacuum()
{
lock (_locker)
{
_lstHandler.AddLast(new HwAlignerGuideSetHandler(this, "CVN", "CVN"));
}
return true;
}
/// <summary>
/// 关闭当前巡边器的真空吸附。
/// </summary>
/// <returns>
/// <value>True命令发送成功。</value>
/// <br/>
/// <value>False命令发送失败</value>
/// </returns>
public bool CloseVacuum()
{
lock (_locker)
{
_lstHandler.AddLast(new HwAlignerGuideSetHandler(this, "CVF", "CVF"));
}
return true;
}
public bool MoveToRobotPutPlace()
{
lock (_locker)
{
_lstHandler.AddLast(new HwAlignerGuideSetHandler(this, "MTM", "MTM"));
}
return true;
}
public bool MsgAliger()
{
lock (_locker)
{
_lstHandler.AddLast(new HwAlignerGuideSetHandler(this, "BAL", "BAL"));
}
return true;
}
public bool DoAliger()
{
lock (_locker)
{
_lstHandler.Clear();
_lstHandler.AddLast(new HwAlignerGuideSetHandler(this, "CVN", "CVN"));
_lstHandler.AddLast(new HwAlignerGuideSetHandler(this, "BAL", "BAL"));
_lstHandler.AddLast(new HwAlignerGuideSetHandler(this, "CVF", "CVF"));
}
return true;
}
public bool ClearError()
{
lock (_locker)
{
_lstHandler.Clear();
_lstHandler.AddLast(new HwAlignerGuideSetHandler(this, "ERS", "ERS"));
}
return true;
}
/// <summary>
/// 新增一条命令到命令执行列队。
/// </summary>
/// <param name="command">命令字符。</param>
public void Set(string command)
{
lock (_locker)
{
_lstHandler.AddLast(new HwAlignerGuideSetHandler(this, command, command));
}
}
public void Terminate()
{
try
{
if (_connection != null)
{
_connection.Disconnect();
_connection = null;
}
}
catch (Exception ex)
{
LOG.Write(ex);
}
}
public void Reset()
{
_bIsDisconnect = _connection.IsCommunicationError;
//这里重置了CommunicationError 就是去了OnTimer里面的重连的触发所以需要另设变量以触发之(使用timeout来触发的情况
_connection.SetCommunicationError(false,"");
_trigCommunicationError.RST = true;
_trigRetryConnect.RST = true;
_iCurrentOper = CommandEnum.NULL;
lock (_locker)
_lstHandler.Clear();
}
public void SetCurrentOper()
{
_iCurrentOper = CommandEnum.CCD;
}
internal bool ParseData(string name, byte[] buffer, out bool bResult)
{
bResult = true;
var sAnswer = Encoding.ASCII.GetString(buffer);
if (sAnswer.Contains("END"))
{
_iCurrentOper = CommandEnum.NULL;
return true;
}
if (sAnswer.Contains("ERR"))
{
lock (_locker)
{
_lstHandler.Clear();
}
_iCurrentOper = CommandEnum.NULL;
bResult = false;
EV.PostAlarmLog(Module, $"Aligner, Execute {_lastHandlerName} error, {sAnswer.TrimEnd('\r', '\n')}");
return true; //Handled
}
return false;
}
internal bool CheckWaferDataA(string name, byte[] buffer, out bool bResult)
{
bResult = true;
var sAnswer = Encoding.ASCII.GetString(buffer.ToArray());
if (sAnswer.Contains("END"))
{
HaveWafer = sAnswer.Contains("1\r\nEND");
_iCurrentOper = CommandEnum.NULL;
return true;
}
if (sAnswer.Contains("ERR"))
{
lock (_locker)
{
_lstHandler.Clear();
}
_iCurrentOper = CommandEnum.NULL;
bResult = false;
EV.PostAlarmLog(Module, $"Aligner, Execute {_lastHandlerName} error, {sAnswer.TrimEnd('\r', '\n')}");
return false; //Handle
}
return false;
}
}
#endregion
}