964 lines
35 KiB
C#
964 lines
35 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 Aitex.Core.RT.DBCore;
|
|
using Aitex.Core.Common.DeviceData;
|
|
using Aitex.Common.Util;
|
|
using Aitex.Core.RT.Log;
|
|
using System.Xml;
|
|
using System.Collections.ObjectModel;
|
|
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts.TDK;
|
|
using Aitex.Core.RT.OperationCenter;
|
|
using Aitex.Core.UI.Control;
|
|
using System.Xml.Linq;
|
|
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.MFCs;
|
|
using MECF.Framework.Common.Device.Bases;
|
|
using MECF.Framework.Common.DBCore;
|
|
using System.Data;
|
|
using System.Reflection;
|
|
using System.Linq;
|
|
using MECF.Framework.Common.Aitex.Core.Common.DeviceData.IoDevice;
|
|
using Newtonsoft.Json;
|
|
using Aitex.Core.RT.DataCenter;
|
|
|
|
namespace SicModules.PMs.Routines
|
|
{
|
|
public class MfcRorAction
|
|
{
|
|
public string Name { get; set; }
|
|
|
|
public string Value { get; set; }
|
|
}
|
|
|
|
public class PMMfcRorRoutine : PMBaseRoutine
|
|
{
|
|
private enum RoutineStep
|
|
{
|
|
TimeDelay1,
|
|
TimeDelay2,
|
|
TimeDelay3,
|
|
TimeDelay4,
|
|
TimeDelay5,
|
|
TimeDelay6,
|
|
TimeDelay7,
|
|
TimeDelay8,
|
|
TimeDelay9,
|
|
TimeDelay10,
|
|
|
|
SetEPV2_1,
|
|
SetEPV2_2,
|
|
SetEPV2_3,
|
|
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,
|
|
PreSetMfcFlow,
|
|
SetMfcFlow_1,
|
|
SetMfcFlow_2,
|
|
SetMfcFlow_3,
|
|
PostSetMfcFlow,
|
|
|
|
SetPressure1,
|
|
SetPressure2,
|
|
SetPressure3,
|
|
SetPressure4,
|
|
|
|
SetMaintainPressure1,
|
|
SetMaintainPressure2,
|
|
|
|
CalStandardMfc,
|
|
CalTestMfc,
|
|
|
|
CalBasePressure1,
|
|
CalBasePressure2,
|
|
}
|
|
|
|
private ModuleName moduleName;
|
|
|
|
private PMModule _pmModule;
|
|
|
|
private MfcRorData _mfcData;
|
|
|
|
private Stopwatch _swTimer = new Stopwatch();
|
|
|
|
//Mfc Name列表
|
|
public List<string> MfcNameList { get; set; } = new List<string>();
|
|
|
|
//标准Mfc
|
|
public MfcRorData StandardMfcRorData { get; set; }
|
|
|
|
public List<MfcRorData> MfcRorList { get; set; } = new List<MfcRorData>();
|
|
|
|
//摩尔气体常数
|
|
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 _flag1;
|
|
|
|
private bool _flag2;
|
|
|
|
private string _startTime;
|
|
|
|
private string _endTime;
|
|
|
|
private string _mfcRorConfigPath = PathManager.GetCfgDir() + @"PM\MfcRor\MfcRor.xml";
|
|
|
|
private Dictionary<string, List<MfcRorAction>> _preActionList = new Dictionary<string, List<MfcRorAction>>();
|
|
|
|
private Dictionary<string, List<MfcRorAction>> _postActionList = new Dictionary<string, List<MfcRorAction>>();
|
|
|
|
public PMMfcRorRoutine(ModuleName module, PMModule pm) : base(module, pm)
|
|
{
|
|
moduleName = module;
|
|
_pmModule = pm;
|
|
Name = "MfcRor";
|
|
|
|
_IoThrottle = DEVICE.GetDevice<IoThrottleValve2>($"{Module}.TV");
|
|
|
|
InitializeXml();
|
|
|
|
InitializeMfcRorList();
|
|
|
|
InitStandardMfc();
|
|
}
|
|
|
|
private void InitializeXml()
|
|
{
|
|
string reason = string.Empty;
|
|
try
|
|
{
|
|
XmlDocument xmlDocument = new XmlDocument();
|
|
xmlDocument.Load(_mfcRorConfigPath);
|
|
XmlNode xmlNode = xmlDocument.SelectSingleNode("Items");
|
|
|
|
foreach (XmlNode childNode in xmlNode.ChildNodes)
|
|
{
|
|
if (childNode.NodeType == XmlNodeType.Comment || !(childNode is XmlElement xmlElement))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (xmlElement.Name != "Item")
|
|
{
|
|
if (xmlElement.NodeType != XmlNodeType.Comment)
|
|
{
|
|
reason += "mfcRor config file contains no comments content, " + xmlElement.InnerXml;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (!xmlElement.HasAttribute("Name"))
|
|
{
|
|
reason += "action node has no [Name] attribute \r\n";
|
|
continue;
|
|
}
|
|
|
|
string name = xmlElement.GetAttribute("Name");
|
|
|
|
//PreAction
|
|
List<MfcRorAction> preActionList = new List<MfcRorAction>();
|
|
|
|
XmlNode xmlNode1 = childNode.SelectSingleNode("PreAction");
|
|
|
|
foreach (XmlElement childNode1 in xmlNode1.ChildNodes)
|
|
{
|
|
if (childNode1.Name != "Action")
|
|
{
|
|
if (childNode1.NodeType != XmlNodeType.Comment)
|
|
{
|
|
LOG.Error("MfcRor config file contains no comments content, " + childNode1.InnerXml);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (!childNode1.HasAttribute("Name") || !childNode1.HasAttribute("Value"))
|
|
{
|
|
reason += "MfcRor node lack of Name or Value attribute \r\n";
|
|
continue;
|
|
}
|
|
|
|
string actionName = childNode1.GetAttribute("Name");
|
|
string value = childNode1.GetAttribute("Value");
|
|
|
|
preActionList.Add(new MfcRorAction() { Name = actionName, Value = value });
|
|
}
|
|
|
|
_preActionList[name] = preActionList;
|
|
|
|
//PostAction
|
|
List<MfcRorAction> postActionList = new List<MfcRorAction>();
|
|
|
|
XmlNode xmlNode2 = childNode.SelectSingleNode("PostAction");
|
|
|
|
foreach (XmlElement childNode2 in xmlNode2.ChildNodes)
|
|
{
|
|
if (childNode2.Name != "Action")
|
|
{
|
|
if (childNode2.NodeType != XmlNodeType.Comment)
|
|
{
|
|
LOG.Error("MfcRor config file contains no comments content, " + childNode2.InnerXml);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (!childNode2.HasAttribute("Name") || !childNode2.HasAttribute("Value"))
|
|
{
|
|
reason += "MfcRor node lack of Name or Value attribute \r\n";
|
|
continue;
|
|
}
|
|
|
|
string actionName = childNode2.GetAttribute("Name");
|
|
string value = childNode2.GetAttribute("Value");
|
|
|
|
postActionList.Add(new MfcRorAction() { Name = actionName, Value = value });
|
|
}
|
|
|
|
_postActionList[name] = postActionList;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LOG.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
private void InitializeMfcRorList()
|
|
{
|
|
//初始化所有MFC
|
|
foreach (var item in _preActionList)
|
|
{
|
|
MfcNameList.Add(item.Key);
|
|
MfcRorList.Add(new MfcRorData() { Name = item.Key });
|
|
}
|
|
|
|
QueryMfcRorListData();
|
|
}
|
|
|
|
private void QueryMfcRorListData()
|
|
{
|
|
try
|
|
{
|
|
string cmd = $"select * from pm_mfcror where module = '{Module}' order by \"endtime\" ASC";
|
|
var dt = DB.ExecuteDataSet(cmd);
|
|
if (dt is null || dt.Tables[0].Rows.Count == 0)
|
|
return;
|
|
|
|
for (int i = 0; i < dt.Tables[0].Rows.Count; i++)
|
|
{
|
|
if (dt.Tables[0].Rows[i].ItemArray.Length != 0)
|
|
{
|
|
//if(bool.Parse(dt.Tables[0].Rows[i]["isstandardMfc"].ToString()))
|
|
//{
|
|
// continue;
|
|
//}
|
|
|
|
MfcRorList.ForEach(t =>
|
|
{
|
|
if (t.Name == dt.Tables[0].Rows[i]["name"].ToString())
|
|
{
|
|
t.StartTime = Convert.ToDateTime(dt.Tables[0].Rows[i]["starttime"].ToString());
|
|
t.EndTime = Convert.ToDateTime(dt.Tables[0].Rows[i]["endtime"].ToString());
|
|
t.Module = dt.Tables[0].Rows[i]["module"].ToString();
|
|
t.Pressure1 = double.Parse(dt.Tables[0].Rows[i]["pressure1"].ToString());
|
|
t.Pressure2 = double.Parse(dt.Tables[0].Rows[i]["pressure2"].ToString());
|
|
t.Pressure3 = double.Parse(dt.Tables[0].Rows[i]["pressure3"].ToString());
|
|
t.Pressure4 = double.Parse(dt.Tables[0].Rows[i]["pressure4"].ToString());
|
|
t.ActualFlow = double.Parse(dt.Tables[0].Rows[i]["actualflow"].ToString());
|
|
t.SetFlow = double.Parse(dt.Tables[0].Rows[i]["setflow"].ToString());
|
|
t.Temperature = double.Parse(dt.Tables[0].Rows[i]["temperature"].ToString());
|
|
t.Interval = double.Parse(dt.Tables[0].Rows[i]["interval"].ToString());
|
|
t.IsStandardMfc = bool.Parse(dt.Tables[0].Rows[i]["isstandardMfc"].ToString());
|
|
t.MaintainPressure1 = double.Parse(dt.Tables[0].Rows[i]["maintainpressure1"].ToString());
|
|
t.MaintainPressure2 = double.Parse(dt.Tables[0].Rows[i]["maintainpressure2"].ToString());
|
|
t.MaintainPressureDifference = double.Parse(dt.Tables[0].Rows[i]["maintainpressuredifference"].ToString());
|
|
t.Volume = double.Parse(dt.Tables[0].Rows[i]["volume"].ToString());
|
|
t.MeanDifferencePressure = double.Parse(dt.Tables[0].Rows[i]["meandifferencepressure"].ToString());
|
|
t.BasePressure = double.Parse(dt.Tables[0].Rows[i]["basepressure"].ToString());
|
|
t.Deviation = double.Parse(dt.Tables[0].Rows[i]["deviation"].ToString());
|
|
t.Result = dt.Tables[0].Rows[i]["result"].ToString();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LOG.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
public void InitStandardMfc()
|
|
{
|
|
try
|
|
{
|
|
string sql = $"select * from \"pm_mfcror\" where \"module\" = '{Module}' and \"isstandardmfc\" = 't' order by \"endtime\" DESC";
|
|
|
|
DataTable dbData = DataQuery.Query(sql);
|
|
|
|
if (dbData != null)
|
|
{
|
|
StandardMfcRorData = TableToListModel<MfcRorData>(dbData).FirstOrDefault();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LOG.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
public void ClearMfcRorData()
|
|
{
|
|
MfcRorList.Clear();
|
|
foreach (var item in _preActionList)
|
|
{
|
|
MfcRorList.Add(new MfcRorData() { Name = item.Key });
|
|
}
|
|
|
|
//DB.ExcuteTransAction(new List<string> { $"delete from pm_mfcror where \"module\" = '{Module}'" });
|
|
}
|
|
|
|
public List<T> TableToListModel<T>(DataTable dt) where T : new()
|
|
{
|
|
// 定义集合
|
|
List<T> ts = new List<T>();
|
|
|
|
// 获得此模型的类型
|
|
Type type = typeof(T);
|
|
string tempName = "";
|
|
|
|
foreach (DataRow dr in dt.Rows)
|
|
{
|
|
T t = new T();
|
|
// 获得此模型的公共属性
|
|
PropertyInfo[] propertys = t.GetType().GetProperties();
|
|
foreach (PropertyInfo pi in propertys)
|
|
{
|
|
tempName = pi.Name; // 检查DataTable是否包含此列
|
|
|
|
if (dt.Columns.Contains(tempName))
|
|
{
|
|
// 判断此属性是否有Setter
|
|
if (!pi.CanWrite) continue;
|
|
|
|
object value = dr[tempName];
|
|
if (value != DBNull.Value)
|
|
pi.SetValue(t, value, null);
|
|
}
|
|
}
|
|
ts.Add(t);
|
|
}
|
|
return ts;
|
|
}
|
|
|
|
public override Result Start(params object[] objs)
|
|
{
|
|
Reset();
|
|
|
|
_mfcData = JsonConvert.DeserializeObject<MfcRorData>(objs[0].ToString());
|
|
|
|
_pressureMaxDiff = SC.GetValue<double>($"PM.{Module}.ThrottlePressureMaxDiff");
|
|
_throttleTimeout = SC.GetValue<int>($"PM.{Module}.ThrottlePressureTimeout");
|
|
|
|
_flag1 = _pmModule.GetChamberPressure() > _mfcData.BasePressure;
|
|
|
|
_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
|
|
{
|
|
//检查是否退出
|
|
if (_pmModule.GetChamberPressure() > 980)
|
|
{
|
|
//设置对应的MFC流量为0
|
|
SetMfcFlow((int)RoutineStep.SetMfcFlow_3, _mfcData.Name, 0, 3);
|
|
|
|
TimeDelay((int)RoutineStep.TimeDelay10, 3);
|
|
|
|
EV.PostWarningLog(Module, "Chamber Pressure above 980mbar,Mfc Ror Routine Abort!");
|
|
|
|
throw (new RoutineFaildException());
|
|
}
|
|
|
|
if (_flag1)
|
|
{
|
|
//打开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流量前执行动作
|
|
PreSetMfcFlow((int)RoutineStep.PreSetMfcFlow);
|
|
|
|
//设定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流量后执行动作
|
|
PostSetMfcFlow((int)RoutineStep.PostSetMfcFlow);
|
|
|
|
CalBasePressure((int)RoutineStep.CalBasePressure2);
|
|
if (_flag2)
|
|
{
|
|
//打开EPV2
|
|
SetIoValueByGroup((int)RoutineStep.SetEPV2_3, 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 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;
|
|
_mfcData.MaintainPressureDifference = Math.Round(_mfcData.MaintainPressureDifference, 2);
|
|
}
|
|
break;
|
|
}
|
|
|
|
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;
|
|
_mfcData.MeanDifferencePressure = Math.Round(_mfcData.MeanDifferencePressure, 2);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
});
|
|
if (ret.Item1)
|
|
{
|
|
if (ret.Item2 == Result.FAIL)
|
|
{
|
|
throw (new RoutineFaildException());
|
|
}
|
|
else
|
|
throw (new RoutineBreakException());
|
|
}
|
|
}
|
|
|
|
protected void PreSetMfcFlow(int id)
|
|
{
|
|
Tuple<bool, Result> ret = Execute(id, () =>
|
|
{
|
|
if (!_preActionList.ContainsKey(_mfcData.Name))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
foreach (MfcRorAction action in _preActionList[_mfcData.Name])
|
|
{
|
|
if (action.Name.Contains("Mfc"))
|
|
{
|
|
SetMfc(action.Name, action.Value);
|
|
}
|
|
else if (action.Name.Contains("V"))
|
|
{
|
|
SetValve(action.Name, action.Value);
|
|
}
|
|
else if (action.Name.Contains("Pressure"))
|
|
{
|
|
SetPC(action.Name, action.Value);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
});
|
|
|
|
if (ret.Item1)
|
|
{
|
|
if (ret.Item2 == Result.FAIL)
|
|
{
|
|
throw (new RoutineFaildException());
|
|
}
|
|
else
|
|
throw (new RoutineBreakException());
|
|
}
|
|
}
|
|
|
|
protected void PostSetMfcFlow(int id)
|
|
{
|
|
Tuple<bool, Result> ret = Execute(id, () =>
|
|
{
|
|
if (!_postActionList.ContainsKey(_mfcData.Name))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
foreach (MfcRorAction action in _postActionList[_mfcData.Name])
|
|
{
|
|
if (action.Name.Contains("Mfc"))
|
|
{
|
|
SetMfc(action.Name, action.Value);
|
|
}
|
|
else if (action.Name.Contains("V"))
|
|
{
|
|
SetValve(action.Name, action.Value);
|
|
}
|
|
else if (action.Name.Contains("Pressure"))
|
|
{
|
|
SetPC(action.Name, action.Value);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
});
|
|
|
|
if (ret.Item1)
|
|
{
|
|
if (ret.Item2 == Result.FAIL)
|
|
{
|
|
throw (new RoutineFaildException());
|
|
}
|
|
else
|
|
throw (new RoutineBreakException());
|
|
}
|
|
}
|
|
|
|
private bool SetValve(string valveName, string value)
|
|
{
|
|
IoValve valve = DEVICE.GetDevice<IoValve>($"{Module}.{valveName}");
|
|
|
|
if (valve == null)
|
|
{
|
|
EV.PostAlarmLog(Module, $"{valveName} is null");
|
|
|
|
return false;
|
|
}
|
|
|
|
bool isOpen = value == "Open";
|
|
|
|
if (valve.TurnValve(isOpen, out string reason))
|
|
{
|
|
EV.PostInfoLog(Module, $"{valveName} Set {value} Succeed , {reason}");
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
EV.PostAlarmLog(Module, $"{valveName} Set {value} Failed");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private bool SetPC(string pcName, string value)
|
|
{
|
|
IoPressure pc = DEVICE.GetDevice<IoPressure>($"{Module}.{pcName}");
|
|
|
|
if (pc == null)
|
|
{
|
|
EV.PostAlarmLog(Module, $"{pcName} is null");
|
|
|
|
return false;
|
|
}
|
|
|
|
string reason;
|
|
|
|
if (value == "Open")
|
|
{
|
|
if (pc.SetPcMode(PcCtrlMode.Open, out reason))
|
|
{
|
|
EV.PostInfoLog(Module, $"{pcName} Set {value} Succeed");
|
|
return true;
|
|
}
|
|
}
|
|
else if (value == "Close")
|
|
{
|
|
if (pc.SetPcMode(PcCtrlMode.Close, out reason))
|
|
{
|
|
EV.PostInfoLog(Module, $"{pcName} Set {value} Succeed");
|
|
return true;
|
|
}
|
|
}
|
|
else if (value == "Default")
|
|
{
|
|
pc.Ramp(pc.DefaultValue, 3000);
|
|
|
|
EV.PostInfoLog(Module, $"{pcName} Set {value} Succeed");
|
|
|
|
return true;
|
|
}
|
|
|
|
EV.PostAlarmLog(Module, $"{pcName} Set {value} Failed");
|
|
|
|
return false;
|
|
}
|
|
|
|
private bool SetMfc(string mfcName, string value)
|
|
{
|
|
IoMFC mfc = DEVICE.GetDevice<IoMFC>($"{Module}.{mfcName}");
|
|
|
|
if (mfc == null)
|
|
{
|
|
EV.PostAlarmLog(Module, $"{mfcName} is null");
|
|
|
|
return false;
|
|
}
|
|
|
|
string reason;
|
|
|
|
if (value == "Open")
|
|
{
|
|
if (mfc.SetMfcMode(MfcCtrlMode.Open, out reason))
|
|
{
|
|
EV.PostInfoLog(Module, $"{mfcName} Set {value} Succeed");
|
|
return true;
|
|
}
|
|
}
|
|
else if (value == "Close")
|
|
{
|
|
if (mfc.SetMfcMode(MfcCtrlMode.Close, out reason))
|
|
{
|
|
EV.PostInfoLog(Module, $"{mfcName} Set {value} Succeed");
|
|
return true;
|
|
}
|
|
}
|
|
else if (value == "Default")
|
|
{
|
|
mfc.SetToDefaultByRamp(3000);
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
if (double.TryParse(value, out double dValue))
|
|
{
|
|
mfc.Ramp(dValue, 3000, out reason);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
EV.PostAlarmLog(Module, $"{mfcName} Set {value} Failed");
|
|
|
|
return false;
|
|
}
|
|
|
|
private void CalBasePressure(int id)
|
|
{
|
|
Tuple<bool, Result> ret = Execute(id, () =>
|
|
{
|
|
_flag2 = _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 = 1000000 * (_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);
|
|
_mfcData.Result = "OK";
|
|
|
|
_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\",\"result\") 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}','{_mfcData.Result}')");
|
|
|
|
List<string> cmdList = new List<string>() { sql };
|
|
if (DB.ExcuteTransAction(cmdList))
|
|
{
|
|
//设置基准MFC
|
|
StandardMfcRorData = _mfcData;
|
|
|
|
MfcRorList.ForEach(mfc =>
|
|
{
|
|
if (mfc.Name == _mfcData.Name)
|
|
{
|
|
mfc.Update(_mfcData);
|
|
}
|
|
});
|
|
|
|
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! MeanDifferencePressure Less Than MaintainPressureDifference !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 / 1000000.0 / (R * _mfcData.Temperature)) * Vm * 1000;
|
|
|
|
_mfcData.Deviation = (_mfcData.ActualFlow / _mfcData.SetFlow - 1) * 100;
|
|
//保留2位小数
|
|
_mfcData.Deviation = Math.Round(_mfcData.Deviation, 2);
|
|
_mfcData.Volume = Math.Round(_mfcData.Volume, 2);
|
|
|
|
//大于3%的MFC为超标
|
|
_mfcData.Result = Math.Abs(_mfcData.Deviation) <= 3 ? "OK" : "NG";
|
|
|
|
_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\",\"result\") 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}','{_mfcData.Result}')");
|
|
|
|
List<string> cmdList = new List<string>() { sql };
|
|
if (DB.ExcuteTransAction(cmdList))
|
|
{
|
|
MfcRorList.ForEach(mfc =>
|
|
{
|
|
if (mfc.Name == _mfcData.Name)
|
|
{
|
|
mfc.Update(_mfcData);
|
|
}
|
|
});
|
|
|
|
if (_mfcData.ActualFlow < 1)
|
|
{
|
|
EV.PostWarningLog(Module, $"{_mfcData.Name} ROR Failed!腔体平均压差为{_mfcData.MeanDifferencePressure}," +
|
|
$"压差为{_mfcData.MaintainPressureDifference},时间间隔为{_mfcData.Interval},腔体体积为{_mfcData.Volume}," +
|
|
$"设定温度为{_mfcData.Temperature}");
|
|
}
|
|
else
|
|
{
|
|
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());
|
|
}
|
|
}
|
|
|
|
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());
|
|
// }
|
|
// }
|
|
//}
|
|
}
|
|
}
|