444 lines
16 KiB
C#
444 lines
16 KiB
C#
using Aitex.Core.RT.Device.Devices;
|
|
using Aitex.Core.RT.Device;
|
|
using Aitex.Core.RT.Event;
|
|
using Aitex.Core.RT.Routine;
|
|
using Aitex.Core.RT.SCCore;
|
|
using MECF.Framework.Common.Equipment;
|
|
using SicModules.PMs.Routines.Base;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using SicModules.PMs.Utilities;
|
|
using Aitex.Core.RT.IOCore;
|
|
using Aitex.Core.RT.DBCore;
|
|
|
|
namespace SicModules.PMs.Routines
|
|
{
|
|
public class PMMfcRorRoutine : PMBaseRoutine
|
|
{
|
|
private enum RoutineStep
|
|
{
|
|
TimeDelay1,
|
|
TimeDelay2,
|
|
TimeDelay3,
|
|
TimeDelay4,
|
|
TimeDelay5,
|
|
TimeDelay6,
|
|
TimeDelay7,
|
|
TimeDelay8,
|
|
TimeDelay9,
|
|
|
|
SetEPV2_1,
|
|
SetEPV2_2,
|
|
SetTVEnable_1,
|
|
SetTVEnable_2,
|
|
SetTVPressMode_1,
|
|
SetTVPressMode_2,
|
|
SetTV_1,
|
|
SetTV_2,
|
|
WaitTV_1,
|
|
WaitTV_2,
|
|
SetM2toM40,
|
|
SetTVCloseMode_1,
|
|
SetTVCloseMode_2,
|
|
CloseTV_1,
|
|
CloseTV_2,
|
|
SetMfcFlow_1,
|
|
SetMfcFlow_2,
|
|
|
|
SetPressure1,
|
|
SetPressure2,
|
|
SetPressure3,
|
|
SetPressure4,
|
|
|
|
SetMaintainPressure1,
|
|
SetMaintainPressure2,
|
|
|
|
CalStandardMfc,
|
|
CalTestMfc,
|
|
|
|
CalBasePressure1,
|
|
CalBasePressure2,
|
|
}
|
|
|
|
private ModuleName moduleName;
|
|
|
|
private PMModule _pmModule;
|
|
|
|
private MfcRorData _mfcData;
|
|
|
|
private Stopwatch _swTimer = new Stopwatch();
|
|
|
|
|
|
//摩尔气体常数
|
|
private const double R = 8.314;
|
|
|
|
//气体摩尔体积
|
|
private const double Vm = 22.414;
|
|
|
|
private IoThrottleValve2 _IoThrottle;
|
|
|
|
private int _IoValueTimeout = 10;
|
|
|
|
private double _pressureMaxDiff;
|
|
|
|
private int _throttleTimeout;
|
|
|
|
private double _ventBasePressure;
|
|
|
|
private double _pumpBasePressure;
|
|
|
|
private bool _flag;
|
|
|
|
private string _startTime;
|
|
|
|
private string _endTime;
|
|
|
|
public PMMfcRorRoutine(ModuleName module, PMModule pm) : base(module, pm)
|
|
{
|
|
moduleName = module;
|
|
_pmModule = pm;
|
|
Name = "MfcRor";
|
|
|
|
_IoThrottle = DEVICE.GetDevice<IoThrottleValve2>($"{Module}.TV");
|
|
}
|
|
|
|
public override Result Start(params object[] objs)
|
|
{
|
|
Reset();
|
|
|
|
_mfcData = (MfcRorData)objs[0];
|
|
|
|
_pressureMaxDiff = SC.GetValue<double>($"PM.{Module}.ThrottlePressureMaxDiff");
|
|
_throttleTimeout = SC.GetValue<int>($"PM.{Module}.ThrottlePressureTimeout");
|
|
|
|
_startTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.fff");
|
|
_swTimer.Restart();
|
|
Notify($"Start {_mfcData.Name} ROR");
|
|
return Result.RUN;
|
|
}
|
|
|
|
public override Result Monitor()
|
|
{
|
|
try
|
|
{
|
|
//CheckRoutineTimeOut();
|
|
|
|
CalBasePressure((int)RoutineStep.CalBasePressure1);
|
|
if (_flag)
|
|
{
|
|
//打开EPV2
|
|
SetIoValueByGroup((int)RoutineStep.SetEPV2_1, IoGroupName.EPV2, true, _IoValueTimeout);
|
|
|
|
//设置蝶阀Enable
|
|
SetThrottleEnableAndWait((int)RoutineStep.SetTVEnable_1, _IoThrottle, 5);
|
|
|
|
//设置蝶阀为压力模式
|
|
SetThrottleToPressModeAndWait((int)RoutineStep.SetTVPressMode_1, _IoThrottle, 5);
|
|
|
|
//伺服压力设定值到0mbar
|
|
SetThrottlePressureAndWaitSetPoint((int)RoutineStep.SetTV_1, _IoThrottle, _pumpBasePressure, _pressureMaxDiff, _throttleTimeout);
|
|
|
|
//等待腔体压力Pump到设定值
|
|
WaitChamberPressDownTo((int)RoutineStep.WaitTV_1, _pumpBasePressure, _pressureMaxDiff, _throttleTimeout);
|
|
}
|
|
|
|
//关闭蝶阀,再关闭EPV2
|
|
SetThrottleToCloseMode((int)RoutineStep.SetTVCloseMode_1, _IoThrottle, 8);
|
|
SetThrottleDisable((int)RoutineStep.CloseTV_1, _IoThrottle, 8);
|
|
TimeDelay((int)RoutineStep.TimeDelay1, 1);
|
|
SetIoValueByGroup((int)RoutineStep.SetEPV2_2, IoGroupName.EPV2, false, _IoValueTimeout);
|
|
TimeDelay((int)RoutineStep.TimeDelay2, 3);
|
|
|
|
if (_mfcData.IsStandardMfc)
|
|
{
|
|
//记录第一次保压值
|
|
TimeDelay((int)RoutineStep.TimeDelay3, _mfcData.Interval);
|
|
SetRorMaintainPressure((int)RoutineStep.SetMaintainPressure1, 1);
|
|
|
|
//记录第二次保压值
|
|
TimeDelay((int)RoutineStep.TimeDelay4, _mfcData.Interval);
|
|
SetRorMaintainPressure((int)RoutineStep.SetMaintainPressure2, 2);
|
|
}
|
|
|
|
//设定MFC流量
|
|
SetMfcFlow((int)RoutineStep.SetMfcFlow_1, _mfcData.Name, _mfcData.SetFlow, 3);
|
|
TimeDelay((int)RoutineStep.TimeDelay5, 3);
|
|
|
|
//记录第一次压力值
|
|
TimeDelay((int)RoutineStep.TimeDelay6, _mfcData.Interval);
|
|
SetRorPressure((int)RoutineStep.SetPressure1, 1);
|
|
|
|
//记录第二次压力值
|
|
TimeDelay((int)RoutineStep.TimeDelay7, _mfcData.Interval);
|
|
SetRorPressure((int)RoutineStep.SetPressure2, 2);
|
|
|
|
//记录第三次压力值
|
|
TimeDelay((int)RoutineStep.TimeDelay8, _mfcData.Interval);
|
|
SetRorPressure((int)RoutineStep.SetPressure3, 3);
|
|
|
|
//记录第四次压力值
|
|
TimeDelay((int)RoutineStep.TimeDelay9, _mfcData.Interval);
|
|
SetRorPressure((int)RoutineStep.SetPressure4, 4);
|
|
|
|
//设定MFC流量
|
|
SetMfcFlow((int)RoutineStep.SetMfcFlow_2, _mfcData.Name, 0, 3);
|
|
|
|
CalBasePressure((int)RoutineStep.CalBasePressure2);
|
|
if (_flag)
|
|
{
|
|
//打开EPV2
|
|
SetIoValueByGroup((int)RoutineStep.SetEPV2_2, IoGroupName.EPV2, true, _IoValueTimeout);
|
|
|
|
//设置蝶阀Enable
|
|
SetThrottleEnableAndWait((int)RoutineStep.SetTVEnable_2, _IoThrottle, 5);
|
|
|
|
//设置蝶阀为压力模式
|
|
SetThrottleToPressModeAndWait((int)RoutineStep.SetTVPressMode_2, _IoThrottle, 5);
|
|
|
|
//伺服压力设定值到0mbar
|
|
SetThrottlePressureAndWaitSetPoint((int)RoutineStep.SetTV_2, _IoThrottle, _pumpBasePressure, _pressureMaxDiff, _throttleTimeout);
|
|
|
|
//等待腔体压力Pump到设定值
|
|
WaitChamberPressDownTo((int)RoutineStep.WaitTV_2, _pumpBasePressure, _pressureMaxDiff, _throttleTimeout);
|
|
}
|
|
|
|
//计算
|
|
if(_mfcData.IsStandardMfc)
|
|
{
|
|
CalStandardMfc((int)RoutineStep.CalStandardMfc);
|
|
}
|
|
else
|
|
{
|
|
CalTestMfc((int)RoutineStep.CalTestMfc);
|
|
}
|
|
}
|
|
catch (RoutineBreakException)
|
|
{
|
|
return Result.RUN;
|
|
}
|
|
catch (RoutineFaildException)
|
|
{
|
|
return Result.FAIL;
|
|
}
|
|
|
|
_swTimer.Stop();
|
|
|
|
return Result.DONE;
|
|
}
|
|
|
|
private void CalBasePressure(int id)
|
|
{
|
|
Tuple<bool, Result> ret = Execute(id, () =>
|
|
{
|
|
_flag = _pmModule.GetChamberPressure() > _mfcData.BasePressure;
|
|
|
|
return true;
|
|
});
|
|
if (ret.Item1)
|
|
{
|
|
if (ret.Item2 == Result.FAIL)
|
|
{
|
|
throw (new RoutineFaildException());
|
|
}
|
|
else
|
|
throw (new RoutineBreakException());
|
|
}
|
|
}
|
|
|
|
//计算标准MFC,求得反应腔压力
|
|
private void CalStandardMfc(int id)
|
|
{
|
|
Tuple<bool, Result> ret = Execute(id, () =>
|
|
{
|
|
if (_mfcData.MeanDifferencePressure - _mfcData.MaintainPressureDifference > 0)
|
|
{
|
|
_mfcData.Volume = 100000 * (_mfcData.SetFlow * 0.001 / Vm * R * _mfcData.Temperature) /
|
|
((_mfcData.MeanDifferencePressure - _mfcData.MaintainPressureDifference) / (_mfcData.Interval / 60.0) / 0.01);
|
|
|
|
//保留2位小数
|
|
_mfcData.Volume = Math.Round(_mfcData.Volume, 2);
|
|
|
|
_endTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
|
|
|
|
//数据保存至数据库
|
|
string sql = string.Format($"insert into \"pm_mfcror\"(\"starttime\",\"endtime\",\"name\",\"module\",\"scale\",\"pressure1\",\"pressure2\",\"pressure3\",\"pressure4\",\"actualflow\",\"setflow\",\"temperature\",\"interval\",\"isstandardmfc\",\"maintainpressure1\",\"maintainpressure2\",\"maintainpressuredifference\",\"volume\",\"meandifferencepressure\",\"basepressure\") values('{_startTime}','{_endTime}','{_mfcData.Name}','{_mfcData.Module}','{_mfcData.Scale}','{_mfcData.Pressure1}','{_mfcData.Pressure2}','{_mfcData.Pressure3}','{_mfcData.Pressure4}','{_mfcData.ActualFlow}','{_mfcData.SetFlow}','{_mfcData.Temperature}','{_mfcData.Interval}','{_mfcData.IsStandardMfc}','{_mfcData.MaintainPressure1}','{_mfcData.MaintainPressure2}','{_mfcData.MaintainPressureDifference}','{_mfcData.Volume}','{_mfcData.MeanDifferencePressure}','{_mfcData.BasePressure}')");
|
|
|
|
List<string> cmdList = new List<string>() { sql };
|
|
if(DB.ExcuteTransAction(cmdList))
|
|
{
|
|
Notify($"{_mfcData.Name} ROR Finished! Chamber Volume is {_mfcData.Volume};Elapsed time: {(int)(_swTimer.ElapsedMilliseconds / 1000)} s");
|
|
}
|
|
else
|
|
{
|
|
EV.PostWarningLog(Module, $"{_mfcData.Name} ROR Failed! Elapsed time: {(int)(_swTimer.ElapsedMilliseconds / 1000)} s");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
EV.PostWarningLog(Module, $"{_mfcData.Name} ROR Failed! Elapsed time: {(int)(_swTimer.ElapsedMilliseconds / 1000)} s");
|
|
}
|
|
|
|
return true;
|
|
});
|
|
if (ret.Item1)
|
|
{
|
|
if (ret.Item2 == Result.FAIL)
|
|
{
|
|
throw (new RoutineFaildException());
|
|
}
|
|
else
|
|
throw (new RoutineBreakException());
|
|
}
|
|
}
|
|
|
|
//计算测试MFC,求得实际流量
|
|
private void CalTestMfc(int id)
|
|
{
|
|
Tuple<bool, Result> ret = Execute(id, () =>
|
|
{
|
|
if (_mfcData.SetFlow != 0)
|
|
{
|
|
_mfcData.ActualFlow = ((_mfcData.MeanDifferencePressure - _mfcData.MaintainPressureDifference) / (0.01 * (_mfcData.Interval / 60.0))) * (_mfcData.Volume / 100000.0 / (R * _mfcData.Temperature)) * Vm;
|
|
|
|
_mfcData.Deviation = (_mfcData.ActualFlow / _mfcData.SetFlow - 1) * 100;
|
|
//保留2位小数
|
|
_mfcData.Volume = Math.Round(_mfcData.Volume, 2);
|
|
|
|
_endTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
|
|
|
|
//数据保存至数据库
|
|
string sql = string.Format($"insert into \"pm_mfcror\"(\"starttime\",\"endtime\",\"name\",\"module\",\"scale\",\"pressure1\",\"pressure2\",\"pressure3\",\"pressure4\",\"actualflow\",\"setflow\",\"temperature\",\"interval\",\"isstandardmfc\",\"maintainpressure1\",\"maintainpressure2\",\"maintainpressuredifference\",\"volume\",\"meandifferencepressure\",\"basepressure\",\"deviation\") values('{_startTime}','{_endTime}','{_mfcData.Name}','{_mfcData.Module}','{_mfcData.Scale}','{_mfcData.Pressure1}','{_mfcData.Pressure2}','{_mfcData.Pressure3}','{_mfcData.Pressure4}','{_mfcData.ActualFlow}','{_mfcData.SetFlow}','{_mfcData.Temperature}','{_mfcData.Interval}','{_mfcData.IsStandardMfc}','{_mfcData.MaintainPressure1}','{_mfcData.MaintainPressure2}','{_mfcData.MaintainPressureDifference}','{_mfcData.Volume}','{_mfcData.MeanDifferencePressure}','{_mfcData.BasePressure}','{_mfcData.Deviation}')");
|
|
|
|
List<string> cmdList = new List<string>() { sql };
|
|
if (DB.ExcuteTransAction(cmdList))
|
|
{
|
|
Notify($"{_mfcData.Name} ROR Finished! {_mfcData.Name} Deviation is {_mfcData.Deviation}%;Elapsed time: {(int)(_swTimer.ElapsedMilliseconds / 1000)} s");
|
|
}
|
|
else
|
|
{
|
|
EV.PostWarningLog(Module, $"{_mfcData.Name} ROR Failed! Elapsed time: {(int)(_swTimer.ElapsedMilliseconds / 1000)} s");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
EV.PostWarningLog(Module, $"{_mfcData.Name} ROR Failed! Elapsed time: {(int)(_swTimer.ElapsedMilliseconds / 1000)} s");
|
|
}
|
|
|
|
return true;
|
|
});
|
|
if (ret.Item1)
|
|
{
|
|
if (ret.Item2 == Result.FAIL)
|
|
{
|
|
throw (new RoutineFaildException());
|
|
}
|
|
else
|
|
throw (new RoutineBreakException());
|
|
}
|
|
}
|
|
|
|
//设定压力
|
|
private void SetRorPressure(int id,int index)
|
|
{
|
|
Tuple<bool, Result> ret = Execute(id, () =>
|
|
{
|
|
switch (index)
|
|
{
|
|
case 1:
|
|
{
|
|
_mfcData.Pressure1 = _pmModule.GetChamberPressure();
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
{
|
|
_mfcData.Pressure2 = _pmModule.GetChamberPressure();
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
{
|
|
_mfcData.Pressure3 = _pmModule.GetChamberPressure();
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
{
|
|
_mfcData.Pressure4 = _pmModule.GetChamberPressure();
|
|
|
|
_mfcData.MeanDifferencePressure = (_mfcData.Pressure4 - _mfcData.Pressure1) / 3.0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
});
|
|
if (ret.Item1)
|
|
{
|
|
if (ret.Item2 == Result.FAIL)
|
|
{
|
|
throw (new RoutineFaildException());
|
|
}
|
|
else
|
|
throw (new RoutineBreakException());
|
|
}
|
|
}
|
|
|
|
//设定保压压力
|
|
private void SetRorMaintainPressure(int id, int index)
|
|
{
|
|
Tuple<bool, Result> ret = Execute(id, () =>
|
|
{
|
|
switch (index)
|
|
{
|
|
case 1:
|
|
{
|
|
_mfcData.MaintainPressure1 = _pmModule.GetChamberPressure();
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
{
|
|
_mfcData.MaintainPressure2 = _pmModule.GetChamberPressure();
|
|
|
|
_mfcData.MaintainPressureDifference = _mfcData.MaintainPressure2 - _mfcData.MaintainPressure1;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
});
|
|
if (ret.Item1)
|
|
{
|
|
if (ret.Item2 == Result.FAIL)
|
|
{
|
|
throw (new RoutineFaildException());
|
|
}
|
|
else
|
|
throw (new RoutineBreakException());
|
|
}
|
|
}
|
|
|
|
public override void Abort()
|
|
{
|
|
base.Abort();
|
|
}
|
|
|
|
//private void CheckRoutineTimeOut()
|
|
//{
|
|
// if (_routineTimeOut > 10)
|
|
// {
|
|
// if ((int)(_swTimer.ElapsedMilliseconds / 1000) > _routineTimeOut)
|
|
// {
|
|
// EV.PostAlarmLog(Module,$"Routine TimeOut! over {_routineTimeOut} s");
|
|
// throw (new RoutineFaildException());
|
|
// }
|
|
// }
|
|
//}
|
|
}
|
|
}
|