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

603 lines
16 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
2023-04-13 11:51:03 +08:00
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;
2023-04-13 11:51:03 +08:00
namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Aligners.HiWinAligner
2023-04-13 11:51:03 +08:00
{
public class HwAlignerGuide : BaseDevice, IConnection, IDevice
{
#region Variables
2023-04-13 11:51:03 +08:00
private enum CommandEnum
{
NULL,
SME11,
SME21,
SME31,
HOM,
DOC,
CVN,
MTM,
CCD,
BAL,
MVR,
CVF,
ERS,
STA,
2023-04-13 11:51:03 +08:00
//
SPS,
WSZ,
_WT,
GLM,
FWO,
2023-04-13 11:51:03 +08:00
};
2023-04-13 11:51:03 +08:00
private HwAlignerGuideConnection _connection;
2023-04-13 11:51:03 +08:00
private readonly bool _activeMonitorStatus;
2023-04-13 11:51:03 +08:00
private readonly R_TRIG _trigCommunicationError = new();
private readonly R_TRIG _trigRetryConnect = new();
private bool _bIsDisconnect = false;
2023-04-13 11:51:03 +08:00
private uint _iCurrentOper = 0xff;
2023-04-13 11:51:03 +08:00
private readonly LinkedList<HandlerBase> _lstHandler = new();
2023-04-13 11:51:03 +08:00
private readonly object _locker = new();
2023-04-13 11:51:03 +08:00
#endregion
2023-04-13 11:51:03 +08:00
#region Constructors
2023-04-13 11:51:03 +08:00
/// <summary>
/// 构造上银巡边器对象实例。
/// </summary>
/// <param name="module">所属模组名称。</param>
/// <param name="scRoot">系统配置定义了当前巡边器相关配置的节点。</param>
/// <param name="name">当前巡边器名称。</param>
2023-04-13 11:51:03 +08:00
public HwAlignerGuide(string module, string scRoot, string name) : base(module, name, name, name)
{
ScBasePath = scRoot;
2023-04-13 11:51:03 +08:00
_activeMonitorStatus = true;
}
#endregion
2023-04-13 11:51:03 +08:00
#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
2023-04-13 11:51:03 +08:00
{
lock (_locker)
{
return _lstHandler.Count > 0 || _iCurrentOper != (uint)CommandEnum.NULL;
}
2023-04-13 11:51:03 +08:00
}
}
2023-04-13 11:51:03 +08:00
#endregion
2023-04-13 11:51:03 +08:00
#region Private Methods
private void InitData()
2023-04-13 11:51:03 +08:00
{
DATA.Subscribe($"{Module}.{Name}.HaveWafer", () => HaveWafer);
2023-04-13 11:51:03 +08:00
}
private void InitOp()
2023-04-13 11:51:03 +08:00
{
//参数保存
OP.Subscribe($"{Module}.{Name}.HwSaveParameters", (_, _) =>
2023-04-13 11:51:03 +08:00
{
Set("SPS");
2023-04-13 11:51:03 +08:00
return true;
});
//读取/设定晶圆尺寸
OP.Subscribe($"{Module}.{Name}.HwWaferSize", (_, param) =>
2023-04-13 11:51:03 +08:00
{
Set("WSZ" + " " + param[0]);
2023-04-13 11:51:03 +08:00
return true;
});
//晶圆种类
OP.Subscribe($"{Module}.{Name}.HwWaferType", (_, param) =>
2023-04-13 11:51:03 +08:00
{
Set("_WT" + " " + param[0]);
2023-04-13 11:51:03 +08:00
return true;
});
//寻边材质
OP.Subscribe($"{Module}.{Name}.HwWaferMaterial", (cmd, param) =>
{
Set("GLM" + " " + param[0]);
2023-04-13 11:51:03 +08:00
return true;
});
//晶圆方向
OP.Subscribe($"{Module}.{Name}.HwWaferOrientation", (cmd, param) =>
{
Set("FWO" + " " + param[0]);
2023-04-13 11:51:03 +08:00
return true;
});
//------------------------------------------------------------
2023-04-13 11:51:03 +08:00
//原点复归
OP.Subscribe($"{Module}.{Name}.HwHOM", (_, _) => MsgHome());
2023-04-13 11:51:03 +08:00
//晶圆确认
OP.Subscribe($"{Module}.{Name}.HwDOC", (_, _) => CheckWaferLoad());
2023-04-13 11:51:03 +08:00
//开启真空
OP.Subscribe($"{Module}.{Name}.HwCVN", (_, _) => OpenVacuum());
2023-04-13 11:51:03 +08:00
//寻边补正
OP.Subscribe($"{Module}.{Name}.HwBAL", (_, _) => MsgAliger());
2023-04-13 11:51:03 +08:00
//关闭真空
OP.Subscribe($"{Module}.{Name}.HwCVF", (_, _) => CloseVacuum());
2023-04-13 11:51:03 +08:00
//移至测量中心点
OP.Subscribe($"{Module}.{Name}.HwMTM", (_, _) => MoveToRobotPutPlace());
2023-04-13 11:51:03 +08:00
//清除报警
OP.Subscribe($"{Module}.{Name}.HwERS", (_, _) => ClearError());
2023-04-13 11:51:03 +08:00
//马达激磁
OP.Subscribe($"{Module}.{Name}.HwSME", (_, _) =>
2023-04-13 11:51:03 +08:00
{
InitMachine();
2023-04-13 11:51:03 +08:00
return true;
});
2023-04-13 11:51:03 +08:00
//相对位移
OP.Subscribe($"{Module}.{Name}.HwMVR", (cmd, param) =>
{
Set("MVR");
2023-04-13 11:51:03 +08:00
return true;
});
//
OP.Subscribe($"{Module}.{Name}.HwAbort", (cmd, param) =>
{
Abort();
return true;
});
}
2023-04-13 11:51:03 +08:00
private bool OnTimer()
{
try
{
2023-04-13 11:51:03 +08:00
_connection.MonitorTimeout();
//若断,重连
if ((!_connection.IsConnected) || _connection.IsCommunicationError || _bIsDisconnect)
{
_trigRetryConnect.CLK = _bIsDisconnect;
//重连机制要改timeout之后要是用心跳方式探测重连
_trigRetryConnect.CLK = _bIsDisconnect;
2023-04-13 11:51:03 +08:00
if (_connection.Connect())
{
_bIsDisconnect = false;
2023-04-13 11:51:03 +08:00
//
if (_trigRetryConnect.Q)
{
EV.PostInfoLog(Module, $"{Module}.{Name} connected");
LOG.Write($"{Module}.{Name} connected");
}
2023-04-13 11:51:03 +08:00
}
else
{
if (_trigRetryConnect.Q)
{
EV.PostInfoLog(Module,
$"Trying to connect {Module}.{Name} with address: {_connection.Address}");
2023-04-13 11:51:03 +08:00
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)
2023-04-13 11:51:03 +08:00
{
//Query();
}
if (_lstHandler.Count > 0)
{
handler = _lstHandler.First.Value;
_lstHandler.RemoveFirst();
}
}
if (handler != null)
{
_connection.Execute(handler);
2023-04-13 11:51:03 +08:00
}
}
2023-04-13 11:51:03 +08:00
//
return true;
}
catch (Exception ex)
{
LOG.Write(ex);
}
return true;
}
internal void NoteError()
{
}
protected override void HandleMonitor()
2023-04-13 11:51:03 +08:00
{
try
{
_trigCommunicationError.CLK = _connection.IsCommunicationError;
if (_trigCommunicationError.Q)
{
EV.PostAlarmLog(Module,
$"{Module}.{Name} communication error, {_connection.LastCommunicationError}");
2023-04-13 11:51:03 +08:00
}
}
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));
}
}
2023-04-13 11:51:03 +08:00
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,"");
2023-04-13 11:51:03 +08:00
_trigCommunicationError.RST = true;
_trigRetryConnect.RST = true;
_iCurrentOper = (uint)CommandEnum.NULL;
lock (_locker)
_lstHandler.Clear();
}
public void SetCurrentOper()
{
_iCurrentOper = (uint)CommandEnum.CCD;
2023-04-13 11:51:03 +08:00
}
internal bool ParseData(string name, byte[] buffer, out bool bResult)
2023-04-13 11:51:03 +08:00
{
bResult = true;
var sAnswer = Encoding.ASCII.GetString(buffer);
2023-04-13 11:51:03 +08:00
if (sAnswer.Contains("END"))
{
_iCurrentOper = (uint)CommandEnum.NULL;
return true;
}
if (sAnswer.Contains("ERR"))
{
lock (_locker)
2023-04-13 11:51:03 +08:00
{
_lstHandler.Clear();
2023-04-13 11:51:03 +08:00
}
_iCurrentOper = (uint)CommandEnum.NULL;
bResult = false;
return true; //Handled
}
2023-04-13 11:51:03 +08:00
return false;
}
2023-04-13 11:51:03 +08:00
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 = (uint)CommandEnum.NULL;
2023-04-13 11:51:03 +08:00
return true;
}
if (sAnswer.Contains("ERR"))
2023-04-13 11:51:03 +08:00
{
lock (_locker)
{
_lstHandler.Clear();
}
_iCurrentOper = (uint)CommandEnum.NULL;
bResult = false;
return false; //Handle
2023-04-13 11:51:03 +08:00
}
return false;
2023-04-13 11:51:03 +08:00
}
}
#endregion
2023-04-13 11:51:03 +08:00
}