Browse Source

Process module and Interlock .

sangwq 2 years ago
parent
commit
3222fa143a

+ 1 - 1
Venus/Framework/RTCore/IoProviders/Mitsubishis/MCProtocolPlc.cs

@@ -232,7 +232,7 @@ namespace MECF.Framework.RT.Core.IoProviders
                 bool doN2 = data[10];
                 if(doN2 == false)
                 {
-                    Console.WriteLine($"DO_N2 = {doN2}");
+                    //Console.WriteLine($"DO_N2 = {doN2}");
                 }
             }
 

+ 2 - 3
Venus/Venus_Core/Recipe.cs

@@ -235,10 +235,9 @@ namespace Venus_Core
 
         private Stopwatch _stepTimer = new Stopwatch();
 
-        [JsonIgnore]
-        public long ElapsedTime
+        public long ElapsedTime()
         {
-            get { return _stepTimer.ElapsedMilliseconds; }
+            return _stepTimer.ElapsedMilliseconds; 
         }
 
         public RState Start()

BIN
Venus/Venus_RT/Config/DeviceModelVenus.xml


BIN
Venus/Venus_RT/Config/Interlock.Venus.xml


+ 1 - 1
Venus/Venus_RT/Config/System.sccfg

@@ -152,7 +152,7 @@
 			<!--<config default="false" name="ChillerSameWithPMB" nameView="Chiller Same With PMB" description="enable chiller same with PMB or not" max="1" min="0" tag="" unit="" type="Bool" />-->
 			<config default="1" name="MFG" nameView="MFG" description="厂商, 1:SMC;" max="10" min="0" paramter="" tag="" unit="" type="Integer" />
 			<config default="1" name="CommunicationType" nameView="Communication Type" description="0:Analogue; 1:RS232; 2:Ethernet" max="10" min="0" paramter="" tag="" unit="" type="Integer" />
-			<config default="COM12" name="Port" nameView="Port" description="serial port name of pump" max="" min="" paramter="" tag="" unit="" type="String" />
+			<config default="COM44" name="Port" nameView="Port" description="serial port name of pump" max="" min="" paramter="" tag="" unit="" type="String" />
 			<config default="10" name="ChillerTemperatureOffset" nameView="Chiller Temperature Offset" description="" max="100" min="0" paramter="" tag="" unit="degree" type="Double" />
 			<config default="300" name="SetPointLimitMax" nameView="Chiller Set Point Limit Max" description="" max="500" min="0" paramter="" tag="" unit="degree" type="Double" />
 			<config default="0" name="SetPointLimitMin" nameView="Chiller Set Point Limit Min" description="" max="500" min="0" paramter="" tag="" unit="degree" type="Double" />

+ 1 - 1
Venus/Venus_RT/Config/_ioDefineVenus.xml

@@ -57,7 +57,7 @@
 		<DI_ITEM Index="50" Name="DI_Loadlock_ATM_SW" Device="" Addr="w23.02" />
 		<DI_ITEM Index="51" Name="DI_Gas_Box_Door_SW" Device="" Addr="w23.03"  Note="1=normal, 0=alarm, Interlock-PLC" />
 		<DI_ITEM Index="52" Name="DI_Gas_Box_Pressure_SW" Device="" Addr="w23.04"  Note="1=normal, 0=alarm, Interlock-PLC" />
-		<DI_ITEM Index="53" Name="" />
+		<DI_ITEM Index="53" Name="DI_Turbo_Pump_Water_Flow_Switch" Device="" Addr="w23.5" Note="0=off, 1=on"/>
 		<DI_ITEM Index="54" Name="" />
 		<DI_ITEM Index="55" Name="" />
 		<DI_ITEM Index="56" Name="" />

+ 8 - 0
Venus/Venus_RT/Devices/AdTecRF.cs

@@ -10,6 +10,7 @@ using Aitex.Core.RT.OperationCenter;
 using Aitex.Core.RT.SCCore;
 using Aitex.Core.RT.Tolerance;
 using Aitex.Core.Util;
+using Aitex.Core.RT.Device;
 using MECF.Framework.Common.Communications;
 using MECF.Framework.Common.DataCenter;
 using MECF.Framework.Common.Device.Bases;
@@ -473,6 +474,13 @@ namespace Venus_RT.Devices
         {
             if (!(this.ControlMode == EnumRfPowerControlMode.RS232Mode)) SetCommunicationMode(1);
             str = "";
+
+            var _chamber = DEVICE.GetDevice<JetPM>(Module);
+            if (on && !_chamber.CheckGeneratorAndHVInterlock(VenusDevice.Rf))
+            {
+                return false;
+            }
+
             if (on)
             {
                 SendCmd(AdTecRfMessage.RF_ON);

+ 23 - 43
Venus/Venus_RT/Devices/AdixenTurboPump.cs

@@ -211,7 +211,6 @@ namespace Venus_RT.Devices
                 if(_queCommands.IsEmpty)
                 {
                     _sendCommand(Operation.GetIntervalParametersState);
-                    _lastCommand = Operation.GetIntervalParametersState;
                 }
                 else
                 {
@@ -223,10 +222,10 @@ namespace Venus_RT.Devices
                     }
                 }
             }
-            else if(_queryWatch.ElapsedMilliseconds >= _timeout)
+            else if(_queryWatch.ElapsedMilliseconds > _timeout)
             {
-                _noRepeatAlarm($"last command: {_lastCommand} timeout");
-                Reset();
+                _serial.ClearPortBuffer();
+                _lastCommand = Operation.Invalid;
             }
         }
 
@@ -254,9 +253,9 @@ namespace Venus_RT.Devices
         {
             try
             {
+                _lastCommand = Operation.Invalid;
                 if (obj.Substring(0, 2) == "OK")
                 {
-                    _lastCommand = Operation.Invalid;
                     return;
                 }
 
@@ -271,49 +270,24 @@ namespace Venus_RT.Devices
                         _noRepeatAlarm($"Adixen Turbo Pump unknown communication error: {obj}");
                     }
 
-                    _lastCommand = Operation.Invalid;
-                    return;
-                }
-
-                if(_lastCommand == Operation.Invalid)
-                {
-                    LOG.Write(eEvent.ERR_TURBO_PUMP, Module, $"Adixen Turbo Pump unexpected communication data: {obj}");
                     return;
                 }
 
                 var result_data = obj.Trim().Split(',');
-                switch(_lastCommand)
+                if (result_data.Length >= 9)
                 {
-                    case Operation.GetCurrentSpeed:
-                        if(result_data.Length >= 2)
-                        {
-                            var str_speed = result_data[1].Split();
-                            int speed = 0;
-                            if (int.TryParse(str_speed[0], out speed))
-                            {
-                                Speed = speed;
-                            }
-                        }
-                        break;
-                    case Operation.GetIntervalParametersState:
-                        if(result_data.Length >= 9)
-                        {
-                            int speed = 0;
-                            int temp = 0;
-                            if(int.TryParse(result_data[0], out speed))
-                            {
-                                Speed = speed;
-                            }
-
-                            if(int.TryParse(result_data[8], out temp))
-                            {
-                                Temperature = temp;
-                            }
-                        }
-                        break;
-                }
+                    int speed = 0;
+                    int temp = 0;
+                    if (int.TryParse(result_data[0], out speed))
+                    {
+                        Speed = speed;
+                    }
 
-                _lastCommand = Operation.Invalid;
+                    if (int.TryParse(result_data[8], out temp))
+                    {
+                        Temperature = temp;
+                    }
+                }
 
             }
             catch (Exception ex)
@@ -330,7 +304,7 @@ namespace Venus_RT.Devices
                 if(obj[i] == (byte)'#')
                 {
                     int nOffset = 5;
-                    if(_lastCommand == Operation.GetIntervalParametersState && obj.Length - i >= _internal_parameters_length)
+                    if(obj.Length - i >= _internal_parameters_length)
                     {
                         _pumpStatus = obj[i + 6];
                         _valveStatus = obj[i + 7];
@@ -355,6 +329,12 @@ namespace Venus_RT.Devices
 
         public override void SetPumpOnOff(bool on)
         {
+            var _chamber = DEVICE.GetDevice<JetPM>(Module);
+            if (on && !_chamber.TurboPumpInterlock)
+            {
+                LOG.Write(eEvent.ERR_TURBO_PUMP, Module, "Cannot Run Turbo Pump for Turbo Pump Interlock(DI-9) is off.");
+                return ;
+            }
             _queCommands.Enqueue(on ? Operation.StartPumpRotation : Operation.StopPump);
         }
 

+ 7 - 0
Venus/Venus_RT/Devices/CometRF.cs

@@ -15,6 +15,7 @@ using Aitex.Core.RT.OperationCenter;
 using Aitex.Core.RT.SCCore;
 using Aitex.Core.RT.Tolerance;
 using Aitex.Core.Util;
+using Aitex.Core.RT.Device;
 using Aitex.Sorter.Common;
 using MECF.Framework.Common.Communications;
 using MECF.Framework.Common.DataCenter;
@@ -895,6 +896,12 @@ namespace Venus_RT.Devices
         public override bool SetPowerOnOff(bool on, out string str)
         {
             str = "";
+            var _chamber = DEVICE.GetDevice<JetPM>(Module);
+            if (on && !_chamber.CheckGeneratorAndHVInterlock(VenusDevice.Rf))
+            {
+                return false;
+            }
+
             _isPowerOn = on;
             SendCmd(Mode.Write, CometRFCommand.Command, on ? 1 : 0);
             return true;

+ 11 - 0
Venus/Venus_RT/Devices/ESC5HighVoltage.cs

@@ -263,5 +263,16 @@ namespace Venus_RT.Devices
         {
             return SendCommand(Operation.SetCurrentLimit, limit);
         }
+
+        public bool SetPowerOnOff(bool on)
+        {
+            var _chamber = DEVICE.GetDevice<JetPM>(Module);
+            if (on && !_chamber.CheckGeneratorAndHVInterlock(VenusDevice.Rf))
+            {
+                return false;
+            }
+
+            return SendCommand(on ? Operation.EnableOutputVoltage : Operation.DisableOutputVoltage);
+        }
     }
 }

+ 14 - 2
Venus/Venus_RT/Devices/IODevices/IoBacksideHe.cs

@@ -18,6 +18,8 @@ namespace Venus_RT.Devices
         private readonly IoValve _DownValve;
         private AOAccessor _aoPressure;
         private AOAccessor _aoCtrlMode;
+        private eEvent _lastEvent;
+        private string _lastLogInfo;
 
         public int MinFlowThreshold { get; set;}
         public int MaxFlowThreshold { get; set; }
@@ -46,12 +48,12 @@ namespace Venus_RT.Devices
             if(MinFlowThreshold > 0 && _mfc.FeedBack <= MinFlowThreshold)
             {
                 OutOfRange = true;
-                LOG.Write(eEvent.ERR_BACKSIDE_HE, Module, $"Backside Helium Flow: {_mfc.FeedBack} exceed min threshold value: {MinFlowThreshold}");
+                _noRepeatLog(eEvent.WARN_BACKSIDE_HE, $"Backside Helium Flow: {_mfc.FeedBack} exceed min threshold value: {MinFlowThreshold}");
             }
             else if(MaxFlowThreshold > 0 && _mfc.FeedBack >= MaxFlowThreshold)
             {
                 OutOfRange = true;
-                LOG.Write(eEvent.ERR_BACKSIDE_HE, Module, $"Backside Helium Flow: {_mfc.FeedBack} exceed max threshold value: {MaxFlowThreshold}");
+                _noRepeatLog(eEvent.WARN_BACKSIDE_HE, $"Backside Helium Flow: {_mfc.FeedBack} exceed max threshold value: {MaxFlowThreshold}");
             }
             else
             {
@@ -104,5 +106,15 @@ namespace Venus_RT.Devices
         {
             _SetRealFloat(_aoCtrlMode, bPressureMode ? 1 : 0);
         }
+
+        private void _noRepeatLog(eEvent evt, string logInfo)
+        {
+            if(evt != _lastEvent || logInfo != _lastLogInfo)
+            {
+                LOG.Write(evt, Module, logInfo);
+                _lastEvent = evt;
+                _lastLogInfo = logInfo;
+            }
+        }
     }
 }

+ 70 - 9
Venus/Venus_RT/Devices/JetPM.cs

@@ -4,6 +4,7 @@ using Aitex.Core.RT.Device.Unit;
 using Aitex.Core.RT.Event;
 using Aitex.Core.RT.SCCore;
 using Aitex.RT.Device.Custom;
+using Aitex.Core.RT.Log;
 using MECF.Framework.Common.Device.Bases;
 using MECF.Framework.Common.Equipment;
 using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs;
@@ -90,7 +91,12 @@ namespace Venus_RT.Devices
         private readonly IoSensor _N2Pressure_sw;
         private readonly IoSensor _VAC_sw;
         private readonly IoSensor _WLK_sw;
+        private readonly IoSensor _Water_Flow;
         private readonly IoSensor _RFG_Interlock;
+        private readonly IoSensor _PM_Lid_Closed;
+        private readonly IoSensor _Source_RF_Fan;
+        private readonly IoSensor _PM_SlitDoor_Closed;
+        private readonly IoSensor _TurboPumpInterlock;
 
         private readonly PumpBase _MainPump;
         private readonly ESC5HighVoltage _ESCHV;
@@ -143,9 +149,15 @@ namespace Venus_RT.Devices
         public bool IsATMLoadlock => _ATM_Loadlock_sw.Value;
         public bool IsVACLoadLock => LoadlockPressure <= 1000;
         public bool IsVAC => _VAC_sw.Value;
+        public bool IsWaterFlowOk => _Water_Flow.Value;
         public bool IsWLK => _WLK_sw.Value;
         public bool IsRFGInterlockOn => _RFG_Interlock.Value;
 
+        public bool PMLidClosed => _PM_Lid_Closed.Value;
+        public bool TurboPumpInterlock => _TurboPumpInterlock.Value;
+        public bool SourceRFFanInterlock => _Source_RF_Fan.Value;
+        public bool SlitDoorClosed => _PM_SlitDoor_Closed.Value;
+
         public double ProcessPressure => _pressureController.ProcessGauge.Value;
         public override double ChamberPressure => _pressureController.PressureGauge.Value;
         public double ForelinePressure => _pressureController.ForelineGauge.Value;
@@ -277,15 +289,21 @@ namespace Venus_RT.Devices
             _LoadlockVentValve = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveLoadlockVent}");
             _LoadlockPumpingValve = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveLoadlockPumping}");
 
-            _ATM_sw = DEVICE.GetDevice<IoSensor>($"{Module}.SensorATMSwitch");
-            _ATM_Loadlock_sw = DEVICE.GetDevice<IoSensor>($"{Module}.SensorLoadlockATMSwitch");
-            _N2Pressure_sw = DEVICE.GetDevice<IoSensor>($"{Module}.N2PressureOk");
-            _VAC_sw = DEVICE.GetDevice<IoSensor>($"{Module}.SensorVacSwitch");
-            _WLK_sw = DEVICE.GetDevice<IoSensor>($"{Module}.SensorWaterLeakOk");
-            _CDAPressure = DEVICE.GetDevice<IoSensor>($"{Module}.SensorCDAPressureOk");
-            _RFG_Interlock = DEVICE.GetDevice<IoSensor>($"{Module}.GeneratorInterlock");
+            _ATM_sw                 = DEVICE.GetDevice<IoSensor>($"{Module}.SensorATMSwitch");
+            _ATM_Loadlock_sw        = DEVICE.GetDevice<IoSensor>($"{Module}.SensorLoadlockATMSwitch");
+            _N2Pressure_sw          = DEVICE.GetDevice<IoSensor>($"{Module}.N2PressureOk");
+            _VAC_sw                 = DEVICE.GetDevice<IoSensor>($"{Module}.SensorVacSwitch");
+            _Water_Flow             = DEVICE.GetDevice<IoSensor>($"{Module}.SensorWaterFlowOk");
+            _WLK_sw                 = DEVICE.GetDevice<IoSensor>($"{Module}.SensorWaterLeakOk");
+            _CDAPressure            = DEVICE.GetDevice<IoSensor>($"{Module}.SensorCDAPressureOk");
+            _RFG_Interlock          = DEVICE.GetDevice<IoSensor>($"{Module}.GeneratorInterlock");
 
-            _ForelineTC = DEVICE.GetDevice<IoHeater>($"{Module}.ForelineHeater");
+            _PM_Lid_Closed          = DEVICE.GetDevice<IoSensor>($"{Module}.SensorPMLidClosed");
+            _Source_RF_Fan          = DEVICE.GetDevice<IoSensor>($"{Module}.SensorSourceRFFan");
+            _PM_SlitDoor_Closed     = DEVICE.GetDevice<IoSensor>($"{Module}.SensorSlitDoorClosed");
+            _TurboPumpInterlock     = DEVICE.GetDevice<IoSensor>($"{Module}.TurboPumpInterlock");
+
+        _ForelineTC = DEVICE.GetDevice<IoHeater>($"{Module}.ForelineHeater");
 
             _SignalTower = DEVICE.GetDevice<IoSignalTower>($"{Module}.SignalTower");
 
@@ -610,7 +628,7 @@ namespace Venus_RT.Devices
 
         public bool CheckChillerStatus()
         {
-            return _Chiller != null && _Chiller.IsRunning && !_Chiller.IsError;
+            return _Chiller != null /*&& _Chiller.IsRunning*/ && !_Chiller.IsError;
         }
 
 
@@ -714,6 +732,49 @@ namespace Venus_RT.Devices
             return _ESCHV.SetOutputVoltage(nVoltage);
         }
 
+        public bool CheckGeneratorAndHVInterlock(VenusDevice device)
+        {
+            eEvent evt = device == VenusDevice.Rf ? eEvent.ERR_RF : eEvent.ERR_ESC_HV;
+            string deviceName = device == VenusDevice.Rf ? "RF Generator" : "ESC HV";
+            if (!PMLidClosed)
+            {
+                LOG.Write(evt, Module, $"Cannot Power ON {deviceName} as PM Lid is Open.");
+                return false;
+            }
+
+            if (!IsVAC)
+            {
+                LOG.Write(evt, Module, $"Cannot Power ON {deviceName} as PM is not Vacuum.");
+                return false;
+            }
+
+            if(!IsWaterFlowOk)
+            {
+                LOG.Write(evt, Module, $"Cannot Power ON {deviceName} as Water Flow is OFF.");
+                return false;
+            }
+
+            if(!IsRFGInterlockOn)
+            {
+                LOG.Write(evt, Module, $"Cannot Power ON {deviceName} as Generator Interlock is OFF.");
+                return false;
+            }
+
+            if(!SourceRFFanInterlock)
+            {
+                LOG.Write(evt, Module, $"Cannot Power ON {deviceName} as Source RF Fan is OFF.");
+                return false;
+            }
+
+            if(!SlitDoorClosed)
+            {
+                LOG.Write(evt, Module, $"Cannot Power ON {deviceName} as Slit Door is open.");
+                return false;
+            }
+
+            return true;
+        }
+
 
 
         #region EndPoint

+ 1 - 0
Venus/Venus_RT/Devices/PendulumValve.cs

@@ -244,6 +244,7 @@ namespace Venus_RT.Devices
                     case "C":
                     case "O":
                     case "H":
+                    case "S":
                         break;
                     case "E":
                         {

+ 32 - 0
Venus/Venus_RT/Modules/PMs/PMEntity.cs

@@ -121,6 +121,7 @@ namespace Venus_RT.Modules.PMs
         private readonly GasBoxLeakCheckRoutine     _gasBoxLeakCheckRoutine;
         private readonly LLPlaceRoutine             _llPlaceRoutine;
         private readonly LLPickRoutine              _llPickRoutine;
+        private readonly PMProcessRoutine           _processRoutine;
 
         public bool IsIdle
         {
@@ -201,6 +202,7 @@ namespace Venus_RT.Modules.PMs
             _gasBoxLeakCheckRoutine = new GasBoxLeakCheckRoutine(_chamber);
             _llPlaceRoutine         = new LLPlaceRoutine(_chamber);
             _llPickRoutine          = new LLPickRoutine(_chamber, _ventLoadLockRoutine);
+            _processRoutine         = new PMProcessRoutine(_chamber, _pumpRoutine);
 
             fsm                     = new StateMachine<PMEntity>(Module.ToString(), (int)PMState.Init, 50);
 
@@ -298,6 +300,11 @@ namespace Venus_RT.Modules.PMs
             Transition(PMState.LLPicking,       FSM_MSG.TIMER,      FnLLPickTimeout,            PMState.Idle);
             Transition(PMState.LLPicking,       MSG.Abort,          FnAbortLLPick,              PMState.Idle);
 
+            // Process
+            Transition(PMState.Idle,            MSG.RunRecipe,      FnRunRecipe,                PMState.Processing);
+            Transition(PMState.Processing,      FSM_MSG.TIMER,      FnProcessTimeout,           PMState.Idle);
+            Transition(PMState.Processing,      MSG.Abort,          FnAbortProcess,             PMState.Idle);
+
             Running = true;
         }
 
@@ -706,6 +713,27 @@ namespace Venus_RT.Modules.PMs
             return true;
         }
 
+        private bool FnRunRecipe(object[] param)
+        {
+            return _processRoutine.Start(param) == RState.Running;
+        }
+        private bool FnProcessTimeout(object[] param)
+        {
+            RState ret = _processRoutine.Monitor();
+            if (ret == RState.Failed || ret == RState.Timeout)
+            {
+                PostMsg(MSG.Error);
+                return false;
+            }
+
+            return ret == RState.End;
+        }
+        private bool FnAbortProcess(object[] param)
+        {
+            _processRoutine.Abort();
+            return true;
+        }
+
         private void _debugRoutine()
         {
             int flag = 0;
@@ -770,6 +798,10 @@ namespace Venus_RT.Modules.PMs
             {
                 PostMsg(MSG.LLPick);
             }
+            else if(flag == 16)
+            {
+                PostMsg(MSG.RunRecipe, "7777");
+            }
         }
     }
 }

+ 55 - 10
Venus/Venus_RT/Modules/PMs/PMProcessRoutine.cs

@@ -2,9 +2,11 @@
 using System.Collections.Generic;
 using Aitex.Core.RT.Routine;
 using Aitex.Core.RT.SCCore;
+using Aitex.Common.Util;
+using Aitex.Core.RT.RecipeCenter;
 using Venus_RT.Devices;
 using MECF.Framework.Common.SubstrateTrackings;
-using System.Text.Json;
+
 using Venus_Core;
 namespace Venus_RT.Modules.PMs
 {
@@ -26,6 +28,7 @@ namespace Venus_RT.Modules.PMs
         public DateTime RecipeStartTime { get; private set; }
 
         private readonly PumpDownRoutine _pumpDownRoutine;
+        private readonly ProcessHelper _processHelper;
         private bool _withWafer = true;
         private bool _needPumpDown = false;
         private Recipe _currentRecipe = null;
@@ -82,6 +85,28 @@ namespace Venus_RT.Modules.PMs
         {
             Name = "Process";
             _pumpDownRoutine = pdRoutine;
+            _processHelper = new ProcessHelper(chamber);
+        }
+
+        private bool AssignFuns(Recipe recipe)
+        {
+            foreach(var step in recipe.Steps)
+            {
+                if (ProcessHelper.LoadStepFuns(step) == false)
+                    return false;
+
+                foreach(ProcessUnitBase unit in step.LstUnit)
+                {
+                    if (ProcessHelper.LoadMethods(unit) == false)
+                    {
+                        Stop($"Cannot find the process routine for unit:{unit.GetType()}");
+                        return false;
+                    }
+                        
+                }
+            }
+
+            return true;
         }
 
         public RState Start(params object[] objs)
@@ -100,27 +125,47 @@ namespace Venus_RT.Modules.PMs
             // Load/Validate Recipe
             _qeRecipes.Clear();
             string recipeName = (string)objs[0];
-            Recipe recipe = Recipe.Load(recipeName);
+            string recipeContent = RecipeFileManager.Instance.LoadRecipe(_chamber.Name, recipeName, false);
+            Recipe recipe = Recipe.Load(recipeContent);
             if(recipe == null)
             {
+                Stop($"Load Recipe:{recipeName} failed");
+                return RState.Failed;
+            }
+
+            if (AssignFuns(recipe) == false)
+            {
+                Stop($"Associate process alogrithm with recipe:{recipeName} failed");
                 return RState.Failed;
             }
+
             switch(recipe.Header.Type)
             {
                 case RecipeType.Process:
-                    var chuckRecipe = Recipe.Load(recipe.Header.ChuckRecipe);
-                    var dechuckRecipe = Recipe.Load(recipe.Header.DechuckRecipe);
-                    if(chuckRecipe == null || dechuckRecipe == null)
+                   if(recipe.Header.ChuckRecipe != null)
                     {
-                        return RState.Failed;
+                        var chuckRecipe = Recipe.Load(recipe.Header.ChuckRecipe);
+                        if(chuckRecipe != null)
+                        {
+                            ChuckRecipeName = recipe.Header.ChuckRecipe;
+                            _qeRecipes.Enqueue(chuckRecipe);
+                        }
                     }
 
+                    ProcessRecipeHead = recipe.Header;
                     ProcessRecipeName = recipeName;
-                    ChuckRecipeName = recipe.Header.ChuckRecipe;
-                    DechuckRecipeNamae = recipe.Header.DechuckRecipe;
-                    _qeRecipes.Enqueue(chuckRecipe);
                     _qeRecipes.Enqueue(recipe);
-                    _qeRecipes.Enqueue(dechuckRecipe);
+
+                    if(recipe.Header.DechuckRecipe != null)
+                    {
+                        var dechuckRecipe = Recipe.Load(recipe.Header.DechuckRecipe);
+                        if(dechuckRecipe != null)
+                        {
+                            DechuckRecipeNamae = recipe.Header.DechuckRecipe;
+                            _qeRecipes.Enqueue(dechuckRecipe);
+                        }
+                    }
+
                     break;
                 case RecipeType.Chuck:
                     ChuckRecipeName = recipeName;

+ 21 - 21
Venus/Venus_RT/Modules/PMs/ProcessDefine.cs

@@ -14,10 +14,10 @@ namespace Venus_RT.Modules.PMs
     {
         static protected JetPM Chamber;
 
-        private Dictionary<string, Func<ProcessUnitBase, RecipeStep, RState>> startHelper = new Dictionary<string, Func<ProcessUnitBase, RecipeStep, RState>>
+        private static Dictionary<string, Func<ProcessUnitBase, RecipeStep, RState>> startHelper = new Dictionary<string, Func<ProcessUnitBase, RecipeStep, RState>>
         {
-            {"PressureUnitByPressureMode",  PressureUnitByPressureMode_Start},
-            {"PressureUnitByValveMode",     PressureUnitByValveMode_Start},
+            {"PressureByPressureModeUnit",  PressureByPressureModeUnit_Start},
+            {"PressureByValveModeUnit",     PressureByValveModeUnit_Start},
             {"TCPUnit",                     TCPUnit_Start},
             {"BiasUnit",                    BiasUnit_Start},
             {"GasControlUnit",              GasControlUnit_Start },
@@ -25,10 +25,10 @@ namespace Venus_RT.Modules.PMs
             {"ProcessKitUnit",              ProcessKitUnit_Start },
         };
 
-        private Dictionary<string, Func<ProcessUnitBase, RecipeStep, RState>> checkerHelper = new Dictionary<string, Func<ProcessUnitBase, RecipeStep, RState>>
+        private static Dictionary<string, Func<ProcessUnitBase, RecipeStep, RState>> checkerHelper = new Dictionary<string, Func<ProcessUnitBase, RecipeStep, RState>>
         {
-            {"PressureUnitByPressureMode",  PressureUnitByPressureMode_Check},
-            {"PressureUnitByValveMode",     PressureUnitByValveMode_Check},
+            {"PressureByPressureModeUnit",  PressureByPressureModeUnit_Check},
+            {"PressureByValveModeUnit",     PressureByValveModeUnit_Check},
             {"TCPUnit",                     TCPUnit_Check},
             {"BiasUnit",                    BiasUnit_Check},
             {"GasControlUnit",              GasControlUnit_Check},
@@ -37,10 +37,10 @@ namespace Venus_RT.Modules.PMs
 
         };
 
-        private Dictionary<string, Action<ProcessUnitBase, RecipeStep>> endHelper = new Dictionary<string, Action<ProcessUnitBase, RecipeStep>>
+        private static Dictionary<string, Action<ProcessUnitBase, RecipeStep>> endHelper = new Dictionary<string, Action<ProcessUnitBase, RecipeStep>>
         {
-            {"PressureUnitByPressureMode",  PressureUnitByPressureMode_End},
-            {"PressureUnitByValveMode",     PressureUnitByValveMode_End},
+            {"PressureByPressureModeUnit",  PressureByPressureModeUnit_End},
+            {"PressureByValveModeUnit",     PressureByValveModeUnit_End},
             {"TCPUnit",                     TCPUnit_End},
             {"BiasUnit",                    BiasUnit_End},
             {"GasControlUnit",              GasControlUnit_End},
@@ -54,7 +54,7 @@ namespace Venus_RT.Modules.PMs
             Chamber = pm;
         }
 
-        static private RState PressureUnitByPressureMode_Start(ProcessUnitBase unit, RecipeStep step)
+        static private RState PressureByPressureModeUnit_Start(ProcessUnitBase unit, RecipeStep step)
         {
             var ProcessUnit = unit as PressureByPressureModeUnit;
             if (Chamber.SetPVPressure(ProcessUnit.StartPressure))
@@ -65,7 +65,7 @@ namespace Venus_RT.Modules.PMs
             return RState.Failed;
         }
 
-        static private RState PressureUnitByPressureMode_Check(ProcessUnitBase unit, RecipeStep step)
+        static private RState PressureByPressureModeUnit_Check(ProcessUnitBase unit, RecipeStep step)
         {
             var ProcessUnit = unit as PressureByPressureModeUnit;
             if(ProcessUnit.EnableRamp)
@@ -84,12 +84,12 @@ namespace Venus_RT.Modules.PMs
             return RState.Running;
         }
 
-        static private void PressureUnitByPressureMode_End(ProcessUnitBase unit, RecipeStep step)
+        static private void PressureByPressureModeUnit_End(ProcessUnitBase unit, RecipeStep step)
         {
 
         }
 
-        static private RState PressureUnitByValveMode_Start(ProcessUnitBase unit, RecipeStep step)
+        static private RState PressureByValveModeUnit_Start(ProcessUnitBase unit, RecipeStep step)
         {
             var ProcessUnit = unit as PressureByValveModeUnit;
             if(Chamber.SetPVPostion(ProcessUnit.StartPosition))
@@ -100,7 +100,7 @@ namespace Venus_RT.Modules.PMs
             return RState.Failed;
         }
 
-        static private RState PressureUnitByValveMode_Check(ProcessUnitBase unit, RecipeStep step)
+        static private RState PressureByValveModeUnit_Check(ProcessUnitBase unit, RecipeStep step)
         {
             var ProcessUnit = unit as PressureByValveModeUnit;
             if(ProcessUnit.EnableRamp)
@@ -114,7 +114,7 @@ namespace Venus_RT.Modules.PMs
             return RState.Running;
         }
 
-        static private void PressureUnitByValveMode_End(ProcessUnitBase unit, RecipeStep step)
+        static private void PressureByValveModeUnit_End(ProcessUnitBase unit, RecipeStep step)
         {
 
         }
@@ -136,7 +136,7 @@ namespace Venus_RT.Modules.PMs
                 return RState.Failed;
             }
 
-            if(step.ElapsedTime > ProcessUnit.HoldTime * 1000)
+            if(step.ElapsedTime() > ProcessUnit.HoldTime * 1000)
             {
                 Chamber.GeneratorSetpower(0);
                 Chamber.GeneratorPowerOn(false);
@@ -174,7 +174,7 @@ namespace Venus_RT.Modules.PMs
                 return RState.Failed;
             }
 
-            if (step.ElapsedTime > ProcessUnit.BiasRFHoldTime * 1000)
+            if (step.ElapsedTime() > ProcessUnit.BiasRFHoldTime * 1000)
             {
                 Chamber.GeneratorBiasSetpower(0);
                 Chamber.GeneratorBiasPowerOn(false);
@@ -246,7 +246,7 @@ namespace Venus_RT.Modules.PMs
         {
             if(Chamber.BackSideHeOutOfRange)
             {
-                return RState.Failed;
+                //return RState.Failed;
             }
 
             return RState.Running;
@@ -275,7 +275,7 @@ namespace Venus_RT.Modules.PMs
         {
         }
 
-        public bool LoadMethods(ProcessUnitBase unit)
+        public static bool LoadMethods(ProcessUnitBase unit)
         {
             var className = unit.GetType().Name;
             if(startHelper.ContainsKey(className) && checkerHelper.ContainsKey(className))
@@ -300,7 +300,7 @@ namespace Venus_RT.Modules.PMs
             switch(step.Type)
             {
                 case StepType.Time:
-                    return step.ElapsedTime > step.Time ? RState.End : RState.Running;
+                    return step.ElapsedTime() > step.Time * 1000 ? RState.End : RState.Running;
                 case StepType.EndPoint:
                     return Chamber.CheckEndPoint() ? RState.End : RState.Running;
             }
@@ -308,7 +308,7 @@ namespace Venus_RT.Modules.PMs
             return RState.Running;
         }
 
-        public bool LoadStepFuns(RecipeStep step)
+        public static bool LoadStepFuns(RecipeStep step)
         {
             step.starter = stepStarter;
             step.checker = stepChecker;

+ 10 - 7
Venus/Venus_RT/Modules/PMs/StartTurboPumpRoutine.cs

@@ -9,12 +9,12 @@ namespace Venus_RT.Modules.PMs
     {
         private enum TurboPumpStep
         {
-            kCheckForeLine,
+            kStart,
             kEnd,
         }
 
-        private double _chamberForelinePressureThreshold = 500;
-        private int _chamberForelinePressureTimeout;
+        private readonly int FORELINE_PRESSURE_THRESHOLD = 500;
+        private readonly int START_TURBO_PUMP_TIMEOUT = 30000;
 
 
         public StartTurboPumpRoutine(JetPM chamber) : base(chamber)
@@ -30,13 +30,16 @@ namespace Venus_RT.Modules.PMs
                 return RState.Failed;
             }
 
+            if(_chamber.ForelinePressure >= FORELINE_PRESSURE_THRESHOLD)
+            {
+                Stop($"Foreline:{_chamber.ForelinePressure} 压力太高, 不能启动 Turbo Pump");
+                return RState.Failed;
+            }
+
             Reset();
             _chamber.OpenValve(ValveType.FastPump, false);
             _chamber.OpenValve(ValveType.SoftPump, false);
 
-            _chamberForelinePressureThreshold = SC.GetValue<double>($"{Module}.TurboPump.ChamberForelinePressureThreshold");
-            _chamberForelinePressureTimeout = SC.GetValue<int>($"{Module}.TurboPump.ChamberForelinePressureTimeout");
-
             _chamber.TurnTurboPump(true);
 
             return Runner.Start(Module, Name);
@@ -44,7 +47,7 @@ namespace Venus_RT.Modules.PMs
 
         public RState Monitor()
         {
-            Runner.Wait((int)TurboPumpStep.kCheckForeLine, () => { return _chamber.ForelinePressure < _chamberForelinePressureThreshold; }, _chamberForelinePressureTimeout)
+            Runner.Wait((int)TurboPumpStep.kStart, () => { return _chamber.IsTurboPumpRunning; }, START_TURBO_PUMP_TIMEOUT)
                 .End((int)TurboPumpStep.kEnd, NullFun, _delay_50ms);
 
             return Runner.Status;

+ 1 - 0
Venus/Venus_Simulator/App.xaml.cs

@@ -16,6 +16,7 @@ namespace Venus_Simulator
             UiApplication.Instance.Initialize(new UiInstance());
 
             SimulatorSystem.Instance.Initialize();
+            SystemConfig.Instance.Initialize();
         }
 
         protected override void OnExit(ExitEventArgs e)

+ 28 - 24
Venus/Venus_Simulator/Devices/AdTecGeneratorMockPMA.cs

@@ -37,36 +37,40 @@ namespace Venus_Simulator.Devices
                 message = message.Remove(message.Length - 1);
             }
 
-            switch (message)
+            string[] msgs = message.Split('\r');
+            foreach(string msg in msgs)
             {
-            case "Q":
-                if (_simGeneratorStatus == GeneratorStatus.ON)
+                switch (msg)
                 {
-                    sRes = "2010000 12345 00900 00100 45678\r";
+                    case "Q":
+                        if (_simGeneratorStatus == GeneratorStatus.ON)
+                        {
+                            sRes = "2010000 12345 00900 00100 45678\r";
+                        }
+                        else if (_simGeneratorStatus == GeneratorStatus.OFF)
+                        {
+                            sRes = "2000000 12345 00000 00000 45678\r";
+                        }
+                        break;
+                    case "G":
+                        _simGeneratorStatus = GeneratorStatus.ON;
+                        sRes = "\r";
+                        break;
+                    case "S":
+                        _simGeneratorStatus = GeneratorStatus.OFF;
+                        sRes = "\r";
+                        break;
+                    default:
+                        break;
                 }
-                else if (_simGeneratorStatus == GeneratorStatus.OFF)
-                {
-                    sRes = "2000000 12345 00000 00000 45678\r";
-                }
-                break;
-            case "G":
-                _simGeneratorStatus = GeneratorStatus.ON;
-                sRes = "\r";
-                break;
-            case "S":
-                _simGeneratorStatus = GeneratorStatus.OFF;
-                sRes = "\r";
-                break;
-                default:
-                break;
-            }
 
-            //string[] strs = message.Split(MSG_DELIMITER);
+                //string[] strs = message.Split(MSG_DELIMITER);
 
-            //Thread.Sleep(2 * 1000);
+                //Thread.Sleep(2 * 1000);
 
-            sRes += "\r";
-            OnWriteMessage(sRes);
+                sRes += "\r";
+                OnWriteMessage(sRes);
+            }
         }
     }
 }

+ 40 - 1
Venus/Venus_Simulator/Devices/SMCChillerMockPMB.cs

@@ -1,7 +1,12 @@
 using System;
 using System.Threading;
 using MECF.Framework.Simulator.Core.Driver;
-
+using Venus_Simulator.Instances;
+using Aitex.Core.RT.SCCore;
+using MECF.Framework.Common.SCCore;
+using MECF.Framework.Common.DataCenter;
+using Aitex.Core.Util;
+using System.IO;
 namespace Venus_Simulator.Devices
 {
     class SMCChillerMock : SerialPortDeviceSimulator
@@ -27,7 +32,41 @@ namespace Venus_Simulator.Devices
             if (string.IsNullOrEmpty(message))
                 throw new ArgumentException("Hardware command message is invalid");
 
+            string[] separatingStrings = { EOF };
+            string[] msgs = message.Trim().Split(separatingStrings, System.StringSplitOptions.RemoveEmptyEntries);
+            foreach (var msg in msgs)
+            {
+                if(msg.StartsWith(":0106000B"))
+                {
+                    int temp = Convert.ToInt32(msg.Substring(9, 8), 16);
+                    Console.WriteLine($"Chiller Set Temp: {temp}");
+                    SetTemp(temp);
+                }
+                else if(msg.StartsWith(":0106000C0001"))
+                {
+                    _simPumpStatus = SMCChillerStatus.Open;
+                }
+                else if(msg.StartsWith(":0106000C0000"))
+                {
+                    _simPumpStatus = SMCChillerStatus.Close;
+                }
+            }
             
         }
+
+        void SetTemp(int temp)
+        {
+            //Singleton<SystemConfigManager>.Instance.Initialize(PathManager.GetCfgDir() + "System.sccfg");
+
+            
+
+
+            string module = PortName == "COM43" ? "PMA" : "PMB";
+            //double _OffsetTemp = SC.GetValue<double>($"{module}.Chiller.ChillerTemperatureOffset");
+            double _OffsetTemp = SystemConfig.Instance.GetValue<double>($"{module}.Chiller.ChillerTemperatureOffset");
+
+            //double offset = (double)QueryDataClient.Instance.Service.GetConfig($"{module}.Chiller.ChillerTemperatureOffset");
+            SimulatorSystem.Instance.SetCoolantOutletTemp(module, temp / 10 + (int)_OffsetTemp);
+        }
     }
 }

+ 34 - 27
Venus/Venus_Simulator/Devices/TurboPumpMockPMA.cs

@@ -57,40 +57,47 @@ namespace Venus_Simulator.Devices
             if (string.IsNullOrEmpty(message))
                 throw new ArgumentException("Hardware command message is invalid");
 
-            string sRes = string.Empty;
-            string str = message.Trim();
-            if (str.Contains("STA"))
+            string[] strs = message.Trim().Split('\r');
+            foreach(string msg in strs)
             {
-                if(_simTurboPumpStatus == TurboPumpStatus.ON)
+                string sRes = string.Empty;
+                string str = msg.Trim();
+                if (str.Length == 0)
+                    continue;
+
+                if (str.Contains("STA"))
                 {
-                    _speed = 200;
+                    if (_simTurboPumpStatus == TurboPumpStatus.ON)
+                    {
+                        _speed = 200;
+                    }
+                    else
+                    {
+                        _speed = 0;
+                    }
+                    string strData = string.Format("#000,000,{0:D5},000,000,000,000,000,00,00000,{1:D3},099,0123456789012345678901234\r", _speed + _rd.Next(0, 5), _temperature + _rd.Next(-5, 5));
+                    byte[] byteArray = System.Text.Encoding.Default.GetBytes(strData);
+                    byteArray[6] = pumpStatus;
+                    byteArray[7] = valveStatus;
+
+                    OnWriteMessage(byteArray);
+                    return;
                 }
-                else
+                else if (str.Contains("TMPON"))
                 {
-                    _speed = 0;
+                    sRes = "#000,OK\r";
+                    _simTurboPumpStatus = TurboPumpStatus.ON;
                 }
-                string strData = string.Format("#000,000,{0:D5},000,000,000,000,000,00,00000,{1:D3},099,0123456789012345678901234\r", _speed + _rd.Next(0, 5), _temperature + _rd.Next(-5, 5));
-                byte[] byteArray = System.Text.Encoding.Default.GetBytes(strData);
-                byteArray[6] = pumpStatus;
-                byteArray[7] = valveStatus;
+                else if (str.Contains("TMPOFF"))
+                {
+                    sRes = "#000,OK\r";
+                    _simTurboPumpStatus = TurboPumpStatus.OFF;
+                }
+                else
+                    return;
 
-                OnWriteMessage(byteArray);
-                return;
+                OnWriteMessage(sRes);
             }
-            else if (str.Contains("TMPON"))
-            {
-                sRes = "#000,OK\r";
-                _simTurboPumpStatus = TurboPumpStatus.ON;
-            }
-            else if (str.Contains("TMPOFF"))
-            {
-                sRes = "#000,OK\r";
-                _simTurboPumpStatus = TurboPumpStatus.OFF;
-            }
-            else
-                return;
-
-            OnWriteMessage(sRes);
         }
     }
 }

+ 7 - 0
Venus/Venus_Simulator/Instances/SimulatorSystem.cs

@@ -686,5 +686,12 @@ namespace Venus_Simulator.Instances
         {
             _thread.Stop();
         }
+
+        ////////////////////////////////////////////////////////////////////////
+        ////////////////////////////////////////////////////////////////////////
+        public void SetCoolantOutletTemp(string module, int Temp)
+        {
+            SetAiValue($"{module}.AI_Coolant_Outlet_Temp", Temp);
+        }
     }
 }

+ 193 - 0
Venus/Venus_Simulator/Instances/SystemConfig.cs

@@ -0,0 +1,193 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Xml;
+using Aitex.Core.Util;
+using Aitex.Core.RT.SCCore;
+namespace Venus_Simulator.Instances
+{
+    
+    public class SystemConfig : Singleton<SystemConfig>
+    {
+        private Dictionary<string, SCConfigItem> _items = new Dictionary<string, SCConfigItem>();
+        public void Initialize()
+        {
+            var processs = System.Diagnostics.Process.GetProcessesByName("Venus_RT");
+            if(processs.Length > 0)
+            {
+                var venus_path = processs[0].MainModule.FileName;
+                var venus_dir = Path.GetDirectoryName(venus_path);
+                if (venus_dir != null)
+                {
+                    string config_path = $"{venus_dir}\\Config\\_sc.data";
+                    string system_cfg = $"{venus_dir}\\Config\\System.sccfg";
+                    if(File.Exists(system_cfg))
+                    {
+                        BuildItems(system_cfg);
+
+                        if (File.Exists(config_path))
+                        {
+                            XmlDocument xmlData = new XmlDocument();
+                            xmlData.Load(config_path);
+
+                            XmlNodeList scdatas = xmlData.SelectNodes("root/scdata");
+                            foreach (XmlElement nodedata in scdatas)
+                            {
+                                string name = nodedata.GetAttribute("name");
+                                if (_items.ContainsKey(name))
+                                {
+                                    InitializeItemValue(_items[name], nodedata.GetAttribute("value"));
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        private bool InitializeItemValue(SCConfigItem item, string value)
+        {
+            bool changed = false;
+            switch (item.Type)
+            {
+                case "Bool":
+                    bool boolValue;
+                    if (bool.TryParse(value, out boolValue) && boolValue != item.BoolValue)
+                    {
+                        item.BoolValue = boolValue;
+                        changed = true;
+                    }
+                    break;
+                case "Integer":
+                    int intValue;
+                    if (int.TryParse(value, out intValue) && intValue != item.IntValue)
+                    {
+
+                        int.TryParse(item.Min, out int min);
+                        int.TryParse(item.Max, out int max);
+
+                        if (intValue < min || intValue > max)
+                        {
+                            //EV.PostWarningLog(ModuleNameString.System, $"SC {item.PathName} value  {intValue} out of setting range ({item.Min}, {item.Max})");
+                            break;
+                        }
+                        item.IntValue = intValue;
+                        changed = true;
+                    }
+                    break;
+                case "Double":
+                    double doubleValue;
+                    if (double.TryParse(value, out doubleValue) && Math.Abs(doubleValue - item.DoubleValue) > 0.0001)
+                    {
+                        double.TryParse(item.Min, out double min);
+                        double.TryParse(item.Max, out double max);
+                        if (doubleValue < min || doubleValue > max)
+                        {
+                            //EV.PostWarningLog(ModuleNameString.System, $"SC {item.PathName}  value  {doubleValue} out of setting range ({item.Min}, {item.Max})");
+                            break;
+                        }
+                        item.DoubleValue = doubleValue;
+                        changed = true;
+                    }
+                    break;
+                case "String":
+                    if (value != item.StringValue)
+                    {
+                        item.StringValue = value;
+                        changed = true;
+                    }
+                    break;
+            }
+
+            return changed;
+        }
+
+        public T GetValue<T>(string name) where T : struct
+        {
+            try
+            {
+                if (typeof(T) == typeof(bool))
+                    return (T)(object)_items[name].BoolValue;
+                if (typeof(T) == typeof(int))
+                    return (T)(object)_items[name].IntValue;
+                if (typeof(T) == typeof(double))
+                    return (T)(object)_items[name].DoubleValue;
+            }
+            catch (KeyNotFoundException)
+            {
+
+                return default(T);
+            }
+            catch (Exception)
+            {
+
+                return default(T);
+            }
+
+            return default(T);
+        }
+
+        private void BuildItems(string xmlFile)
+        {
+            XmlDocument xml = new XmlDocument();
+
+            try
+            {
+                xml.Load(xmlFile);
+
+                XmlNodeList nodeConfigs = xml.SelectNodes("root/configs");
+                foreach (XmlElement nodeConfig in nodeConfigs)
+                {
+                    BuildPathConfigs(nodeConfig.GetAttribute("name"), nodeConfig as XmlElement);
+                }
+            }
+            catch (Exception ex)
+            {
+                //LOG.Write(ex);
+            }
+        }
+
+        private void BuildPathConfigs(string parentPath, XmlElement configElement)
+        {
+            XmlNodeList nodeConfigsList = configElement.SelectNodes("configs");
+            foreach (XmlElement nodeConfig in nodeConfigsList)
+            {
+                if (string.IsNullOrEmpty(parentPath))
+                {
+                    BuildPathConfigs(nodeConfig.GetAttribute("name"), nodeConfig as XmlElement);
+                }
+                else
+                {
+                    BuildPathConfigs(parentPath + "." + nodeConfig.GetAttribute("name"), nodeConfig as XmlElement);
+                }
+            }
+
+            XmlNodeList nodeConfigs = configElement.SelectNodes("config");
+            foreach (XmlElement nodeConfig in nodeConfigs)
+            {
+                SCConfigItem item = new SCConfigItem()
+                {
+                    Default = nodeConfig.GetAttribute("default"),
+
+                    Name = nodeConfig.GetAttribute("name"),
+                    Description = nodeConfig.GetAttribute("description"),
+                    Max = nodeConfig.GetAttribute("max"),
+                    Min = nodeConfig.GetAttribute("min"),
+                    Parameter = nodeConfig.GetAttribute("paramter"),
+                    Path = parentPath,
+                    Tag = nodeConfig.GetAttribute("tag"),
+                    Type = nodeConfig.GetAttribute("type"),
+                    Unit = nodeConfig.GetAttribute("unit"),
+                };
+                InitializeItemValue(item, item.Default);
+
+                if (_items.ContainsKey(item.PathName))
+                {
+                    //LOG.Error("Duplicated SC item, "+ item.PathName);
+                }
+
+                _items[item.PathName] = item;
+            }
+        }
+    }
+}

+ 1 - 0
Venus/Venus_Simulator/Venus_Simulator.csproj

@@ -81,6 +81,7 @@
     <Compile Include="Devices\ESCHVMockPMA.cs" />
     <Compile Include="Devices\PendulumValveMockPMA.cs" />
     <Compile Include="Devices\TurboPumpMockPMA.cs" />
+    <Compile Include="Instances\SystemConfig.cs" />
     <Compile Include="Views\Converters\CassetteConverter.cs" />
     <Compile Include="Views\Converters\IoConvert.cs" />
     <Compile Include="Views\IoViewModelBase.cs" />