526 lines
20 KiB
C#
526 lines
20 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using Aitex.Core.Common.DeviceData;
|
|
using Aitex.Core.RT.Device;
|
|
using Aitex.Core.RT.Device.Devices;
|
|
using Aitex.Core.RT.Event;
|
|
using Aitex.Core.RT.Log;
|
|
using Aitex.Core.RT.OperationCenter;
|
|
using Aitex.Core.RT.Routine;
|
|
using Aitex.Core.RT.SCCore;
|
|
using Aitex.Core.Util;
|
|
using MECF.Framework.Common.Equipment;
|
|
using SicModules.PMs.RecipeExecutions;
|
|
using SicModules.PMs.Routines.Base;
|
|
|
|
namespace SicModules.PMs.Routines.EditableRoutine
|
|
{
|
|
public enum RoutineType
|
|
{
|
|
AtmRoutine,
|
|
VacRoutine,
|
|
ProcessIdleRoutine,
|
|
PumpRoutine,
|
|
VentRoutine,
|
|
PurgeRoutine,
|
|
CleanRoutine,
|
|
ExchangeMORoutine,
|
|
IsolationRoutine,
|
|
LeakCheckRoutine,
|
|
AbortRoutine
|
|
}
|
|
|
|
public partial class EditableRoutine : PMBaseRoutine
|
|
{
|
|
enum RecipeRunningState
|
|
{
|
|
Error,
|
|
RecipeCompleted,
|
|
ExecStep,
|
|
TimeWait,
|
|
ConditionWait,
|
|
StepCompleted,
|
|
}
|
|
|
|
//当前步
|
|
private int _curStepNumber;
|
|
|
|
//当前循环开始步
|
|
public int CurStartLoopStep;
|
|
|
|
//当前循坏步已循坏次数
|
|
public int CurStepLoopNumber;
|
|
|
|
//当前循坏步总数
|
|
public int CurStepLoopTotalCount;
|
|
|
|
private Stopwatch _swTimer = new Stopwatch();
|
|
|
|
private DeviceTimer _stepTimer = new DeviceTimer();
|
|
|
|
private string _recipeName;
|
|
|
|
private IoInterLock _pmInterLock;
|
|
|
|
private RoutineType _routineType;
|
|
|
|
private RecipeRunningInfo _recipeRunningInfo = new RecipeRunningInfo();
|
|
|
|
private RecipeRunningState _state = RecipeRunningState.ExecStep;
|
|
|
|
private bool _isPSUHeaterJumpMode;
|
|
private bool _isSCRHeaterJumpMode;
|
|
private bool _isMFCJumpMode;
|
|
|
|
public EditableRoutine(ModuleName module, PMModule pm) : base(module, pm)
|
|
{
|
|
Module = module.ToString();
|
|
Name = "EditableRoutine";
|
|
|
|
_pmInterLock = DEVICE.GetDevice<IoInterLock>($"{Module}.PMInterLock");
|
|
}
|
|
|
|
public void Init(string recipeName, RoutineType routineType)
|
|
{
|
|
_recipeName = recipeName;
|
|
_routineType = routineType;
|
|
}
|
|
|
|
public bool SetRoutineRunning(bool eValue,out string reason)
|
|
{
|
|
reason = string.Empty;
|
|
|
|
if(_routineType == RoutineType.ProcessIdleRoutine)
|
|
{
|
|
if (!_pmInterLock.SetPMProcessIdleRunning(eValue, out reason))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if (_routineType == RoutineType.CleanRoutine)
|
|
{
|
|
if (!_pmInterLock.SetPMCleanRoutineRunning(eValue, out reason))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if (_routineType == RoutineType.PurgeRoutine)
|
|
{
|
|
if (!_pmInterLock.SetPMPurgeRoutineRunning(eValue, out reason))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if (_routineType == RoutineType.PumpRoutine)
|
|
{
|
|
if (!_pmInterLock.SetPMPumpRoutineRunning(eValue, out reason))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if (_routineType == RoutineType.VentRoutine)
|
|
{
|
|
if (!_pmInterLock.SetPMVentRoutineRunning(eValue, out reason))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if (_routineType == RoutineType.ExchangeMORoutine)
|
|
{
|
|
if (!_pmInterLock.SetPMExchangeMoRoutineRunning(eValue, out reason))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public override Result Start(params object[] param)
|
|
{
|
|
Reset();
|
|
|
|
//解析Recipe
|
|
if (!EditableRoutineParser.Parse(_recipeName, Module, out var recipeHead, out var recipeSteps, out string reason))
|
|
{
|
|
Stop($"Load Routine {_recipeName} failed, {reason}");
|
|
|
|
return Result.FAIL;
|
|
}
|
|
|
|
if(!SetRoutineRunning(true,out reason))
|
|
{
|
|
EV.PostAlarmLog(Module, $"can not run Routine, {reason}");
|
|
return Result.FAIL;
|
|
}
|
|
|
|
if (_routineType == RoutineType.PurgeRoutine)
|
|
{
|
|
_pmInterLock.DoLidCloseRoutineSucceed = false;
|
|
}
|
|
else if (_routineType == RoutineType.CleanRoutine)
|
|
{
|
|
_pmInterLock.DoLidOpenRoutineSucceed = false;
|
|
}
|
|
|
|
//设置当前Step
|
|
_curStepNumber = 0;
|
|
|
|
CurStartLoopStep = 0;
|
|
CurStepLoopNumber = 0;
|
|
CurStepLoopTotalCount = 0;
|
|
|
|
_recipeRunningInfo.RecipeName = _recipeName;
|
|
_recipeRunningInfo.Head = recipeHead;
|
|
_recipeRunningInfo.RecipeStepList = recipeSteps;
|
|
|
|
_state = RecipeRunningState.ExecStep;
|
|
|
|
_swTimer.Restart();
|
|
|
|
Notify($"Start");
|
|
return Result.RUN;
|
|
}
|
|
|
|
public override Result Monitor()
|
|
{
|
|
string reason;
|
|
|
|
try
|
|
{
|
|
switch (_state)
|
|
{
|
|
case RecipeRunningState.ExecStep:
|
|
{
|
|
Notify($"Running step {_curStepNumber + 1} : {_recipeRunningInfo.RecipeStepList[_curStepNumber].StepName}");
|
|
|
|
if (_recipeRunningInfo.RecipeStepList[_curStepNumber].EndBy == EnumEndByCondition.ByTime)
|
|
{
|
|
//开启Step计时器
|
|
_stepTimer.Start(_recipeRunningInfo.RecipeStepList[_curStepNumber].StepTime * 1000);
|
|
_state = RecipeRunningState.TimeWait;
|
|
}
|
|
else
|
|
{
|
|
_state = RecipeRunningState.ConditionWait;
|
|
}
|
|
|
|
//执行工艺程序命令
|
|
foreach (var recipeCmd in _recipeRunningInfo.RecipeStepList[_curStepNumber].RecipeCommands.Keys)
|
|
{
|
|
if (recipeCmd == "SusHeaterSetMode")
|
|
{
|
|
if (_recipeRunningInfo.RecipeStepList[_curStepNumber].RecipeCommands[recipeCmd] == "Jump")
|
|
{
|
|
_isPSUHeaterJumpMode = true;
|
|
}
|
|
else
|
|
{
|
|
_isPSUHeaterJumpMode = false;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if (recipeCmd == "WWHeaterSetMode")
|
|
{
|
|
if (_recipeRunningInfo.RecipeStepList[_curStepNumber].RecipeCommands[recipeCmd] == "Jump")
|
|
{
|
|
_isSCRHeaterJumpMode = true;
|
|
}
|
|
else
|
|
{
|
|
_isSCRHeaterJumpMode = false;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if (recipeCmd == "FlowSetMode")
|
|
{
|
|
if (_recipeRunningInfo.RecipeStepList[_curStepNumber].RecipeCommands[recipeCmd] == "Jump")
|
|
{
|
|
_isMFCJumpMode = true;
|
|
}
|
|
else
|
|
{
|
|
_isMFCJumpMode = false;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
// 不是注册的方法,需要跳过
|
|
if (IsCmdSkip(recipeCmd))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!OP.CanDoOperation($"{Module}.{recipeCmd}", out reason, _recipeRunningInfo.RecipeStepList[_curStepNumber].RecipeCommands[recipeCmd]))
|
|
{
|
|
EV.PostAlarmLog(Module, $"Can not execute {recipeCmd}, {reason}");
|
|
return Result.FAIL;
|
|
}
|
|
else
|
|
{
|
|
int time = (int)_recipeRunningInfo.RecipeStepList[_curStepNumber].StepTime * 1000;
|
|
|
|
if (recipeCmd.StartsWith("TC1") && _isPSUHeaterJumpMode)
|
|
{
|
|
time = 1;
|
|
}
|
|
|
|
if (recipeCmd.StartsWith("TC2") && _isSCRHeaterJumpMode)
|
|
{
|
|
time = 1;
|
|
}
|
|
|
|
if (recipeCmd.StartsWith("Mfc") && recipeCmd.EndsWith(".Ramp") && _isMFCJumpMode)
|
|
{
|
|
time = 1;
|
|
}
|
|
|
|
if (recipeCmd == "TV.SetPressure"
|
|
|| recipeCmd == "PMServo.SetActualSpeed"
|
|
|| recipeCmd.StartsWith("Pressure") && recipeCmd.EndsWith(".Ramp")
|
|
|| recipeCmd.StartsWith("Mfc") && recipeCmd.EndsWith(".Ramp"))
|
|
{
|
|
if (_curStepNumber >= 1)
|
|
{
|
|
int previousStepNumber = _curStepNumber - 1;
|
|
|
|
if (_recipeRunningInfo.RecipeStepList[previousStepNumber].RecipeCommands.ContainsKey(recipeCmd))
|
|
{
|
|
string previousValue = _recipeRunningInfo.RecipeStepList[previousStepNumber].RecipeCommands[recipeCmd];
|
|
string currentValue = _recipeRunningInfo.RecipeStepList[_curStepNumber].RecipeCommands[recipeCmd];
|
|
if (previousValue == currentValue)
|
|
{
|
|
time = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (recipeCmd.EndsWith(AITValveOperation.GVTurnValve)) // 阀门
|
|
{
|
|
OP.DoOperation($"{Module}.{recipeCmd}", _recipeRunningInfo.RecipeStepList[_curStepNumber].RecipeCommands[recipeCmd]);
|
|
}
|
|
else
|
|
{
|
|
OP.DoOperation($"{Module}.{recipeCmd}", out _, time, _recipeRunningInfo.RecipeStepList[_curStepNumber].RecipeCommands[recipeCmd]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (CurStepLoopNumber == 0)
|
|
{
|
|
if (_recipeRunningInfo.RecipeStepList[_curStepNumber].IsLoopStartStep)
|
|
{
|
|
CurStartLoopStep = _curStepNumber;
|
|
CurStepLoopNumber = 0;
|
|
CurStepLoopTotalCount = _recipeRunningInfo.RecipeStepList[_curStepNumber].LoopCount;
|
|
}
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case RecipeRunningState.TimeWait:
|
|
{
|
|
if (_stepTimer.IsTimeout())
|
|
{
|
|
_state = RecipeRunningState.StepCompleted;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case RecipeRunningState.ConditionWait:
|
|
{
|
|
//设置的压力
|
|
double.TryParse(_recipeRunningInfo.RecipeStepList[_curStepNumber].RecipeCommands["TV.SetPressure"], out double setPressure);
|
|
|
|
//实时反馈的压力
|
|
double feedBackPressure = DEVICE.GetDevice<IoThrottleValve2>($"{Module}.TV").PressureFeedback;
|
|
|
|
double _pmPressureMaxDiff = SC.GetValue<double>($"PM.{Module}.ThrottlePressureMaxDiff");
|
|
|
|
if (Math.Abs(setPressure - feedBackPressure) <= _pmPressureMaxDiff)
|
|
{
|
|
_state = RecipeRunningState.StepCompleted;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case RecipeRunningState.StepCompleted:
|
|
{
|
|
if (_recipeRunningInfo.RecipeStepList[_curStepNumber].IsLoopEndStep)
|
|
{
|
|
CurStepLoopNumber++;
|
|
|
|
if (CurStepLoopNumber >= CurStepLoopTotalCount)
|
|
{
|
|
CurStartLoopStep = 0;
|
|
CurStepLoopNumber = 0;
|
|
CurStepLoopTotalCount = 0;
|
|
|
|
_curStepNumber++;
|
|
}
|
|
else
|
|
{
|
|
_curStepNumber = CurStartLoopStep;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_curStepNumber++;
|
|
}
|
|
|
|
|
|
//判断最后一步是否执行完
|
|
if (_curStepNumber >= _recipeRunningInfo.RecipeStepList.Count)
|
|
{
|
|
_state = RecipeRunningState.RecipeCompleted;
|
|
}
|
|
else
|
|
{
|
|
_state = RecipeRunningState.ExecStep;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case RecipeRunningState.RecipeCompleted:
|
|
{
|
|
if (!SetRoutineRunning(false, out reason))
|
|
{
|
|
EV.PostAlarmLog(Module, $"can not run Routine, {reason}");
|
|
return Result.FAIL;
|
|
}
|
|
|
|
//设置Succeed状态
|
|
if (_routineType == RoutineType.PurgeRoutine)
|
|
{
|
|
_pmInterLock.SetLidOpenRoutineSucceed(true, out reason);
|
|
}
|
|
else if (_routineType == RoutineType.CleanRoutine)
|
|
{
|
|
_pmInterLock.SetLidClosedRoutineSucceed(true, out reason);
|
|
}
|
|
|
|
_curStepNumber = 0;
|
|
|
|
CurStartLoopStep = 0;
|
|
CurStepLoopNumber = 0;
|
|
CurStepLoopTotalCount = 0;
|
|
|
|
Notify("Finished");
|
|
return Result.DONE;
|
|
}
|
|
|
|
case RecipeRunningState.Error:
|
|
{
|
|
if (!SetRoutineRunning(false, out reason))
|
|
{
|
|
EV.PostAlarmLog(Module, $"can not run Routine, {reason}");
|
|
return Result.FAIL;
|
|
}
|
|
|
|
return Result.DONE;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
PmDevice.SetHeaterStopRamp();
|
|
PmDevice.SetMfcStopRamp(PmDevice.GetMfcListByGroupName(MfcGroupName.All));
|
|
PmDevice.SetRotationStopRamp();
|
|
|
|
if (!SetRoutineRunning(false, out reason))
|
|
{
|
|
EV.PostAlarmLog(Module, $"can not run Process, {reason}");
|
|
return Result.FAIL;
|
|
}
|
|
|
|
LOG.Write(ex);
|
|
return Result.FAIL;
|
|
}
|
|
|
|
return Result.RUN;
|
|
}
|
|
|
|
public override void Abort()
|
|
{
|
|
if (!SetRoutineRunning(false, out string reason))
|
|
{
|
|
EV.PostAlarmLog(Module, $"can not run Process, {reason}");
|
|
}
|
|
|
|
//根据Routine类型执行Abort
|
|
SetRoutineAbort();
|
|
|
|
base.Abort();
|
|
}
|
|
|
|
private List<string> _lstGroup1 = new List<string>() { "V46", "V46s", "V73" };
|
|
private List<string> _lstGroup2 = new List<string>() { "V46", "V46s" };
|
|
private List<string> _lstGroup3 = new List<string>() { "V43", "V43s", "V45" };
|
|
|
|
//默认为TMA换源参数
|
|
private int mfc7Or10 = 7;
|
|
private int mfc8Or12 = 8;
|
|
private int mfc11 = 11;
|
|
private int pc2Or3 = 2;
|
|
|
|
public void SetRoutineAbort()
|
|
{
|
|
if (_routineType == RoutineType.ProcessIdleRoutine)
|
|
{
|
|
PmDevice._ioThrottleValve.StopRamp();
|
|
PmDevice.SetMfcStopRamp(PmDevice.GetMfcListByGroupName(MfcGroupName.All));
|
|
PmDevice.SetHeaterStopRamp();
|
|
PmDevice.SetRotationStopRamp();
|
|
PmDevice.SetRotationServo(0, 0);
|
|
}
|
|
else if (_routineType == RoutineType.CleanRoutine)
|
|
{
|
|
PmDevice._ioThrottleValve.StopRamp();
|
|
PmDevice.SetMfcStopRamp(PmDevice.GetMfcListByGroupName(MfcGroupName.All));
|
|
PmDevice.SetRotationServo(0, 0);
|
|
}
|
|
else if (_routineType == RoutineType.PurgeRoutine)
|
|
{
|
|
PmDevice._ioThrottleValve.StopRamp();
|
|
PmDevice.SetMfcStopRamp(PmDevice.GetMfcListByGroupName(MfcGroupName.All));
|
|
PmDevice.SetRotationServo(0, 0);
|
|
}
|
|
else if (_routineType == RoutineType.PumpRoutine)
|
|
{
|
|
PmDevice.SetRotationServo(0, 0);
|
|
}
|
|
else if (_routineType == RoutineType.VentRoutine)
|
|
{
|
|
PmDevice._ioThrottleValve.StopRamp();
|
|
PmDevice.SetMfcStopRamp(PmDevice.GetMfcListByGroupName(MfcGroupName.All));
|
|
PmDevice.SetRotationServo(0, 0);
|
|
}
|
|
else if (_routineType == RoutineType.ExchangeMORoutine)
|
|
{
|
|
PmDevice.SetIoValue(_lstGroup1, false);
|
|
PmDevice.SetIoValue(_lstGroup2, false);
|
|
PmDevice.SetMfcValueToDefault(new List<int> { mfc7Or10 });
|
|
PmDevice.SetMfcValueToDefault(new List<int> { mfc8Or12 });
|
|
PmDevice.SetMfcValueToDefault(new List<int> { mfc11 });
|
|
PmDevice.SetPCValueToDefault(new List<int> { pc2Or3 });
|
|
PmDevice.SetRotationServo(0, 0);
|
|
}
|
|
else if (_routineType == RoutineType.VacRoutine)
|
|
{
|
|
PmDevice.SetRotationServo(0, 0);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|