SicMultiplate/SicRT/Equipments/Systems/EquipmentManager.cs

1482 lines
49 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 Aitex.Core.Common;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Fsm;
using Aitex.Core.RT.Routine;
using Aitex.Core.Utilities;
using MECF.Framework.Common.Fsm;
using SicRT.Instances;
using SicRT.Modules;
using System.Linq;
using System.Threading.Tasks;
using Aitex.Core.RT.Device.Unit;
using Aitex.Core.RT.SCCore;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.UPS;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Temps.AE;
using Aitex.Core.RT.Device.Devices;
using SicModules.Aligners;
using SicModules.Buffers;
using SicModules.Cassettes;
using SicModules.EFEMs;
using SicModules.LLs;
using SicModules.PMs;
using SicModules.TMs;
using SicModules.UnLoads;
using System.Diagnostics;
using MECF.Framework.RT.EquipmentLibrary.Devices;
namespace SicRT.Equipments.Systems
{
public enum RtState
{
Init,
Initializing,
Idle,
Transfer,
AutoRunning,
AutoIdle,
Cycle,
PlatformCycle,
ReturnAllWafer,
Error,
ShutDown = 999
}
public class EquipmentManager : FsmDevice
{
public enum MSG
{
HOME,
RESET,
ABORT,
ERROR,
MoveWafer,
ReturnAllWafer,
PlatformCycle,
HomeUnit,
PauseAuto,
ResumeAuto,
Stop,
StopPlatformCycle,
StartCycle,
SetAutoMode,
SetManualMode,
CreateJob,
PauseJob,
ResumeJob,
StartJob,
StopJob,
AbortJob,
JobDone,
FAJobCommand,
SetOnline,
SetOffline,
ModuleError,
ShutDown = 999,
}
public Dictionary<ModuleName, ModuleFsmDevice> Modules { get; set; }
public bool IsAutoMode
{
get
{
return FsmState == (int)RtState.AutoRunning;
}
}
public bool IsInit
{
get { return FsmState == (int)RtState.Init; }
}
public bool IsOnline
{
get;
set;
}
public bool IsIdle
{
get { return FsmState == (int)RtState.Idle; }
}
public bool IsAlarm
{
get { return FsmState == (int)RtState.Error; }
}
public bool IsAutoIdle
{
get => FsmState == (int)RtState.AutoIdle;
}
public bool IsRunning
{
get
{
return FsmState == (int)RtState.Initializing
|| FsmState == (int)RtState.Transfer
|| FsmState == (int)RtState.Cycle
|| FsmState == (int)RtState.AutoRunning;
}
}
private ManualTransfer _manualTransfer;
private AutoTransfer _auto = null;
private HomeAll _homeAll;
private ReturnAllWafer _returnAll;
//TODO 更名为_lstModuleNames
private List<string> _modules = new List<string>();
//readonly IEnumerable<PropertyInfo> IEntityModules;
private ITAUPS _upsPM1A = null;
private ITAUPS _upsPM1B = null;
private ITAUPS _upsPM2A = null;
private ITAUPS _upsPM2B = null;
private IoUPS _pm1UPS = null;
private IoUPS _pm2UPS = null;
private IoInterLock _pm1InterLock = null;
private IoInterLock _pm2InterLock = null;
private SicModules.Devices.IoInterLock _tmInterLock = null;
private IoSlitValve _pm1SlitValve = null;
private IoSlitValve _pm2SlitValve = null;
private PeriodicJob _thread;
private IoTC _tc = null;
/// <summary>
/// 主三色灯对象。
/// 主三色灯判断方式参考<see cref="GetMainSignalTower"/>方法。
/// </summary>
private IoSignalTower _mainSignalTower;
public EquipmentManager()
{
Module = "System";
Name = "System";
Modules = new Dictionary<ModuleName, ModuleFsmDevice>();
}
public override bool Initialize()
{
InitModules();
GetMainSignalTower();
EnumLoop<RtState>.ForEach((item) =>
{
MapState((int)item, item.ToString());
});
EnumLoop<MSG>.ForEach((item) =>
{
MapMessage((int)item, item.ToString());
});
EnableFsm(100, RtState.Init);
BuildTransitionTable();
SubscribeDataVariable();
SubscribeOperation();
//InitSetPSUY();
Singleton<EventManager>.Instance.OnAlarmEvent += Instance_OnAlarmEvent;
_manualTransfer = new ManualTransfer();
_homeAll = new HomeAll();
_auto = new AutoTransfer();
_returnAll = new ReturnAllWafer();
SC.RegisterValueChangedCallback("TM.ProcessPressure", SetTansferPressure1);
SC.RegisterValueChangedCallback("TM.VacuumPressureBaseOffset", SetTansferPressure2);
return true;
}
private void SetTansferPressure1(object value)
{
try
{
double.TryParse(value.ToString(), out double dbValue);
double offset = SC.GetValue<double>("TM.VacuumPressureBaseOffset");
double basePressure = offset + dbValue;
SC.SetItemValue("TM.PressureBalance.BalancePressure", dbValue);
SC.SetItemValue("TM.VacuumPressureBase", basePressure);
SC.SetItemValue("TM.Purge.VentBasePressure", dbValue);
SC.SetItemValue("PM.VacuumPressureBase", basePressure);
SC.SetItemValue("PM.PM1.ProcessIdle.FinalPressure", dbValue);
SC.SetItemValue("PM.PM1.PreProcess.ChamberPressure", dbValue);
SC.SetItemValue("PM.PM2.ProcessIdle.FinalPressure", dbValue);
SC.SetItemValue("PM.PM2.PreProcess.ChamberPressure", dbValue);
SC.SetItemValue("LoadLock.VacuumPressureBase", basePressure);
SC.SetItemValue("LoadLock.Purge.VentBasePressure", dbValue);
SC.SetItemValue("UnLoad.VacuumPressureBase", basePressure);
SC.SetItemValue("UnLoad.Purge.VentBasePressure", dbValue);
}
catch (Exception ex)
{
EV.PostWarningLog("System", ex.Message);
}
}
private void SetTansferPressure2(object value)
{
try
{
double dbValue = SC.GetValue<double>("TM.ProcessPressure");
double.TryParse(value.ToString(), out double offset);
double basePressure = offset + dbValue;
SC.SetItemValue("TM.PressureBalance.BalancePressure", dbValue);
SC.SetItemValue("TM.VacuumPressureBase", basePressure);
SC.SetItemValue("TM.Purge.VentBasePressure", dbValue);
SC.SetItemValue("PM.VacuumPressureBase", basePressure);
SC.SetItemValue("PM.PM1.ProcessIdle.FinalPressure", dbValue);
SC.SetItemValue("PM.PM1.PreProcess.ChamberPressure", dbValue);
SC.SetItemValue("PM.PM2.ProcessIdle.FinalPressure", dbValue);
SC.SetItemValue("PM.PM2.PreProcess.ChamberPressure", dbValue);
SC.SetItemValue("LoadLock.VacuumPressureBase", basePressure);
SC.SetItemValue("LoadLock.Purge.VentBasePressure", dbValue);
SC.SetItemValue("UnLoad.VacuumPressureBase", basePressure);
SC.SetItemValue("UnLoad.Purge.VentBasePressure", dbValue);
}
catch (Exception ex)
{
EV.PostWarningLog("System", ex.Message);
}
}
/// <summary>
/// 创建指定的Module的实例。
/// </summary>
/// <typeparam name="T">Module类型。</typeparam>
/// <param name="name">Module名称。</param>
/// <param name="totalSlots">Module包含的Wafer槽位总数。</param>
private void GenModule<T>(ModuleName name, int totalSlots = 1)
where T : ModuleFsmDevice
{
ModuleFsmDevice module;
if (totalSlots > 1)
module = (ModuleFsmDevice)Activator.CreateInstance(typeof(T), name, totalSlots);
else
module = (ModuleFsmDevice)Activator.CreateInstance(typeof(T), name);
Debug.Assert(module != null, $"Failed to create instance of module {name}");
// 创建Module实例失败
if (module == null)
{
LOG.Error($"Failed to create instance of module {name}");
return;
}
// 如果Module在系统配置中配置为“未安装”则不要注册Alarm事件
/*if (!module.IsInstalled)
{
LOG.Warning($"{name} is configured as NotInstalled");
return;
}*/
module.OnEnterError += OnModuleError;
Modules[name] = module;
}
private void InitModules()
{
GenModule<TMModule>(ModuleName.TM);
GenModule<LoadLockModule>(ModuleName.LoadLock);
GenModule<UnLoadModule>(ModuleName.UnLoad);
GenModule<BufferModule>(ModuleName.Buffer);
GenModule<AlignerModule>(ModuleName.Aligner);
GenModule<WaferRobotModule>(ModuleName.WaferRobot);
GenModule<TrayRobotModule>(ModuleName.TrayRobot);
GenModule<EFEMModule>(ModuleName.EFEM);
GenModule<CassetteModule>(ModuleName.CassAL, 25);
GenModule<CassetteModule>(ModuleName.CassAR, 25);
GenModule<CassetteModule>(ModuleName.CassBL, 8);
GenModule<PMModule>(ModuleName.PM1);
GenModule<PMModule>(ModuleName.PM2);
_modules = new List<string>() { "System" };
foreach (var modulesKey in Modules.Keys)
_modules.Add(modulesKey.ToString());
foreach (var module in Modules.Values)
{
module.Initialize();
if (!module.IsInstalled)
{
// 如果Module设置为NotInstalled则禁用其下的所有Device。
DEVICE.GetAllDevice().ForEach(x =>
{
if (x.Module == module.Module)
x.IsEnabled = false;
});
}
}
_pm1SlitValve = DEVICE.GetDevice<IoSlitValve>("TM.PM1Door");
_pm2SlitValve = DEVICE.GetDevice<IoSlitValve>("TM.PM2Door");
_pm1InterLock = DEVICE.GetDevice<IoInterLock>("PM1.PMInterLock");
_pm2InterLock = DEVICE.GetDevice<IoInterLock>("PM2.PMInterLock");
_tmInterLock = DEVICE.GetDevice<SicModules.Devices.IoInterLock>("TM.IoInterLock");
_upsPM1A = DEVICE.GetDevice<ITAUPS>("PM1.ITAUPSA");
_upsPM1B = DEVICE.GetDevice<ITAUPS>("PM1.ITAUPSB");
_pm1UPS = DEVICE.GetDevice<IoUPS>("PM1.UPS");
_upsPM2A = DEVICE.GetDevice<ITAUPS>("PM2.ITAUPSA");
_upsPM2B = DEVICE.GetDevice<ITAUPS>("PM2.ITAUPSB");
_pm2UPS = DEVICE.GetDevice<IoUPS>("PM2.UPS");
_tc = DEVICE.GetDevice<IoTC>("PM1.TC1");
_thread = new PeriodicJob(200, OnTimer, "PmSlitDoor", false, true);
Task.Delay(15000).ContinueWith((a) => _thread.Start());
//IEntityModules = this.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)
// .Where(t => t.PropertyType.GetInterfaces().Contains(typeof(IEntity)) && t.PropertyType.GetInterfaces().Contains(typeof(IModuleEntity)));
}
private void BuildTransitionTable()
{
//ShutDown
Transition(RtState.Init, MSG.ShutDown, FsmStartShutDown, RtState.ShutDown);
Transition(RtState.Idle, MSG.ShutDown, FsmStartShutDown, RtState.ShutDown);
Transition(RtState.AutoIdle, MSG.ShutDown, FsmStartShutDown, RtState.ShutDown);
EnterExitTransition<RtState, FSM_MSG>(RtState.ShutDown, FsmShutDown, null, null);
//Init sequence
Transition(RtState.Init, MSG.HOME, FsmStartHome, RtState.Initializing);
Transition(RtState.Idle, MSG.HOME, FsmStartHome, RtState.Initializing);
Transition(RtState.Error, MSG.HOME, FsmStartHome, RtState.Initializing);
// EnterExitTransition<RtState, FSM_MSG>(RtState.Initializing, fStartInit, FSM_MSG.NONE, null);
Transition(RtState.Initializing, FSM_MSG.TIMER, FsmMonitorHome, RtState.Idle);
Transition(RtState.Initializing, MSG.ERROR, fError, RtState.Error);
Transition(RtState.Initializing, MSG.ABORT, FsmAbort, RtState.Init);
//Online
Transition(RtState.Idle, MSG.SetOnline, FsmStartSetOnline, RtState.Idle);
Transition(RtState.Idle, MSG.SetOffline, FsmStartSetOffline, RtState.Idle);
//Reset
AnyStateTransition(MSG.RESET, fStartReset, RtState.Idle);
AnyStateTransition(MSG.ERROR, fError, RtState.Error);
AnyStateTransition((int)FSM_MSG.ALARM, fError, (int)RtState.Error);
//Auto/manual sequence
Transition(RtState.Idle, MSG.SetAutoMode, fStartAutoTransfer, RtState.AutoIdle);
Transition(RtState.AutoRunning, FSM_MSG.TIMER, fAutoTransfer, RtState.AutoRunning);
Transition(RtState.AutoRunning, MSG.ABORT, fAbortAutoTransfer, RtState.AutoIdle);
Transition(RtState.AutoRunning, MSG.JobDone, null, RtState.AutoIdle);
Transition(RtState.AutoRunning, MSG.FAJobCommand, FsmFAJobCommand, RtState.AutoRunning);
Transition(RtState.AutoRunning, MSG.CreateJob, FsmCreateJob, RtState.AutoRunning);
Transition(RtState.AutoRunning, MSG.StartJob, FsmStartJob, RtState.AutoRunning);
Transition(RtState.AutoRunning, MSG.PauseJob, FsmPauseJob, RtState.AutoRunning);
Transition(RtState.AutoRunning, MSG.ResumeJob, FsmResumeJob, RtState.AutoRunning);
Transition(RtState.AutoRunning, MSG.StopJob, FsmStopJob, RtState.AutoRunning);
Transition(RtState.AutoRunning, MSG.AbortJob, FsmAbortJob, RtState.AutoRunning);
Transition(RtState.AutoIdle, FSM_MSG.TIMER, FsmMonitorAutoIdle, RtState.AutoIdle);
Transition(RtState.AutoIdle, MSG.SetManualMode, FsmStartSetManualMode, RtState.Idle);
Transition(RtState.AutoIdle, MSG.FAJobCommand, FsmFAJobCommand, RtState.AutoIdle);
Transition(RtState.AutoIdle, MSG.CreateJob, FsmCreateJob, RtState.AutoIdle);
Transition(RtState.AutoIdle, MSG.StartJob, FsmStartJob, RtState.AutoRunning);
Transition(RtState.AutoIdle, MSG.ABORT, FsmAbort, RtState.AutoIdle);
Transition(RtState.AutoIdle, MSG.AbortJob, FsmAbortJob, RtState.AutoIdle);
EnterExitTransition<RtState, FSM_MSG>(RtState.AutoRunning, null, FSM_MSG.NONE, fExitAutoTransfer);
//return all wafer
Transition(RtState.Idle, MSG.ReturnAllWafer, FsmStartReturnAllWafer, RtState.ReturnAllWafer);
Transition(RtState.ReturnAllWafer, FSM_MSG.TIMER, FsmMonitorReturnAllWafer, RtState.Idle);
Transition(RtState.ReturnAllWafer, MSG.ABORT, FsmAbortReturnAllWafer, RtState.Idle);
//Transfer sequence
Transition(RtState.Idle, MSG.MoveWafer, fStartTransfer, RtState.Transfer);
Transition(RtState.Transfer, FSM_MSG.TIMER, fTransfer, RtState.Idle);
EnterExitTransition<RtState, FSM_MSG>(RtState.Transfer, null, FSM_MSG.NONE, fExitTransfer);
Transition(RtState.Transfer, MSG.ABORT, FsmAbort, RtState.Idle);
}
void SubscribeDataVariable()
{
DATA.Subscribe("Rt.Status", () => StringFsmStatus);
DATA.Subscribe("System.IsOnline", () => IsOnline);
DATA.Subscribe("System.IsIdle", () => IsIdle || IsInit);
DATA.Subscribe("System.IsAlarm", () => IsAlarm);
DATA.Subscribe("System.IsBusy", () => IsRunning);//System.IsBusy=>IsRunning绑定相同的值不同的地方用
DATA.Subscribe("System.IsAutoIdle", () => IsAutoIdle);
DATA.Subscribe("System.IsAutoRunning", () => IsRunning);//System.IsAutoRunning=>IsRunning绑定相同的值不同的地方用
DATA.Subscribe("System.Modules", () => _modules);
DATA.Subscribe("System.SignalTowerData", () => _mainSignalTower?.DeviceData);
}
void SubscribeOperation()
{
OP.Subscribe("CreateWafer", InvokeCreateWafer);
OP.Subscribe("DeleteWafer", InvokeDeleteWafer);
OP.Subscribe("ReturnWafer", InvokeReturnWafer);
OP.Subscribe("DeleteTray", InvokeDeleteTray);
OP.Subscribe("AlterWaferInfo", InvokeAlterWaferInfo);
OP.Subscribe("UpdatTrayBelongTo", (string cmd, object[] args) => { return true; });//注册空的方法,否则调用时日志有错误输出
OP.Subscribe("System.ReturnAllWafer", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.ReturnAllWafer);
});
OP.Subscribe("System.MoveWafer", (string cmd, object[] args) =>
{
if (!Enum.TryParse((string)args[0], out ModuleName source))
{
EV.PostWarningLog(Name, $"Parameter source {(string)args[0]} not valid");
return false;
}
if (!Enum.TryParse((string)args[2], out ModuleName destination))
{
EV.PostWarningLog(Name, $"Parameter destination {(string)args[1]} not valid");
return false;
}
if (args.Length > 9 )
{
if ((bool)args[9])
{
WaferManager.Instance.WaferMoved(source, (int)args[1], destination, (int)args[3]);
return true;
}
if ((bool)args[10])
{
WaferManager.Instance.TrayMoved(source, (int)args[1], destination, (int)args[3]);
return true;
}
}
if (args.Length >= 8)
{
return CheckToPostMessage((int)MSG.MoveWafer, source, (int)args[1], destination, (int)args[3],
(bool)args[4], (int)args[5], (bool)args[6], (int)args[7]);
}
if (args.Length == 5)
{
return CheckToPostMessage((int)MSG.MoveWafer, source, (int)args[1], destination, (int)args[3], (bool)args[4]);
}
return CheckToPostMessage((int)MSG.MoveWafer, source, (int)args[1], destination, (int)args[3]);
});
OP.Subscribe("System.HomeAll", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.HOME);
});
OP.Subscribe("System.Abort", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.ABORT);
});
OP.Subscribe("System.Reset", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.RESET);
});
OP.Subscribe("System.SetAutoMode", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.SetAutoMode);
});
OP.Subscribe("System.SetManualMode", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.SetManualMode);
});
OP.Subscribe("System.CreateJob", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.CreateJob, args[0]);
});
OP.Subscribe("System.StartJob", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.StartJob, args[0]);
});
OP.Subscribe("System.PauseJob", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.PauseJob, args[0]);
});
OP.Subscribe("System.ResumeJob", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.ResumeJob, args[0]);
});
OP.Subscribe("System.StopJob", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.StopJob, args[0]);
});
OP.Subscribe("System.AbortJob", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.AbortJob, args[0]);
});
OP.Subscribe("System.SetOnline", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.SetOnline);
});
OP.Subscribe("System.SetOffline", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.SetOffline);
});
OP.Subscribe("System.ShutDown", (string cmd, object[] args) =>
{
return CheckToPostMessage((int)MSG.ShutDown, null);
});
//OP.Subscribe("System.StartAutoRun", (string cmd, object[] args) =>
//{
// return CheckToPostMessage((int)MSG.StartJob, args[0]);
//});
#region Recipe Editor Lock Password Management
const string SC_PATH_REQ_RESET_PASS = "System.Recipe.ResetEditorPassword";
const string SC_PATH_PASSWORD = "System.Recipe.EditorPassword";
OP.Subscribe("System.SetNewRecipeEditorPassword", (string cmd, object[] args) =>
{
if (args.Length == 2 && args[0] is string oldPass
&& args[1] is string newPass)
{
var oldPassInSc = SC.GetStringValue(SC_PATH_PASSWORD);
if (oldPass != oldPassInSc)
{
EV.PostWarningLog(Module, "Incorrect old password");
return false;
}
SC.SetItemValue(SC_PATH_REQ_RESET_PASS, false);
SC.SetItemValue(SC_PATH_PASSWORD, newPass);
EV.PostInfoLog(Module, "Recipe Editor Password has been changed");
return true;
}
else
{
EV.PostWarningLog(Module, "Incorrect args of setting new Recipe Editor password");
return false;
}
});
// 程序启动时禁用复位密码选项,写在这里方便移植
SC.SetItemValue(SC_PATH_REQ_RESET_PASS, false);
#endregion
}
private void InitSetPSUY()
{
Task.Delay(2000).ContinueWith(x=> _tc.SetPCPSUY());
}
private void Instance_OnAlarmEvent(EventItem obj)
{
FSM_MSG msg;
if (obj.Level == EventLevel.Warning)
msg = FSM_MSG.WARNING;
else if (obj.Level == EventLevel.Alarm)
{
msg = FSM_MSG.ALARM;
if(obj.Source == null)
{
return;
}
// 如果设备产生报警则向设备所在的Module发送状态机信号切换到Error状态。
if (Modules.ContainsKey(ModuleHelper.Converter(obj.Source)))
{
Modules[ModuleHelper.Converter(obj.Source)]?.PostMsg(msg, obj.Id, obj.Description);
}
// 产生新的报警时重新启用Buzzer
_mainSignalTower?.SwitchOffBuzzer(false);
}
}
/// <summary>
/// 获取主三色灯对象。
/// </summary>
/// <remarks>
/// 系统设备配置中配置多个三色灯对象,但软件仅控制唯一个三色灯。
/// <br/>
/// 该三色灯定义为主三色灯,其余三色灯对象将被禁用,其工作状态自动跟随主三色灯。
/// <br/>
/// 通常情况下使用PM1的三色灯作为主三色灯。
/// <br/>
/// 如果PM1被卸载则系统自动使用PM2控制的三色灯依此类推。
/// </remarks>
/// <returns></returns>
private void GetMainSignalTower()
{
// 系统配置是否PM控制三色灯
var isPmHostSt = SC.GetValue("System.IsPMHostSignalTower", true);
// 获取三色灯列表,并按名称排序
var sts = DEVICE.GetAllDevice()
.Where(x => x is IoSignalTower)
.OrderBy(x => x.Module)
.Cast<IoSignalTower>()
.ToList();
// 禁用所有三色灯,待确定完主灯后再使能主灯。
foreach (var st in sts)
{
st.IsEnabled = false;
}
// 判断三色灯主灯
if (isPmHostSt)
{
var pmAttachedSts =
sts.Where(x => x.Module.StartsWith("PM"))
.OrderBy(x => x.Module)
.ToList();
if (pmAttachedSts.Any())
{
foreach (var st in pmAttachedSts)
{
if (st != null && Modules.TryGetValue(ModuleHelper.Converter(st.Module), out var module))
{
if (module.IsInstalled)
{
// 找到第一个有效的PM获取其三色灯对象。
_mainSignalTower = st;
break;
}
}
}
}
}
// 如果没找到PM三色灯或系统配置指定使用TM三色灯
// 获取隶属于TM的三色灯对象
_mainSignalTower ??= sts.FirstOrDefault(x => x.Module.StartsWith("TM"));
// 使能三色灯
if (_mainSignalTower != null)
{
LOG.Write($"SignalTower attaches to {_mainSignalTower.Module}");
_mainSignalTower.IsEnabled = true;
}
else
{
LOG.Error("SignalTower object not found");
}
}
#region Init
private bool FsmStartHome(object[] objs)
{
return _homeAll.Start() == Result.RUN;
}
private bool FsmMonitorHome(object[] objs)
{
Result ret = _homeAll.Monitor();
if (ret == Result.DONE)
{
_homeAll.Clear();
return true;
}
if (ret == Result.FAIL)
{
_homeAll.Clear();
PostMsg(MSG.ERROR);
}
return false;
}
private bool fError(object[] objs)
{
IsOnline = false;
if (FsmState == (int)RtState.Transfer)
{
_manualTransfer.Clear();
}
return true;
}
#endregion
#region AutoTransfer
private bool FsmMonitorAutoIdle(object[] param)
{
//fMonitorFAJob(param);
Result ret = _auto.Monitor();
//if (!_auto.CheckAllJobDone())
//{
// return false;
//}
return ret == Result.DONE;
}
private bool FsmStartSetManualMode(object[] objs)
{
if (_auto.HasJobRunning)
{
EV.PostWarningLog("System", "Can not change to manual mode, abort running job first");
return false;
}
return true;
}
private bool fStartAutoTransfer(object[] objs)
{
Result ret = _auto.Start(objs);
return ret == Result.RUN;
}
private bool fAutoTransfer(object[] objs)
{
Result ret = _auto.Monitor();
if (_auto.CheckAllJobDone())
{
if (!CheckToPostMessage((int)MSG.JobDone))
return false;
}
return ret == Result.DONE;
}
private bool fExitAutoTransfer(object[] objs)
{
_auto.Clear();
return true;
}
private bool fAbortAutoTransfer(object[] objs)
{
if (FsmState == (int)RtState.Transfer)
{
_manualTransfer.Clear();
}
if (FsmState == (int)RtState.AutoRunning)
{
_auto.Clear();
}
foreach (var modulesValue in Modules.Values)
{
if (!modulesValue.Module.Contains("PM"))
{
modulesValue.PostMsg(MSG.ABORT);
}
}
return true;
}
#endregion
#region cycle
private bool FsmAbortCycle(object[] param)
{
return true;
}
private bool FsmMonitorCycle(object[] param)
{
return _auto.Monitor() == Result.DONE;
}
private bool FsmStartCycle(object[] param)
{
return _auto.Start() == Result.RUN;
}
#endregion
#region return all wafer
private bool FsmAbortReturnAllWafer(object[] param)
{
//_returnAll.Clear();
return true;
}
private bool FsmMonitorReturnAllWafer(object[] param)
{
return _returnAll.Monitor() == Result.DONE;
}
private bool FsmStartReturnAllWafer(object[] param)
{
return _returnAll.Start() == Result.RUN;
}
#endregion
#region Transfer
private bool fStartTransfer(object[] objs)
{
Result ret = _manualTransfer.Start(objs);
if (ret == Result.FAIL || ret == Result.DONE)
return false;
return ret == Result.RUN;
}
private bool fTransfer(object[] objs)
{
Result ret = _manualTransfer.Monitor(objs);
if (ret == Result.FAIL)
{
PostMsg(MSG.ERROR);
return false;
}
return ret == Result.DONE;
}
private bool fExitTransfer(object[] objs)
{
_manualTransfer.Clear();
return true;
}
private bool fAbortTransfer(object[] objs)
{
return true;
}
#endregion
#region reset
private bool fStartReset(object[] objs)
{
EV.ClearAlarmEvent();
if (FsmState == (int)RtState.AutoRunning)
{
_auto.ResetTask();
}
Singleton<DeviceEntity>.Instance.PostMsg(DeviceEntity.MSG.RESET);
foreach (var modulesValue in Modules.Values)
{
modulesValue.PostMsg(MSG.RESET);
}
IoProviderManager.Instance.Reset();
if (FsmState == (int)RtState.Error)
return true;
return false;
}
#endregion
private bool FsmFAJobCommand(object[] param)
{
switch ((string)param[0])
{
case "CreateProcessJob":
//_auto.CreateProcessJob((string)param[1], (string)param[2], (List<int>)param[3], (bool)param[4]);
break;
case "CreateControlJob":
//_auto.CreateControlJob((string)param[1], (string)param[2], (List<string>)param[3], (bool)param[4]);
CheckToPostMessage((int)MSG.StartJob, (string)param[1]);
break;
}
return true;
}
private bool FsmCreateJob(object[] param)
{
_auto.CreateJob((Dictionary<string, object>)param[0]);
return true;
}
private bool FsmAbortJob(object[] param)
{
_auto.AbortJob((string)param[0]);
return true;
}
private bool FsmStopJob(object[] param)
{
_auto.StopJob((string)param[0]);
return true;
}
private bool FsmResumeJob(object[] param)
{
_auto.ResumeJob((string)param[0]);
return true;
}
private bool FsmPauseJob(object[] param)
{
_auto.PauseJob((string)param[0]);
return true;
}
private bool FsmStartJob(object[] param)
{
_auto.StartJob((string)param[0]);
return true;
}
private bool FsmAbort(object[] param)
{
if (FsmState == (int)RtState.Transfer)
{
_manualTransfer.Clear();
}
if (FsmState == (int)RtState.AutoRunning)
{
_auto.Clear();
}
foreach (var modulesValue in Modules.Values)
{
if (!modulesValue.Module.Contains("PM"))
{
modulesValue.PostMsg(MSG.ABORT);
}
}
return true;
}
private bool FsmStartSetOffline(object[] param)
{
IsOnline = false;
var tm = Modules[ModuleName.TM] as TMModule;
tm.InvokeOffline();
var ll = Modules[ModuleName.LoadLock] as LoadLockModule;
ll.InvokeOffline();
var buffer = Modules[ModuleName.Buffer] as BufferModule;
buffer.InvokeOffline();
var unLoad = Modules[ModuleName.UnLoad] as UnLoadModule;
unLoad.InvokeOffline();
var efem = Modules[ModuleName.EFEM] as EFEMModule;
efem.InvokeOffline();
var aligner = Modules[ModuleName.Aligner] as AlignerModule;
aligner.InvokeOffline();
if (SC.GetValue<bool>($"System.SetUp.IsPM1Installed"))
{
var pm1 = Modules[ModuleName.PM1] as PMModule;
pm1.InvokeOffline();
}
if (SC.GetValue<bool>($"System.SetUp.IsPM2Installed"))
{
var pm2 = Modules[ModuleName.PM2] as PMModule;
pm2.InvokeOffline();
}
var cassAL = Modules[ModuleName.CassAL] as CassetteModule;
cassAL.InvokeOffline();
var cassAR = Modules[ModuleName.CassAR] as CassetteModule;
cassAR.InvokeOffline();
var cassBL = Modules[ModuleName.CassBL] as CassetteModule;
cassBL.InvokeOffline();
var waferRobot = Modules[ModuleName.WaferRobot] as WaferRobotModule;
waferRobot.InvokeOffline();
var trayRobot = Modules[ModuleName.TrayRobot] as TrayRobotModule;
trayRobot.InvokeOffline();
return true;
}
private bool FsmStartSetOnline(object[] param)
{
IsOnline = true;
var tm = Modules[ModuleName.TM] as TMModule;
tm.InvokeOnline();
var ll = Modules[ModuleName.LoadLock] as LoadLockModule;
ll.InvokeOnline();
var buffer = Modules[ModuleName.Buffer] as BufferModule;
buffer.InvokeOnline();
var unLoad = Modules[ModuleName.UnLoad] as UnLoadModule;
unLoad.InvokeOnline();
var efem = Modules[ModuleName.EFEM] as EFEMModule;
efem.InvokeOnline();
var aligner = Modules[ModuleName.Aligner] as AlignerModule;
aligner.InvokeOnline();
if (SC.GetValue<bool>($"System.SetUp.IsPM1Installed"))
{
var pm1 = Modules[ModuleName.PM1] as PMModule;
pm1.InvokeOnline();
}
if (SC.GetValue<bool>($"System.SetUp.IsPM2Installed"))
{
var pm2 = Modules[ModuleName.PM2] as PMModule;
pm2.InvokeOnline();
}
var cassAL = Modules[ModuleName.CassAL] as CassetteModule;
cassAL.InvokeOnline();
var cassAR = Modules[ModuleName.CassAR] as CassetteModule;
cassAR.InvokeOnline();
var cassBL = Modules[ModuleName.CassBL] as CassetteModule;
cassBL.InvokeOnline();
var waferRobot = Modules[ModuleName.WaferRobot] as WaferRobotModule;
waferRobot.InvokeOnline();
var trayRobot = Modules[ModuleName.TrayRobot] as TrayRobotModule;
trayRobot.InvokeOnline();
return true;
}
#region cassette popup menu
private bool InvokeReturnWafer(string arg1, object[] args)
{
ModuleName target = ModuleHelper.Converter(args[0].ToString());
int slot = (int)args[1];
if (ModuleHelper.IsLoadPort(target))
{
EV.PostInfoLog("System", string.Format("Wafer already at LoadPort {0} {1}, return operation is not valid", target.ToString(), slot + 1));
return false;
}
if (!WaferManager.Instance.IsWaferSlotLocationValid(target, slot))
{
EV.PostWarningLog("System", string.Format("Invalid position{0}{1}", target.ToString(), slot.ToString()));
return false;
}
var wafer = WaferManager.Instance.GetWafer(target, slot);
if (wafer.IsWaferEmpty)
{
EV.PostInfoLog("System", string.Format("No wafer at {0} {1}, return operation is not valid", target.ToString(), slot + 1));
return false;
}
return CheckToPostMessage((int)MSG.MoveWafer,
target, slot,
(ModuleName)wafer.WaferOriginStation, wafer.WaferOriginSlot,
false, 0, false, 0);
}
private bool InvokeDeleteWafer(string arg1, object[] args)
{
ModuleName chamber = ModuleHelper.Converter(args[0].ToString());
int slot = (int)args[1];
if (chamber == ModuleName.TrayRobot || chamber == ModuleName.CassBL)
{
if (WaferManager.Instance.CheckHasTray(chamber, slot))
{
WaferManager.Instance.DeleteWafer(chamber, slot);
EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferDelete, chamber.ToString(), slot + 1);
}
else
{
EV.PostInfoLog("System", string.Format("No wafer at {0} {1}, delete not valid", chamber.ToString(), slot + 1));
}
}
else if (WaferManager.Instance.CheckHasWafer(chamber, slot))
{
if (chamber == ModuleName.TMRobot || chamber == ModuleName.LoadLock || chamber == ModuleName.UnLoad
|| chamber == ModuleName.Buffer || chamber == ModuleName.PM1 || chamber == ModuleName.PM2)
{
if (WaferManager.Instance.CheckHasTray(chamber, slot))
{
WaferManager.Instance.DeleteWaferOnly(chamber, slot);
}
else
{
WaferManager.Instance.DeleteWafer(chamber, slot);
}
}
else
{
WaferManager.Instance.DeleteWafer(chamber, slot);
}
}
else
{
EV.PostWarningLog("System", string.Format("Invalid position{0}{1}", chamber.ToString(), slot.ToString()));
return false;
}
return true;
}
private bool InvokeCreateWafer(string arg1, object[] args)
{
ModuleName chamber = ModuleHelper.Converter(args[0].ToString());
int slot = (int)args[1];
WaferStatus state = WaferStatus.Normal;
if (chamber == ModuleName.TrayRobot || chamber == ModuleName.CassBL)
{
if (WaferManager.Instance.IsWaferSlotLocationValid(chamber, slot))
{
if (WaferManager.Instance.CheckHasTray(chamber, slot))
{
EV.PostInfoLog("System", string.Format("{0} slot {1} already has tray.create wafer is not valid", chamber, slot));
}
else if (WaferManager.Instance.CreateWafer(chamber, slot, state) != null)
{
EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferCreate, chamber.ToString(), slot + 1, state.ToString());
}
}
else
{
EV.PostWarningLog("System", string.Format("Invalid position{0}{1}", chamber.ToString(), slot.ToString()));
return false;
}
}
else
{
if (WaferManager.Instance.IsWaferSlotLocationValid(chamber, slot))
{
if (WaferManager.Instance.CheckHasWafer(chamber, slot))
{
EV.PostInfoLog("System", string.Format("{0} slot {1} already has wafer.create wafer is not valid", chamber, slot));
}
else if (WaferManager.Instance.CreateWafer(chamber, slot, state) != null)
{
EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferCreate, chamber.ToString(), slot + 1, state.ToString());
}
}
else
{
EV.PostWarningLog("System", string.Format("Invalid position{0}{1}", chamber.ToString(), slot.ToString()));
return false;
}
}
return true;
}
private bool InvokeDeleteTray(string arg1, object[] args)
{
ModuleName chamber = ModuleHelper.Converter(args[0].ToString());
int slot = (int)args[1];
if (WaferManager.Instance.CheckHasTray(chamber, slot))
{
if (chamber == ModuleName.Buffer)
{
WaferManager.Instance.DeleteWafer(chamber, slot);
}
else if (WaferManager.Instance.CheckHasWafer(chamber, slot))
{
if(chamber == ModuleName.PM1 || chamber == ModuleName.PM2)
{
WaferManager.Instance.DeleteWafer(chamber, slot);
}
else
{
WaferManager.Instance.GetWafer(chamber, slot).TrayState = TrayStatus.Empty;
}
}
else
{
WaferManager.Instance.DeleteWafer(chamber, slot);
}
}
return true;
}
private bool InvokeAlterWaferInfo(string arg1, object[] args)
{
ModuleName chamber = ModuleHelper.Converter(args[0].ToString());
int slot = (int)args[1];
string recipeName = args[2].ToString();
int trayProcessCount = (int)args[3];
var wafer = WaferManager.Instance.GetWafer(chamber, slot);
if (WaferManager.Instance.CheckHasWafer(chamber, slot))
{
if(!String.IsNullOrEmpty(recipeName) && wafer != null && wafer.ProcessJob != null && wafer.ProcessJob.Sequence != null && wafer.ProcessState == WaferProcessStatus.Idle)
{
for (int i = 0; i < wafer.ProcessJob.Sequence.Steps.Count; i++)
{
if (!String.IsNullOrEmpty(wafer.ProcessJob.Sequence.Steps[i].RecipeName))
{
wafer.ProcessJob.Sequence.Steps[i].RecipeName = recipeName;
}
}
}
}
if (WaferManager.Instance.CheckHasTray(chamber, slot))
{
if (wafer != null)
{
wafer.TrayProcessCount = trayProcessCount;
}
}
return true;
}
#endregion
private void OnModuleError(object sender, string module)
{
if (FsmState == (int)RtState.AutoRunning)
{
ModuleName mod = ModuleHelper.Converter(module);
PostMsg(MSG.ModuleError, module);
}
}
#region ShutDown
private bool FsmStartShutDown(object[] objs)
{
var InBusyModuleNames = this.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)
.Where(t => t.PropertyType.GetInterfaces().Contains(typeof(IModuleEntity)) && ((IModuleEntity)t.GetValue(this, null)).IsBusy)
.Select(n => n.Name).ToArray();
if (InBusyModuleNames.Length > 0)
{
EV.PostWarningLog("System", $"Shut down fail , {string.Join(" , ", InBusyModuleNames)} is in busy");
return false;
}
Term();
EV.PostKickoutMessage("ShutDown");
return true;
}
private bool FsmShutDown(object[] objs)
{
Task.Delay(3000).ContinueWith(a =>
{
Environment.Exit(0);
});
return true;
}
protected void Term()
{
foreach (var modulesValue in Modules.Values)
{
modulesValue.Terminate();
}
}
public bool OnTimer()
{
//MonitorModuleAlarm();
MonitorPmTmInfo();
MonitorUPSAlarm();
return true;
}
private void MonitorPmTmInfo()
{
if (_pm1SlitValve != null)
{
if (_pm1InterLock != null && _pm1InterLock.DoPMASlitDoorClosed != _pm1SlitValve.IsClose)
{
_pm1InterLock.DoPMASlitDoorClosed = _pm1SlitValve.IsClose;
}
if (_tmInterLock != null && _pm1InterLock != null)
{
if (_tmInterLock.DoPm1LidClosed != _pm1InterLock.DiChamLidClosed)
{
_tmInterLock.DoPm1LidClosed = _pm1InterLock.DiChamLidClosed;
}
if (_tmInterLock.DoRectorAATMTransferReady != _pm1InterLock.DoReactorATMTransferReady)
{
_tmInterLock.DoRectorAATMTransferReady = _pm1InterLock.DoReactorATMTransferReady;
}
if (_tmInterLock.DoRectorAProcessTransferReady != _pm1InterLock.DoReactorVACTransferReady)
{
_tmInterLock.DoRectorAProcessTransferReady = _pm1InterLock.DoReactorVACTransferReady;
}
}
}
if (_pm2SlitValve != null)
{
if (_pm2InterLock != null && _pm2InterLock.DoPMASlitDoorClosed != _pm2SlitValve.IsClose)
{
_pm2InterLock.DoPMASlitDoorClosed = _pm2SlitValve.IsClose;
}
if (_tmInterLock != null && _pm2InterLock != null)
{
if (_tmInterLock.DoPm2LidClosed != _pm2InterLock.DiChamLidClosed)
{
_tmInterLock.DoPm2LidClosed = _pm2InterLock.DiChamLidClosed;
}
if (_tmInterLock.DoRectorBATMTransferReady != _pm2InterLock.DoReactorATMTransferReady)
{
_tmInterLock.DoRectorBATMTransferReady = _pm2InterLock.DoReactorATMTransferReady;
}
if (_tmInterLock.DoRectorBProcessTransferReady != _pm2InterLock.DoReactorVACTransferReady)
{
_tmInterLock.DoRectorBProcessTransferReady = _pm2InterLock.DoReactorVACTransferReady;
}
}
}
}
private void MonitorUPSAlarm()
{
string sReason;
if (_upsPM1A != null && _upsPM1B != null && _pm1UPS != null)
{
bool _power1 = !(_upsPM1A.UPSPowerAlarm || _upsPM1B.UPSPowerAlarm);
bool _lowerBattery1 = !(_upsPM1A.UPSLowerBatteryAlarm || _upsPM1B.UPSLowerBatteryAlarm);
if (_pm1UPS.UPSEnable == _power1)
{
_pm1UPS.SetUPSEnable(_power1, out sReason);
}
if (_pm1UPS.UPSLowBattery == _lowerBattery1)
{
_pm1UPS.SetUPSLowBattery(_lowerBattery1, out sReason);
}
}
if (_upsPM2A != null && _upsPM2B != null && _pm2UPS != null)
{
bool _power2 = !(_upsPM2A.UPSPowerAlarm || _upsPM2B.UPSPowerAlarm);
bool _lowerBattery2 = !(_upsPM2A.UPSLowerBatteryAlarm || _upsPM2B.UPSLowerBatteryAlarm);
if (_pm2UPS.UPSEnable == _power2)
{
_pm2UPS.SetUPSEnable(_power2, out sReason);
}
if (_pm2UPS.UPSLowBattery == _lowerBattery2)
{
_pm2UPS.SetUPSLowBattery(_lowerBattery2, out sReason);
}
}
}
#endregion
}
}