|  | @@ -25,6 +25,7 @@ namespace FurnaceRT.Equipments.PMs
 | 
	
		
			
				|  |  |          private R_TRIG _trigN2DownRD = new R_TRIG();
 | 
	
		
			
				|  |  |          private R_TRIG _trigN2AirUpRD = new R_TRIG();
 | 
	
		
			
				|  |  |          private R_TRIG _trigN2AirDownRD = new R_TRIG();
 | 
	
		
			
				|  |  | +        private R_TRIG _trigN2AirDownTwoRD = new R_TRIG();
 | 
	
		
			
				|  |  |          private R_TRIG _trigSelectN2PurgeModeD = new R_TRIG();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          private Dictionary<string, Tuple<R_TRIG, List<Tuple<IDevice, string>>>> _n2PurgeSequenceAction;
 | 
	
	
		
			
				|  | @@ -33,7 +34,9 @@ namespace FurnaceRT.Equipments.PMs
 | 
	
		
			
				|  |  |          private N2PurgeModeEnum _N2PurgeMode = N2PurgeModeEnum.Auto;
 | 
	
		
			
				|  |  |          private double _n2PurgeData = 20;
 | 
	
		
			
				|  |  |          private double _n2ToAirData = 185000;
 | 
	
		
			
				|  |  | -        private double _stabilityTime = 30;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        private double _manualPhase2StabilityTime = 60;
 | 
	
		
			
				|  |  | +        private double _manualPhase4StabilityTime = 60;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          private Dictionary<string, Stopwatch> _allTimeDict = new Dictionary<string, Stopwatch>();
 | 
	
		
			
				|  |  |          private void InitN2PurgeData()
 | 
	
	
		
			
				|  | @@ -49,7 +52,8 @@ namespace FurnaceRT.Equipments.PMs
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              _n2PurgeData = SC.ContainsItem($"System.N2PurgeData") ? SC.GetValue<double>("System.N2PurgeData") : 20;
 | 
	
		
			
				|  |  |              _n2ToAirData = SC.ContainsItem($"System.N2PurgeData") ? SC.GetValue<double>("System.N2ToAirData") : 185000;
 | 
	
		
			
				|  |  | -            _stabilityTime = SC.ContainsItem($"System.StabilityTime") ? SC.GetValue<double>("System.StabilityTime") : 30;
 | 
	
		
			
				|  |  | +            _manualPhase2StabilityTime = SC.ContainsItem($"PM1.N2Purge.Manual_phase2.StabilityTime") ? SC.GetValue<double>("PM1.N2Purge.Manual_phase2.StabilityTime") : 60;
 | 
	
		
			
				|  |  | +            _manualPhase4StabilityTime = SC.ContainsItem($"PM1.N2Purge.Manual_phase4.StabilityTime") ? SC.GetValue<double>("PM1.N2Purge.Manual_phase4.StabilityTime") : 60;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              _n2PurgeSequenceAction = ExtractionMethods.GetN2PurgeSequenceAction();
 | 
	
		
			
				|  |  |              _n2PurgeSequenceStatus = new Dictionary<string, Func<bool>>()
 | 
	
	
		
			
				|  | @@ -65,6 +69,7 @@ namespace FurnaceRT.Equipments.PMs
 | 
	
		
			
				|  |  |                  {N2PurgeModeEnum.Manual_phase2.ToString(),()=>  GetN2PurgePhase2()},
 | 
	
		
			
				|  |  |                  {N2PurgeModeEnum.Manual_phase3.ToString(),()=>  GetN2PurgePhase3() },
 | 
	
		
			
				|  |  |                  {N2PurgeModeEnum.Manual_phase4.ToString(),()=>  GetN2PurgePhase4() },
 | 
	
		
			
				|  |  | +                {N2PurgeModeEnum.Manual_phase5.ToString(),()=>  GetN2PurgePhase5() },
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              };
 | 
	
		
			
				|  |  |              _allTimeDict = new Dictionary<string, Stopwatch>()
 | 
	
	
		
			
				|  | @@ -72,7 +77,8 @@ namespace FurnaceRT.Equipments.PMs
 | 
	
		
			
				|  |  |                  {N2PurgeModeEnum.Manual_phase1.ToString(),new Stopwatch() },
 | 
	
		
			
				|  |  |                  {N2PurgeModeEnum.Manual_phase2.ToString(),new Stopwatch()},
 | 
	
		
			
				|  |  |                  {N2PurgeModeEnum.Manual_phase3.ToString(),new Stopwatch()},
 | 
	
		
			
				|  |  | -                {N2PurgeModeEnum.Manual_phase4.ToString(),new Stopwatch() }
 | 
	
		
			
				|  |  | +                {N2PurgeModeEnum.Manual_phase4.ToString(),new Stopwatch() },
 | 
	
		
			
				|  |  | +                {N2PurgeModeEnum.Manual_phase5.ToString(),new Stopwatch() }
 | 
	
		
			
				|  |  |              };
 | 
	
		
			
				|  |  |              _rTrigDict = new Dictionary<string, R_TRIG>();
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -101,12 +107,13 @@ namespace FurnaceRT.Equipments.PMs
 | 
	
		
			
				|  |  |                  case N2PurgeModeEnum.N2PurgeMode:
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                      ProcessPhase(_trigN2UpRD, N2PurgeModeEnum.Manual_phase1.ToString());
 | 
	
		
			
				|  |  | -                    ProcessPhase(_trigN2DownRD, N2PurgeModeEnum.Manual_phase2.ToString());
 | 
	
		
			
				|  |  | +                    ProcessPhase(_trigN2DownRD, N2PurgeModeEnum.Manual_phase2.ToString(), true, (int)(_manualPhase2StabilityTime * 1000));
 | 
	
		
			
				|  |  |                      break;
 | 
	
		
			
				|  |  |                  case N2PurgeModeEnum.ATMMode:
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                      ProcessPhase(_trigN2AirDownRD, N2PurgeModeEnum.Manual_phase3.ToString());
 | 
	
		
			
				|  |  | -                    ProcessPhase(_trigN2AirUpRD, N2PurgeModeEnum.Manual_phase4.ToString());
 | 
	
		
			
				|  |  | +                    ProcessPhase(_trigN2AirUpRD, N2PurgeModeEnum.Manual_phase4.ToString(), true, (int)(_manualPhase4StabilityTime * 1000));
 | 
	
		
			
				|  |  | +                    ProcessPhase(_trigN2AirDownTwoRD, N2PurgeModeEnum.Manual_phase5.ToString());
 | 
	
		
			
				|  |  |                      break;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -134,9 +141,9 @@ namespace FurnaceRT.Equipments.PMs
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |              return true;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        private void ProcessPhase(R_TRIG r_TRIG, string modeKey)
 | 
	
		
			
				|  |  | +        private void ProcessPhase(R_TRIG r_TRIG, string modeKey, bool needCheck = false, int time = 0)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            r_TRIG.CLK = _n2PurgeSequenceStatus[modeKey].Invoke();
 | 
	
		
			
				|  |  | +            r_TRIG.CLK = needCheck ? (CheckConditionInTime(modeKey, time, () => _n2PurgeSequenceStatus[modeKey].Invoke())) : _n2PurgeSequenceStatus[modeKey].Invoke();
 | 
	
		
			
				|  |  |              if (r_TRIG.Q)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  LOG.Info($"N2PurgeMode Trigger {modeKey}!,O2:{GetO2Density()},time:{_allTimeDict[modeKey].ElapsedMilliseconds}");
 | 
	
	
		
			
				|  | @@ -266,15 +273,15 @@ namespace FurnaceRT.Equipments.PMs
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          private bool GetN2PurgePhase3()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            return GetLADoorOpenStatus();
 | 
	
		
			
				|  |  | +            return GetO2Density() < _n2ToAirData && GetLADoorOpenStatus();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          private bool GetN2PurgePhase5()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            return GetO2Density() >= _n2ToAirData && GetLADoorOpenStatus();
 | 
	
		
			
				|  |  | +            return GetO2Density() >= _n2ToAirData && !GetLADoorOpenStatus();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          private bool GetN2PurgePhase4()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            return GetO2Density() >= _n2ToAirData;
 | 
	
		
			
				|  |  | +            return GetO2Density() >= _n2ToAirData && GetLADoorOpenStatus();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          private bool GetN2PurgeAIRTo20PPMStatus()
 | 
	
		
			
				|  |  |          {
 |