2023-04-13 15:35:13 +08:00
using System ;
using System.Collections.Generic ;
using Aitex.Core.Common ;
2023-03-28 13:24:11 +08:00
using Aitex.Core.RT.DataCenter ;
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.RT.Tolerance ;
using Aitex.Core.Util ;
using MECF.Framework.Common.DBCore ;
using MECF.Framework.Common.Equipment ;
using MECF.Framework.Common.SubstrateTrackings ;
2023-04-23 14:18:42 +08:00
using MECF.Framework.UI.Core.TrayCoating ;
2023-04-13 15:35:13 +08:00
using SicModules.PMs.Routines.Base ;
2023-03-28 13:24:11 +08:00
using static Aitex . Core . RT . Device . PmDevices . DicMode ;
2023-04-13 15:35:13 +08:00
namespace SicModules.PMs.RecipeExecutions
2023-03-28 13:24:11 +08:00
{
public enum RecipeContinueMode
{
None ,
WaferReturnAndJobStop ,
RecipeCompleted ,
StepContinue ,
StepRestart ,
RecipeRestart ,
NextStep ,
}
public partial class Process : PMBaseRoutine
{
enum RoutineStep
{
WaitProcess ,
}
enum RecipeRunningState
{
Error ,
RecipeCompleted ,
ExecStep ,
TimeWait ,
ConditionWait ,
StepCompleted ,
Paused ,
}
private object _recipeLocker = new object ( ) ;
private bool _hasRecordRunTime = false ;
private RecipeRunningState _state = RecipeRunningState . ExecStep ;
private RecipeRunningState _pausedState = RecipeRunningState . ExecStep ;
private DeviceTimer _estimatedTimeCalcTimer = new DeviceTimer ( ) ; //用于定时计算工艺程序估计的结束时间
private double _curStepElpasedTimeBeforePaused ;
private double _curStepElpasedTimeBeforePaused2 ;
private List < int > _lstSkipSteps = new List < int > ( ) ;
public RecipeContinueMode ContinueAction { get ; set ; }
public DateTime _recipeStartTime
{
get ;
private set ;
}
public string CurrentRecipeContent { get ; private set ; }
private int _currentStepNumber ;
private int _dummyStepCount ;
public int CurStepTotalLoopCount
{
get ;
private set ;
}
public double CurStepTotalTime
{
get
{
if ( PmDevice . RecipeRunningInfo . RecipeStepList = = null | | PmDevice . RecipeRunningInfo . RecipeStepList . Count = = 0 | | _state = = RecipeRunningState . RecipeCompleted | | _state = = RecipeRunningState . Error )
return 0 ;
return PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . StepTime * 1000 ;
}
}
public int CurrentLoopCount
{
get ;
private set ;
}
private DeviceTimer _stepTimer = new DeviceTimer ( ) ;
private DeviceTimer _stepTimer2 = new DeviceTimer ( ) ;
private DeviceTimer _recipeTimer = new DeviceTimer ( ) ;
public bool IsPaused
{
private set ;
get ;
}
private double CurStepLeftTime
{
get
{
return _stepTimer . GetTotalTime ( ) - _stepTimer . GetElapseTime ( ) ;
}
}
public double EstimatedTotalLeftTime
{
get ;
private set ;
}
private RecipeDBCallback _dbCallback ;
private Fdc _fdc ;
private bool _isDryRun ;
private int _delayTimeDryRun ;
private double _tempOffset ;
private int _currentStepIndex = 99 ;
private IoInterLock _pmInterLock ;
#region Parse
private bool _isPSUHeaterJumpMode ;
private bool _isSCRHeaterJumpMode ;
private bool _isMFCJumpMode ;
#endregion
#region Check
private PeriodicJob _thread ;
private DeviceTimer _rampCalcTimer = new DeviceTimer ( ) ; //用于定时获取PC的Ramp
protected ToleranceChecker [ ] _mfcGapChecker = new ToleranceChecker [ 32 ] ;
protected R_TRIG [ ] _mfcTrig = new R_TRIG [ 32 ] ;
protected ToleranceChecker [ ] _pcGapChecker = new ToleranceChecker [ 7 ] ;
protected R_TRIG [ ] _pcTrig = new R_TRIG [ 7 ] ;
protected R_TRIG [ ] _pcTrig2 = new R_TRIG [ 7 ] ;
protected double [ ] _pressurePrevious = new double [ 7 ] ;
#endregion
public Process ( ModuleName module , PMModule pm1 ) : base ( module , pm1 )
{
Module = module . ToString ( ) ;
Name = "Process" ;
_dbCallback = new RecipeDBCallback ( ) ;
_fdc = new Fdc ( Module ) ;
_pmInterLock = DEVICE . GetDevice < IoInterLock > ( $"{Module}.PMInterLock" ) ;
for ( int i = 0 ; i < _mfcGapChecker . Length ; i + + )
{
_mfcGapChecker [ i ] = new ToleranceChecker ( ) ;
_mfcTrig [ i ] = new R_TRIG ( ) ;
}
for ( int i = 0 ; i < _pcGapChecker . Length ; i + + )
{
_pcGapChecker [ i ] = new ToleranceChecker ( ) ;
_pcTrig [ i ] = new R_TRIG ( ) ;
_pcTrig2 [ i ] = new R_TRIG ( ) ;
}
Initialize ( ) ;
Calculte ( ) ;
_thread = new PeriodicJob ( 10 * 1000 , Calculte , "Calculte Standard Deviation" , false ) ;
}
public override Result Start ( params object [ ] param )
{
Reset ( ) ;
_hasRecordRunTime = false ;
if ( ! _pmInterLock . SetPMProcessRunning ( true , out string reason ) )
{
EV . PostAlarmLog ( Module , $"can not run Process, {reason}" ) ;
return Result . FAIL ;
}
_lstSkipSteps = new List < int > ( ) ;
_currentStepIndex = 99 ;
_currentStepNumber = CurStepTotalLoopCount = 0 ;
_dummyStepCount = 0 ;
_estimatedTimeCalcTimer . Start ( 1000 ) ;
_rampCalcTimer . Start ( 1000 ) ;
PmDevice . RecipeRunningInfo . InnerId = Guid . NewGuid ( ) ;
PmDevice . RecipeRunningInfo . BeginTime = DateTime . Now ;
PmDevice . RecipeRunningInfo . TotalTime = CalcRecipeTime ( ) ;
PmDevice . RecipeRunningInfo . IsRoutineAbort = false ;
_state = RecipeRunningState . ExecStep ;
_recipeTimer . Start ( int . MaxValue ) ;
_dbCallback . RecipeStart ( PmDevice . Module , 0 , PmDevice . RecipeRunningInfo . InnerId . ToString ( ) , PmDevice . RecipeRunningInfo . RecipeName ) ;
_dbCallback . RecipeUpdateStatus ( PmDevice . RecipeRunningInfo . InnerId . ToString ( ) , "InProcess" ) ;
WaferManager . Instance . UpdateWaferProcessStatus ( ModuleHelper . Converter ( Module ) , 0 , EnumWaferProcessStatus . InProcess ) ;
WaferManager . Instance . GetWafer ( ModuleHelper . Converter ( Module ) , 0 ) . TrayProcessCount - - ;
_fdc . Reset ( ) ;
_isDryRun = SC . GetValue < bool > ( $"PM.{Module}.DryRun.IsDryRun" ) ;
_delayTimeDryRun = SC . GetValue < int > ( $"PM.{Module}.DryRun.DryRunDelayTime" ) ;
_tempOffset = SC . GetValue < double > ( $"PM.{Module}.Process.TempOffset" ) ;
_thread . Start ( ) ;
Notify ( $"Start" ) ;
return Result . RUN ;
}
public override Result Monitor ( )
{
if ( ! PmDevice . CheckEnableRunProcess ( out string reason ) )
{
EV . PostAlarmLog ( Module , reason ) ;
return Result . FAIL ;
}
if ( _isDryRun ) // 空跑工艺
{
try
{
DryRunProcess ( ( int ) RoutineStep . WaitProcess , $"Chamber:{Name}:WaitProcess" , _delayTimeDryRun ) ;
}
catch ( RoutineBreakException )
{
return Result . RUN ;
}
catch ( RoutineFaildException )
{
return Result . FAIL ;
}
Notify ( "End" ) ;
return Result . DONE ;
}
else
{
MonitorRecipeEndTime ( ) ;
MonitorRecipeRunInfo ( ) ;
lock ( _recipeLocker )
{
try
{
switch ( _state )
{
case RecipeRunningState . ExecStep :
{
PmDevice . ResetToleranceChecker ( ) ;
//int stepTime = (int)PMDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepTime * 1000;
if ( ContinueAction ! = RecipeContinueMode . StepContinue )
{
_curStepElpasedTimeBeforePaused = 0 ;
_curStepElpasedTimeBeforePaused2 = 0 ;
}
ContinueAction = RecipeContinueMode . None ;
if ( PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . IsLoopStartStep )
{
CurStepTotalLoopCount = PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . LoopCount ;
if ( CurStepTotalLoopCount = = 0 )
{
CurrentLoopCount = 0 ;
}
else
{
CurrentLoopCount + + ;
}
}
//stepTime = (int)(PMDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepTime - _curStepElpasedTimeBeforePaused / 1000);
_stepTimer . Start ( PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . StepTime * 1000 - _curStepElpasedTimeBeforePaused ) ;
if ( ! _stepTimer2 . IsIdle ( ) )
{
_curStepElpasedTimeBeforePaused2 + = _stepTimer2 . GetElapseTime ( ) ;
_stepTimer2 . Stop ( ) ;
}
_stepTimer2 . Start ( int . MaxValue ) ;
Notify ( $"Running step {_currentStepNumber + 1} : {PmDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepName}" ) ;
if ( PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . IsDummyStep )
{
_dummyStepCount + + ;
}
//执行工艺程序命令
foreach ( var recipeCmd in PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . RecipeCommands . Keys )
{
if ( recipeCmd = = "SusHeaterSetMode" )
{
if ( PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . RecipeCommands [ recipeCmd ] = = "Jump" )
_isPSUHeaterJumpMode = true ;
else
_isPSUHeaterJumpMode = false ;
continue ;
}
if ( recipeCmd = = "WWHeaterSetMode" )
{
if ( PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . RecipeCommands [ recipeCmd ] = = "Jump" )
_isSCRHeaterJumpMode = true ;
else
_isSCRHeaterJumpMode = false ;
continue ;
}
if ( recipeCmd = = "FlowSetMode" )
{
if ( PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . RecipeCommands [ recipeCmd ] = = "Jump" )
_isMFCJumpMode = true ;
else
_isMFCJumpMode = false ;
continue ;
}
if ( IsCmdSkip ( recipeCmd ) ) // 不是注册的方法,需要跳过
continue ;
if ( ! OP . CanDoOperation ( $"{Module}.{recipeCmd}" , out reason , PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . RecipeCommands [ recipeCmd ] ) )
{
EV . PostAlarmLog ( Module , $"Can not execute {recipeCmd}, {reason}" ) ;
return Result . FAIL ;
}
else
{
int time = ( int ) ( PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . StepTime * 1000 - _curStepElpasedTimeBeforePaused ) ; // (int)PMDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepTime * 1000;
if ( recipeCmd . StartsWith ( "TC1" ) & & _isPSUHeaterJumpMode )
{
time = 1 ;
}
if ( recipeCmd . StartsWith ( "TC2" ) & & _isSCRHeaterJumpMode )
{
time = 1 ;
}
if ( recipeCmd . StartsWith ( "Mfc" ) & & recipeCmd . EndsWith ( ".Ramp" ) & & ! PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . IsDummyStep )
{
if ( _isMFCJumpMode )
{
time = 1 ;
}
}
if ( ( recipeCmd = = "TV.SetPressure"
| | recipeCmd = = "PMServo.SetActualSpeed"
| | recipeCmd . StartsWith ( "Pressure" ) & & recipeCmd . EndsWith ( ".Ramp" )
| | recipeCmd . StartsWith ( "Mfc" ) & & recipeCmd . EndsWith ( ".Ramp" ) )
& & ! PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . IsDummyStep )
{
if ( _currentStepNumber > = 1 )
{
int previousStepNumber = _currentStepNumber - 1 ;
if ( PmDevice . RecipeRunningInfo . RecipeStepList [ previousStepNumber ] . IsDummyStep )
previousStepNumber = _currentStepNumber - 2 ;
if ( PmDevice . RecipeRunningInfo . RecipeStepList [ previousStepNumber ] . RecipeCommands . ContainsKey ( recipeCmd ) )
{
string previousValue = PmDevice . RecipeRunningInfo . RecipeStepList [ previousStepNumber ] . RecipeCommands [ recipeCmd ] ;
string currentValue = PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . RecipeCommands [ recipeCmd ] ;
if ( previousValue = = currentValue )
{
if ( _lstSkipSteps . Count > 0 & & _lstSkipSteps . Contains ( previousStepNumber ) ) //上一步是跳步过来的,这一步和上一步的值是相同的不用设置
{
continue ;
}
time = 1 ;
}
}
}
}
OP . DoOperation ( $"{Module}.{recipeCmd}" , out string reason1 , time , PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . RecipeCommands [ recipeCmd ] ) ;
}
}
if ( PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . EndBy = = EnumEndByCondition . ByTime )
_state = RecipeRunningState . TimeWait ;
else
_state = RecipeRunningState . ConditionWait ;
//ResetChecker();
_dbCallback . RecipeStepStart ( PmDevice . RecipeRunningInfo . InnerId . ToString ( ) , _currentStepNumber , PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . StepName , ( float ) PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . StepTime ) ;
_fdc . Start ( PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . RecipeCommands ) ;
}
break ;
case RecipeRunningState . TimeWait :
if ( IsPaused )
{
_state = RecipeRunningState . Paused ;
}
if ( _stepTimer . IsTimeout ( ) )
{
_state = RecipeRunningState . StepCompleted ;
2023-04-23 14:18:42 +08:00
Grow ( ) ;
2023-03-28 13:24:11 +08:00
}
//ToleranceChecker();
SkipStepForHeat ( ) ;
break ;
case RecipeRunningState . ConditionWait :
{
if ( _stepTimer . IsTimeout ( ) )
{
_state = RecipeRunningState . StepCompleted ;
2023-04-23 14:18:42 +08:00
Grow ( ) ;
2023-03-28 13:24:11 +08:00
}
}
break ;
case RecipeRunningState . Paused :
PmDevice . PauseRecipe ( out reason ) ;
if ( ! _stepTimer . IsIdle ( ) )
{
_curStepElpasedTimeBeforePaused + = _stepTimer . GetElapseTime ( ) ;
_stepTimer . Stop ( ) ;
}
switch ( ContinueAction )
{
case RecipeContinueMode . None :
break ;
case RecipeContinueMode . WaferReturnAndJobStop :
//Singleton<RouteManager>.Instance.CheckToPostMessage((int)RouteManager.MSG.StopJob);
_state = RecipeRunningState . Error ;
break ;
case RecipeContinueMode . RecipeCompleted :
_state = RecipeRunningState . RecipeCompleted ;
break ;
case RecipeContinueMode . StepContinue :
_state = RecipeRunningState . ExecStep ;
break ;
case RecipeContinueMode . StepRestart :
_state = RecipeRunningState . ExecStep ;
break ;
case RecipeContinueMode . RecipeRestart :
_currentStepNumber = 0 ;
_state = RecipeRunningState . ExecStep ;
break ;
case RecipeContinueMode . NextStep :
_state = RecipeRunningState . StepCompleted ;
break ;
}
break ;
case RecipeRunningState . StepCompleted :
{
//放在前面, stepnumber后面会被更新
_stepTimer2 . Stop ( ) ;
_dbCallback . RecipeStepEnd ( PmDevice . RecipeRunningInfo . InnerId . ToString ( ) , _currentStepNumber , _fdc . DataList ) ;
_fdc . Stop ( ) ;
if ( PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . IsLoopEndStep )
{
//重新读取循环的设定次数
for ( int nn = _currentStepNumber ; nn > = 0 ; nn - - )
{
if ( PmDevice . RecipeRunningInfo . RecipeStepList [ nn ] . IsLoopStartStep )
{
CurStepTotalLoopCount = PmDevice . RecipeRunningInfo . RecipeStepList [ nn ] . LoopCount ;
break ;
}
}
if ( CurrentLoopCount > = CurStepTotalLoopCount )
{
CurrentLoopCount = CurStepTotalLoopCount = 0 ;
_currentStepNumber + + ;
}
else
{
int n = _currentStepNumber - 1 ;
int next = - 1 ;
while ( n > = 0 )
{
if ( PmDevice . RecipeRunningInfo . RecipeStepList [ n ] . IsLoopStartStep )
{
next = n ;
break ;
}
n - - ;
}
if ( next = = - 1 )
throw new Exception ( "Loop End control error" ) ;
_currentStepNumber = next ;
}
}
else
{
_currentStepNumber + + ;
}
if ( _currentStepNumber > = PmDevice . RecipeRunningInfo . RecipeStepList . Count )
{
_currentStepNumber = PmDevice . RecipeRunningInfo . RecipeStepList . Count - 1 ;
_state = RecipeRunningState . RecipeCompleted ;
}
else
{
_state = RecipeRunningState . ExecStep ;
}
}
break ;
case RecipeRunningState . RecipeCompleted :
{
//更新PM的Runtime
if ( ! _hasRecordRunTime )
{
_hasRecordRunTime = true ;
RuntimeDataRecorder . UpdateElapseTimePM ( Module + " Process" , ( int ) ( _recipeTimer . GetElapseTime ( ) / 60000 ) ) ;
}
_recipeTimer . Stop ( ) ;
Notify ( "Finished" ) ;
return Result . DONE ;
}
case RecipeRunningState . Error :
{
//更新PM的Runtime
if ( ! _hasRecordRunTime )
{
_hasRecordRunTime = true ;
RuntimeDataRecorder . UpdateElapseTimePM ( Module + " Process" , ( int ) ( _recipeTimer . GetElapseTime ( ) / 60000 ) ) ;
}
return Result . DONE ;
}
default :
break ;
}
}
catch ( Exception ex )
{
PmDevice . SetHeaterStopRamp ( ) ;
PmDevice . SetMfcStopRamp ( PmDevice . GetMfcListByGroupName ( MfcGroupName . All ) ) ;
PmDevice . SetRotationStopRamp ( ) ;
LOG . Write ( ex ) ;
return Result . FAIL ;
}
}
return Result . RUN ;
}
}
private void MonitorRecipeRunInfo ( )
{
try
{
PmDevice . RecipeRunningInfo . StepNumber = _currentStepNumber + 1 - _dummyStepCount ; //CurStepNum start from 0, ignore dummy step
PmDevice . RecipeRunningInfo . StepName = PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . StepName ;
PmDevice . RecipeRunningInfo . StepTime = PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . StepTime ;
2023-04-23 14:18:42 +08:00
PmDevice . RecipeRunningInfo . GrowthRate = PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . GrowthRate ;
2023-03-28 13:24:11 +08:00
PmDevice . RecipeRunningInfo . StepElapseTime = _stepTimer . IsIdle ( ) ? _curStepElpasedTimeBeforePaused / 1000 : ( _stepTimer . GetElapseTime ( ) + _curStepElpasedTimeBeforePaused ) / 1000 ;
PmDevice . RecipeRunningInfo . TotalElapseTime = CalcElapseRecipeTime ( ) ;
PmDevice . RecipeRunningInfo . StepElapseTime2 = _stepTimer2 . IsIdle ( ) ? _curStepElpasedTimeBeforePaused2 / 1000 : ( _stepTimer2 . GetElapseTime ( ) + _curStepElpasedTimeBeforePaused2 ) / 1000 ;
PmDevice . RecipeRunningInfo . TotalElapseTime2 = _recipeTimer . GetElapseTime ( ) / 1000 ;
if ( PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . RecipeCommands . ContainsKey ( "SHArH2Switch.SetValve" ) )
{
PmDevice . RecipeRunningInfo . ArH2Switch = PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . RecipeCommands [ "SHArH2Switch.SetValve" ] ;
}
if ( PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . RecipeCommands . ContainsKey ( "N2Dilution.SetValve" ) )
{
PmDevice . RecipeRunningInfo . N2FlowMode = PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] . RecipeCommands [ "N2Dilution.SetValve" ] ;
}
if ( _currentStepIndex ! = PmDevice . RecipeRunningInfo . StepNumber )
{
Notify ( $"Start Recipe: Step:{PmDevice.RecipeRunningInfo.StepNumber} Name:{PmDevice.RecipeRunningInfo.StepName} " ) ;
_currentStepIndex = PmDevice . RecipeRunningInfo . StepNumber ;
}
}
catch ( Exception ex )
{
}
}
public override void Abort ( )
{
//更新PM的Runtime
PmDevice . RecipeRunningInfo . IsRoutineAbort = true ;
if ( ! _hasRecordRunTime )
{
_hasRecordRunTime = true ;
RuntimeDataRecorder . UpdateElapseTimePM ( Module + " Process" , ( int ) ( _recipeTimer . GetElapseTime ( ) / 60000 ) ) ;
}
_state = RecipeRunningState . RecipeCompleted ;
_dbCallback . RecipeFailed ( PmDevice . RecipeRunningInfo . InnerId . ToString ( ) ) ;
_fdc . Stop ( ) ;
PmDevice . AbortRunProcess ( out string reason ) ;
PmDevice . RecipeRunningInfo . StepName = string . Empty ;
PmDevice . RecipeRunningInfo . StepNumber = 0 ;
PmDevice . RecipeRunningInfo . StepTime = 0 ;
PmDevice . RecipeRunningInfo . StepElapseTime = 0 ;
PmDevice . RecipeRunningInfo . TotalTime = 0 ;
PmDevice . RecipeRunningInfo . TotalElapseTime = 0 ;
//PMDevice.Rf.SetPowerOnOff(false, out _);
//PMDevice.Microwave.SetPowerOnOff(false, out _);
//PMDevice.GasLine1.SetFlow(out _, 0, 0);
//PMDevice.GasLine2.SetFlow(out _, 0, 0);
//PMDevice.GasLine3.SetFlow(out _, 0, 0);
}
public void ExitProcess ( )
{
if ( _state = = RecipeRunningState . RecipeCompleted )
{
_dbCallback . RecipeComplete ( PmDevice . RecipeRunningInfo . InnerId . ToString ( ) ) ;
_fdc . Stop ( ) ;
}
else
{
_dbCallback . RecipeFailed ( PmDevice . RecipeRunningInfo . InnerId . ToString ( ) ) ;
_fdc . Stop ( ) ;
}
_thread . Stop ( ) ;
}
public void PauseRecipe ( )
{
if ( _state ! = RecipeRunningState . TimeWait & & _state ! = RecipeRunningState . ConditionWait )
return ;
if ( ! IsPaused )
{
IsPaused = true ;
_pausedState = _state ;
_state = RecipeRunningState . Paused ;
}
}
public void SkipCurrentRecipeStep ( )
{
if ( _state = = RecipeRunningState . ConditionWait | | _state = = RecipeRunningState . TimeWait )
{
_lstSkipSteps . Add ( _currentStepNumber ) ;
_state = RecipeRunningState . StepCompleted ;
}
}
protected int CalcRecipeTime ( )
{
double total = 0 ;
for ( int i = 0 ; i < PmDevice . RecipeRunningInfo . RecipeStepList . Count ; i + + )
{
if ( ! PmDevice . RecipeRunningInfo . RecipeStepList [ i ] . IsDummyStep ) // 不统计虚拟Step的时间
{
total + = PmDevice . RecipeRunningInfo . RecipeStepList [ i ] . StepTime ;
}
}
return ( int ) total ;
}
protected int CalcElapseRecipeTime ( )
{
double total = 0 ;
for ( int i = 0 ; i < _currentStepNumber ; i + + )
{
if ( ! PmDevice . RecipeRunningInfo . RecipeStepList [ i ] . IsDummyStep ) // 不统计虚拟Step的时间
{
total + = PmDevice . RecipeRunningInfo . RecipeStepList [ i ] . StepTime ;
}
}
total + = PmDevice . RecipeRunningInfo . StepElapseTime ;
return ( int ) total ;
}
protected void MonitorRecipeEndTime ( )
{
try
{
if ( ! _estimatedTimeCalcTimer . IsTimeout ( ) )
return ;
_estimatedTimeCalcTimer . Start ( 1000 ) ;
EstimatedTotalLeftTime = 0 ;
if ( _state = = RecipeRunningState . RecipeCompleted )
return ;
if ( ! ( _currentStepNumber > = 0 & & _currentStepNumber < = PmDevice . RecipeRunningInfo . RecipeStepList . Count - 1 ) )
return ;
if ( CurStepLeftTime > 0 )
{
EstimatedTotalLeftTime = CurStepLeftTime ;
}
int nextBegin = _currentStepNumber ;
bool IsInLoop = false ;
int iNum1 = 0 ;
int iNum2 = 0 ;
//int j=i;
for ( int j = _currentStepNumber ; j < PmDevice . RecipeRunningInfo . RecipeStepList . Count ; j + + )
{
if ( PmDevice . RecipeRunningInfo . RecipeStepList [ j ] . IsLoopEndStep )
{
iNum2 = j ;
IsInLoop = true ;
break ;
}
else if ( j > _currentStepNumber & & PmDevice . RecipeRunningInfo . RecipeStepList [ j ] . IsLoopStartStep )
{
IsInLoop = false ;
break ;
}
}
if ( IsInLoop )
{
iNum1 = _currentStepNumber ;
for ( int j = _currentStepNumber ; j > = 0 ; j - - )
{
if ( PmDevice . RecipeRunningInfo . RecipeStepList [ j ] . IsLoopStartStep )
{
iNum1 = j ;
break ;
}
}
for ( int j = _currentStepNumber + 1 ; j < = iNum2 ; j + + )
{
EstimatedTotalLeftTime + = PmDevice . RecipeRunningInfo . RecipeStepList [ j ] . StepTime * 1000 * ( PmDevice . RecipeRunningInfo . RecipeStepList [ iNum1 ] . LoopCount - CurrentLoopCount + 1 ) ;
}
for ( int j = iNum1 ; j < = _currentStepNumber ; j + + )
{
EstimatedTotalLeftTime + = PmDevice . RecipeRunningInfo . RecipeStepList [ j ] . StepTime * 1000 * ( PmDevice . RecipeRunningInfo . RecipeStepList [ iNum1 ] . LoopCount - CurrentLoopCount ) ;
}
nextBegin = iNum2 + 1 ;
}
else
{
nextBegin + + ;
}
for ( int j = nextBegin ; j < PmDevice . RecipeRunningInfo . RecipeStepList . Count ; j + + )
{
if ( PmDevice . RecipeRunningInfo . RecipeStepList [ j ] . IsLoopStartStep )
{
//j=i;
iNum1 = j ;
iNum2 = j + 1 ;
double lr1 = 0 ;
for ( int m = j ; m < PmDevice . RecipeRunningInfo . RecipeStepList . Count ; m + + )
{
lr1 + = PmDevice . RecipeRunningInfo . RecipeStepList [ m ] . StepTime * 1000 ;
if ( PmDevice . RecipeRunningInfo . RecipeStepList [ m ] . IsLoopEndStep )
{
iNum2 = m ;
break ;
}
}
EstimatedTotalLeftTime + = lr1 * PmDevice . RecipeRunningInfo . RecipeStepList [ iNum1 ] . LoopCount ;
j = iNum2 ;
}
else
{
EstimatedTotalLeftTime + = PmDevice . RecipeRunningInfo . RecipeStepList [ j ] . StepTime * 1000 ;
}
}
}
catch ( Exception ex )
{
LOG . Write ( ex ) ;
}
}
public void SetContinue ( string continueMode )
{
switch ( continueMode )
{
case "Step continue" :
ContinueAction = RecipeContinueMode . StepContinue ;
break ;
case "Step restart" :
ContinueAction = RecipeContinueMode . StepRestart ;
break ;
case "Next step" :
ContinueAction = RecipeContinueMode . NextStep ;
break ;
case "Recipe restart" :
ContinueAction = RecipeContinueMode . RecipeRestart ;
break ;
case "Recipe complete" :
ContinueAction = RecipeContinueMode . RecipeCompleted ;
break ;
case "Wafer return and job stop" :
ContinueAction = RecipeContinueMode . WaferReturnAndJobStop ;
break ;
}
IsPaused = false ;
PmDevice . ResetToleranceChecker ( ) ;
}
public void DryRunProcess ( int id , string stepName , int delayTime )
{
Tuple < bool , Result > ret = Delay ( id , ( ) = >
{
Notify ( $"Dry run process {delayTime} seconds" ) ;
_stepSpan = new TimeSpan ( 0 , 0 , 0 , ( int ) delayTime ) ;
_stepStartTime = DateTime . Now ;
_stepName = stepName ;
return true ;
} , delayTime * 1000 ) ;
if ( ret . Item1 )
{
if ( ret . Item2 = = Result . FAIL )
{
throw ( new RoutineFaildException ( ) ) ;
}
throw new RoutineBreakException ( ) ;
}
}
public void ToleranceChecker ( )
{
#region MFC
for ( int i = 0 ; i < _mfcGapChecker . Length ; i + + )
{
_mfcGapChecker [ i ] . Monitor ( PmDevice . _mfcList [ i ] . FeedBack , PmDevice . _mfcList [ i ] . SetPoint * ( 1 - 2 / 100 ) , PmDevice . _mfcList [ i ] . SetPoint * ( 1 + 2 / 100 ) , 5 * 60 ) ;
if ( _mfcGapChecker [ i ] . Trig )
{
EV . PostWarningLog ( Module , $"{PmDevice._mfcList[i].Name} flow gap > 2%, over 5 minites" ) ;
}
}
for ( int i = 0 ; i < _mfcTrig . Length ; i + + )
{
double gap = Convert . ToDouble ( dbMfcGapResults [ i ] . StdDev ) ;
double setPoint = Convert . ToDouble ( dbMfcSetPointResults [ i ] . Mean ) ;
_mfcTrig [ i ] . CLK = gap / setPoint > 1 / 100 ;
if ( _mfcTrig [ i ] . Q )
{
EV . PostWarningLog ( Module , $"{PmDevice._mfcList[i].Name} flow standard deviation > 1%, for 5 minites" ) ;
}
}
#endregion
#region PC
for ( int i = 0 ; i < _pcGapChecker . Length ; i + + )
{
_pcGapChecker [ i ] . Monitor ( PmDevice . _pcList [ i ] . FeedBack , PmDevice . _pcList [ i ] . SetPoint - 60 , PmDevice . _pcList [ i ] . SetPoint + 60 , 5 * 60 ) ;
if ( _pcGapChecker [ i ] . Trig )
{
EV . PostWarningLog ( Module , $"{PmDevice._pcList[i].Name} flow gap > 60 mbar over 5 minites" ) ;
}
}
for ( int i = 0 ; i < _pcTrig . Length ; i + + )
{
double gap = Convert . ToDouble ( dbPcGapResults [ i ] . StdDev ) ;
//double setPoint = Convert.ToDouble(dbPcSetPointResults[i].StdDev);
_pcTrig [ i ] . CLK = gap > 10 ;
if ( _pcTrig [ i ] . Q )
{
EV . PostWarningLog ( Module , $"{PmDevice._mfcList[i].Name} flow standard deviation > 1%, for 5 minites" ) ;
}
}
if ( _rampCalcTimer . IsTimeout ( ) )
{
for ( int i = 0 ; i < _pcTrig2 . Length ; i + + )
{
_pcTrig2 [ i ] . CLK = Math . Abs ( PmDevice . _pcList [ i ] . FeedBack - _pressurePrevious [ i ] ) > 90 ;
if ( _pcTrig2 [ i ] . Q )
{
EV . PostWarningLog ( Module , $"{PmDevice._mfcList[i].Name} pressure ramp > 90 mbar" ) ;
}
_pressurePrevious [ i ] = PmDevice . _pcList [ i ] . FeedBack ;
}
_rampCalcTimer . Start ( 1000 ) ;
}
#endregion
}
public void ResetChecker ( )
{
#region MFC
for ( int i = 0 ; i < _mfcGapChecker . Length ; i + + )
{
_mfcGapChecker [ i ] . Reset ( 5 * 60 ) ;
}
for ( int i = 0 ; i < _mfcTrig . Length ; i + + )
{
_mfcTrig [ i ] . RST = true ;
}
#endregion
#region PC
for ( int i = 0 ; i < _pcGapChecker . Length ; i + + )
{
_pcGapChecker [ i ] . Reset ( 5 * 60 ) ;
}
for ( int i = 0 ; i < _pcTrig . Length ; i + + )
{
_pcTrig [ i ] . RST = true ;
}
#endregion
}
public void SkipStepForHeat ( )
{
int stepCount = PmDevice . RecipeRunningInfo . RecipeStepList . Count ;
if ( _currentStepNumber + 1 < stepCount )
{
var currentStep = PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber ] ;
var nextStep = PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber + 1 ] ;
if ( currentStep . IsDummyStep )
return ;
if ( nextStep . IsDummyStep )
nextStep = PmDevice . RecipeRunningInfo . RecipeStepList [ _currentStepNumber + 2 ] ;
if ( ! currentStep . RecipeCommands . ContainsKey ( "TC1.SetHeaterMode" ) | | ! nextStep . RecipeCommands . ContainsKey ( "TC1.SetHeaterMode" ) )
return ;
HeaterControlMode currentPSUMode = ( HeaterControlMode ) Enum . Parse ( typeof ( HeaterControlMode ) , currentStep . RecipeCommands [ "TC1.SetHeaterMode" ] ) ;
HeaterControlMode nextPSUMode = ( HeaterControlMode ) Enum . Parse ( typeof ( HeaterControlMode ) , nextStep . RecipeCommands [ "TC1.SetHeaterMode" ] ) ;
if ( currentPSUMode = = HeaterControlMode . Power & & nextPSUMode ! = HeaterControlMode . Power )
{
float PSUL2InputTemp = ( float ) DATA . Poll ( $"{Module}.TC1.L2InputTempSetPoint" ) ; // (float)DATA.Poll($"{Module}.TC1.L1PVFeedBack"); 测试用
float nextL2Temp = Convert . ToSingle ( nextStep . RecipeCommands [ "TC1.SetL2TargetSP" ] ) ;
if ( nextL2Temp > PSUL2InputTemp & & nextL2Temp - PSUL2InputTemp < Math . Abs ( _tempOffset ) )
{
SkipCurrentRecipeStep ( ) ;
EV . PostInfoLog ( Module , $"Current PSU middle temperature is {PSUL2InputTemp}℃ and Power mode, next step PSU middle temperature setpoint is {nextL2Temp}℃ and {nextPSUMode} mode." +
$" TempOffset is {_tempOffset}℃. Need jump step!" ) ;
}
}
}
}
2023-04-23 14:18:42 +08:00
public void Grow ( )
{
var wi = WaferManager . Instance . GetWafer ( ModuleHelper . Converter ( Module ) , 0 ) ;
2023-04-28 13:46:54 +08:00
OP . DoOperation ( $"CoatingManager.Grow" ,
new object [ ] {
2023-04-23 14:18:42 +08:00
( wi . TrayOriginSlot + 1 ) . ToString ( ) ,
PmDevice . RecipeRunningInfo . GrowthRate ,
PmDevice . RecipeRunningInfo . StepTime ,
Module } ) ;
}
2023-03-28 13:24:11 +08:00
}
}