浏览代码

add reservoir regulate pump

chenzk 4 月之前
父节点
当前提交
2b887d9e15

+ 47 - 3
CyberX8_MainPages/ViewModels/MetalSHHomePageViewModel.cs

@@ -1,5 +1,6 @@
 using Aitex.Core.Common;
 using Aitex.Core.UI.MVVM;
+using ExcelLibrary.BinaryFileFormat;
 using MECF.Framework.Common.CommonData.Metal;
 using MECF.Framework.Common.CommonData.PowerSupplier;
 using MECF.Framework.Common.DataCenter;
@@ -149,7 +150,15 @@ namespace CyberX8_MainPages.ViewModels
         /// <summary>
         /// 是否存在WaferHolder
         /// </summary>
-        private bool _isWaferHolder;
+        private bool _isWaferHolder;
+        /// <summary>
+        /// 是否为调速泵
+        /// </summary>
+        private bool _isRegulatePump;
+        /// <summary>
+        /// 泵速
+        /// </summary>
+        private int _pumpSpeed;
         #endregion
 
         #region PowerSupplier
@@ -359,6 +368,22 @@ namespace CyberX8_MainPages.ViewModels
         {
             get { return _isWaferHolder; }
             set { SetProperty(ref _isWaferHolder, value); }
+        }
+        /// <summary>
+        /// 是否为调速泵
+        /// </summary>
+        public bool IsRegulatePump
+        {
+            get { return _isRegulatePump; }
+            set { SetProperty(ref _isRegulatePump, value); }
+        }
+        /// <summary>
+        /// 泵速
+        /// </summary>
+        public int PumpSpeed
+        {
+            get { return _pumpSpeed; }
+            set { SetProperty(ref _pumpSpeed, value); }
         }
         #endregion
 
@@ -384,7 +409,8 @@ namespace CyberX8_MainPages.ViewModels
         #endregion
 
         #region Command指令
-        public ICommand InitializeCommand { get; set; }
+        public ICommand InitializeCommand { get; set; }
+        public ICommand PumpSpeedCommand { get; private set; }
         #endregion
 
         /// <summary>
@@ -393,6 +419,7 @@ namespace CyberX8_MainPages.ViewModels
         public MetalSHHomePageViewModel()
         {
             InitializeCommand = new DelegateCommand<object>(InitializeAction);
+            PumpSpeedCommand = new DelegateCommand<object>(PumpSpeedAction);
             WaferSizeList.Add((int)WaferSize.WS8);
             WaferSizeList.Add((int)WaferSize.WS12);
         }
@@ -417,6 +444,8 @@ namespace CyberX8_MainPages.ViewModels
             _rtDataKeys.Add($"{Module}.CurrentRecipe");
             _rtDataKeys.Add($"{Module}.TotalTime");
             _rtDataKeys.Add($"{Module}.TimeRemain");
+            _rtDataKeys.Add($"{Module}.IsRegulatePump");
+            _rtDataKeys.Add($"{Module}.PumpSpeed");
             if (_timer == null)
             {
                 _timer = new DispatcherTimer();
@@ -437,7 +466,10 @@ namespace CyberX8_MainPages.ViewModels
                 _rtDataValueDic = QueryDataClient.Instance.Service.PollData(_rtDataKeys);
                 if (_rtDataValueDic != null)
                 {
+                    IsRegulatePump = CommonFunction.GetValue<bool>(_rtDataValueDic, $"{Module}.IsRegulatePump");
+                    PumpSpeed = CommonFunction.GetValue<int>(_rtDataValueDic, $"{Module}.PumpSpeed");
                     MetalData = CommonFunction.GetValue<StandardHotMetalDeviceData>(_rtDataValueDic, $"{Module}.{METALDATA}");
+                    MetalData.CellPump ^= MetalData.RegulatePumpSignalIn; //用于metal4 确保metal4 pump开关正常显示
                     MetalPersistent = CommonFunction.GetValue<MetalPersistentValue>(_rtDataValueDic, $"{Module}.{PERSISTENT_VALUE}");                   
                     WaferHolderInfo = CommonFunction.GetValue<WaferHolderInfo>(_rtDataValueDic, $"{Module}.WaferHolder");
                     if (WaferHolderInfo != null)
@@ -476,7 +508,6 @@ namespace CyberX8_MainPages.ViewModels
                     {
                         ClampStatus = MetalData.WaferHolderClamp ? "Clamped" : "Unclamped";
                     }
-
                     CurrentRecipe = CommonFunction.GetValue<string>(_rtDataValueDic, $"{Module}.CurrentRecipe");
 
                     TotalTime = CommonFunction.GetValue<int>(_rtDataValueDic, $"{Module}.TotalTime");
@@ -506,6 +537,19 @@ namespace CyberX8_MainPages.ViewModels
         private void InitializeAction(object param)
         {
             InvokeClient.Instance.Service.DoOperation($"{Module}.InitializeAll");
+        }
+        /// <summary>
+        /// Initialize Action
+        /// </summary>
+        /// <param name="param"></param>
+        private void PumpSpeedAction(object obj)
+        {
+            object[] objects = (object[])obj;
+            if (objects.Length >= 2)
+            {
+                InvokeClient.Instance.Service.DoOperation($"{Module}.RegulatPumpSpeed", objects[1]);
+            }
         }
+       
     }
 }

+ 3 - 3
CyberX8_MainPages/ViewModels/PMCounterViewModel.cs

@@ -198,8 +198,8 @@ namespace CyberX8_MainPages.ViewModels
                     double ReservoirTotalAmpHoursFaultLimit = (double)Convert.ToDouble(QueryDataClient.Instance.Service.GetConfig("Reservoir.ReservoirTotalAmpHoursFaultLimit"));
                     double BathTotalAmpHoursWarningLimit = (double)Convert.ToDouble(QueryDataClient.Instance.Service.GetConfig("Reservoir.BathTotalAmpHoursWarningLimit"));
                     double BathTotalAmpHoursFaultLimit = (double)Convert.ToDouble(QueryDataClient.Instance.Service.GetConfig("Reservoir.BathTotalAmpHoursFaultLimit"));
-                    double ANBathTotalAmpHoursWarningLimit = (double)Convert.ToDouble(QueryDataClient.Instance.Service.GetConfig("Reservoir.ANBathTotalAmpHoursWarningLimit"));
-                    double ANBathTotalAmpHoursFaultLimit = (double)Convert.ToDouble(QueryDataClient.Instance.Service.GetConfig("Reservoir.ANBathTotalAmpHoursFaultLimit"));
+                    //double ANBathTotalAmpHoursWarningLimit = (double)Convert.ToDouble(QueryDataClient.Instance.Service.GetConfig("Reservoir.ANBathTotalAmpHoursWarningLimit"));
+                    //double ANBathTotalAmpHoursFaultLimit = (double)Convert.ToDouble(QueryDataClient.Instance.Service.GetConfig("Reservoir.ANBathTotalAmpHoursFaultLimit"));
                     int BathTotalDaysWarningLimit = (int)Convert.ToDouble(QueryDataClient.Instance.Service.GetConfig("Reservoir.BathTotalDaysWarningLimit"));
                     int BathTotalDaysFaultLimit = (int)Convert.ToDouble(QueryDataClient.Instance.Service.GetConfig("Reservoir.BathTotalDaysFaultLimit"));
                     double MembraneTotalAmpHoursWarningLimit = (double)Convert.ToDouble(QueryDataClient.Instance.Service.GetConfig("Reservoir.MembraneTotalAmpHoursWarningLimit"));
@@ -208,7 +208,7 @@ namespace CyberX8_MainPages.ViewModels
                     int ReservoirTotalWafersFaultLimit = (int)Convert.ToDouble(QueryDataClient.Instance.Service.GetConfig("Reservoir.ReservoirTotalWafersFaultLimit"));         
                     ReservoirPMCounterNode.Children.Add(new PMCounterCommonData { ComponentName = $"{Module}", CounterName = "Total Usage(AHr)", Value = $"{reservoirUsage.TotalUsage}", FaultLimit = $"{ReservoirTotalAmpHoursFaultLimit}", WarningLimit = $"{ReservoirTotalAmpHoursWarningLimit}" });
                     ReservoirPMCounterNode.Children.Add(new PMCounterCommonData { ComponentName = $"{Module}", CounterName = "Bath Usage(AHr)", Value = $"{reservoirUsage.BathUsage}", FaultLimit = $"{BathTotalAmpHoursFaultLimit}", WarningLimit = $"{BathTotalAmpHoursWarningLimit}" });
-                    ReservoirPMCounterNode.Children.Add(new PMCounterCommonData { ComponentName = $"{Module}", CounterName = "Anolyte Bath Usage(AHr)", Value = $"{reservoirUsage.AnodeUsage}", FaultLimit = $"{ANBathTotalAmpHoursFaultLimit}", WarningLimit = $"{ANBathTotalAmpHoursWarningLimit}" });
+                    //ReservoirPMCounterNode.Children.Add(new PMCounterCommonData { ComponentName = $"{Module}", CounterName = "Anolyte Bath Usage(AHr)", Value = $"{reservoirUsage.AnodeUsage}", FaultLimit = $"{ANBathTotalAmpHoursFaultLimit}", WarningLimit = $"{ANBathTotalAmpHoursWarningLimit}" });
                     ReservoirPMCounterNode.Children.Add(new PMCounterCommonData { ComponentName = $"{Module}", CounterName = "Bath Usage(Days)", Value = $"{reservoirUsage.BathUsageDays}", FaultLimit = $"{BathTotalDaysFaultLimit}", WarningLimit = $"{BathTotalDaysWarningLimit}" });
                     ReservoirPMCounterNode.Children.Add(new PMCounterCommonData { ComponentName = $"{Module}", CounterName = "Membrance Usage(AHr)", Value = $"{reservoirUsage.MembranceUsage}", FaultLimit = $"{MembraneTotalAmpHoursFaultLimit}", WarningLimit = $"{MembraneTotalAmpHoursWarningLimit}" });
                     ReservoirPMCounterNode.Children.Add(new PMCounterCommonData { ComponentName = $"{Module}", CounterName = "Total Wafers", Value = $"{reservoirUsage.TotalWafers}", FaultLimit = $"{ReservoirTotalWafersFaultLimit}", WarningLimit = $"{ReservoirTotalWafersWarningLimit}" });

+ 1 - 0
CyberX8_MainPages/ViewModels/StandardHotReservoirsViewModel.cs

@@ -970,6 +970,7 @@ namespace CyberX8_MainPages.ViewModels
                     for (int i = 0;i < CellsCount;i++)
                     {
                         MetalDataCollection[i] = CommonFunction.GetValue<StandardHotMetalDeviceData>(_rtDataValueDic, $"{CellModuleNameCollection[i]}.MetalData");
+                        MetalDataCollection[i].CellPump ^= MetalDataCollection[i].RegulatePumpSignalIn; //用于reservoir4 确保reservoir4 pump开关正常显示
                     }
                     ReservoirData = CommonFunction.GetValue<StandardHotReservoirData>(_rtDataValueDic, $"{Module}.ReservoirData");
                     

+ 19 - 2
CyberX8_MainPages/Views/MetalSHHomePageView.xaml

@@ -6,14 +6,16 @@
              xmlns:local="clr-namespace:CyberX8_MainPages.Views"
              xmlns:prism="http://prismlibrary.com/" 
              xmlns:converters="clr-namespace:CyberX8_Themes.Converters;assembly=CyberX8_Themes"
-             xmlns:UserControls="clr-namespace:CyberX8_Themes.UserControls;assembly=CyberX8_Themes"           
+             xmlns:UserControls="clr-namespace:CyberX8_Themes.UserControls;assembly=CyberX8_Themes"
+             xmlns:ctrls="clr-namespace:CyberX8_Themes.UserControls;assembly=CyberX8_Themes"
+             xmlns:Control="clr-namespace:MECF.Framework.UI.Core.Control;assembly=MECF.Framework.UI.Core" 
              prism:ViewModelLocator.AutoWireViewModel="True"
              mc:Ignorable="d" x:Name="self"
              d:DesignHeight="800" d:DesignWidth="1850">
     <UserControl.Resources>
         <converters:BoolToColor x:Key="boolToColor"/>
         <converters:RecipeIconConverter x:Key="recipeIconConverter"/>
-
+        <converters:BoolToVisibility2 x:Key="BoolToVisibility2"/>
         <Style x:Key="TextBlockStyle" TargetType="TextBlock">
             <Style.Setters>
                 <Setter Property="Text" Value="UnClamped"/>
@@ -123,6 +125,21 @@
             <Grid Grid.Row="2" Width="410" HorizontalAlignment="Left">
                 <UserControls:MetalWaferSizeControl IsEnabled="{Binding IsEnabled}" MetalWaferSize="{Binding MetalPersistent.MetalWaferSize}" ModuleName="{Binding Module}"/>
             </Grid>
+            <GroupBox Header="Pump Settings" FontWeight="Bold" FontSize="15" Grid.Row="3" Margin="10 20 400 80" Visibility="{Binding IsRegulatePump,Converter={StaticResource BoolToVisibility2}}">
+                <Grid>
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="30"></RowDefinition>
+                        <RowDefinition Height="35"></RowDefinition>
+                    </Grid.RowDefinitions>
+                    <Grid Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center">
+                        <Label FontSize="14" FontWeight="Bold">Pump Speed(RPM)</Label>
+                    </Grid>
+                    <Control:NumbericTextBox Grid.Row="1"  Margin="10,0,10,0" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="15" FontWeight="Bold" Height="30" Width="130"
+               Value="{Binding Path=PumpSpeed,Mode=TwoWay}" TextboxName="PumpSpeed" KeyOperation="{Binding PumpSpeedCommand}"
+               />
+                </Grid>
+            </GroupBox>
+
         </Grid>
         <Grid Grid.Row="2" Grid.Column="3" Margin="0,0,0,30" Grid.RowSpan="2">
             <Grid.RowDefinitions>

+ 5 - 1
CyberX8_RT/Config/Devices/ModuleIOCfg.xml

@@ -413,6 +413,7 @@
 	<IO Name="Reservoir1.LowLevel" IOName="r_RES1_LOW_LEVEL"/>
 	<IO Name="Reservoir1.SafetyHighLevel" IOName="r_RES1_HIGH_LEVEL"/>
 	<IO Name="Reservoir1.HedFlow" IOName="r_RES1_HED_FLOW"/>
+    <IO Name="Reservoir1.HedPowerOn" IOName="c_HED1_POWER_ON"/>
 	</Module>
 	<Module Name="Reservoir2">
 	<IO Name="Reservoir2.Flow" IOName="r_MBS2_FLOW"/>
@@ -435,6 +436,7 @@
 	<IO Name="Reservoir3.LowLevel" IOName="r_RES3_LOW_LEVEL"/>
     <IO Name="Reservoir3.SafetyHighLevel" IOName="r_RES3_HIGH_LEVEL"/>
 	<IO Name="Reservoir3.HedFlow" IOName="r_RES3_HED_FLOW"/>
+	<IO Name="Reservoir3.HedPowerOn" IOName="c_HED3_POWER_ON"/>
 	</Module>
     <Module Name="Reservoir4">
 	<IO Name="Reservoir4.Flow" IOName="r_RES4_CMM_FLOW"/>
@@ -466,8 +468,10 @@
 	</Module>
 	<Module Name="Metal4">
 	<IO Name="Metal4.CellFlow" IOName="r_PUMP4_FLOW"/>
-	<IO Name="Metal4.CellPump" IOName="c_METAL4_PUMP_ON"/>
+	<IO Name="Metal4.RegulatPump" IOName="c_METAL4_PUMP_ON"/>
 	<IO Name="Metal4.Circulation" IOName="c_METAL4_CIRCULATION"/>
 	<IO Name="Metal4.WaferHolderClamp" IOName="c_METAL4_WH_CLAMP"/>
+	<IO Name="Metal4.RegulatePumpSignalIn" IOName="r_METAL4_PUMP_ON"/>
+	<IO Name="Metal4.RegulatePumpSpeed" IOName="c_METAL4_PUMP_ON_SPEED"/>
 	</Module>
 </BeckhoffModuleIOCfg>

+ 1 - 1
CyberX8_RT/Config/Devices/WagoControllerCfg-Simulator.xml

@@ -518,7 +518,7 @@
 		</Dig_Out>
 		<Ano_Out>
 			<AOGroup Name="1">
-				<AO Name="c_METAL4_PUMP_ON_SPEED"  Address="512" Scaling="0=3276.7,10000=32767" DataType="short"/>
+				<AO Name="c_METAL4_PUMP_ON_SPEED"  Address="512" Scaling="0=0,10000=32767" DataType="short"/>
 				<AO Name="AO2"  Address="513" DataType="short"/>
 				<AO Name="AO3"  Address="514" DataType="short"/>
 				<AO Name="AO4"  Address="515" DataType="short"/>

+ 1 - 1
CyberX8_RT/Config/Devices/WagoControllerCfg.xml

@@ -518,7 +518,7 @@
 		</Dig_Out>
 		<Ano_Out>
 			<AOGroup Name="1">
-				<AO Name="c_METAL4_PUMP_ON_SPEED"  Address="512" Scaling="0=3276.7,10000=32767" DataType="short"/>
+				<AO Name="c_METAL4_PUMP_ON_SPEED"  Address="512" Scaling="0=0,10000=32767" DataType="short"/>
 				<AO Name="AO2"  Address="513" DataType="short"/>
 				<AO Name="AO3"  Address="514" DataType="short"/>
 				<AO Name="AO4"  Address="515" DataType="short"/>

+ 7 - 3
CyberX8_RT/Config/Layout/ToolLayoutConfiguration.xml

@@ -396,6 +396,7 @@
 					<PlatingPowerSupplyBID>Power2-1</PlatingPowerSupplyBID>
 					<LinmotID>LNM1-1</LinmotID>
 					<SubType>Stratus</SubType>
+					<PumpType>Standard</PumpType>
 				</Item>
 			</MetalCells>
 			<CellPosition>11</CellPosition>
@@ -410,7 +411,7 @@
 			<ChemReplenPumps>2</ChemReplenPumps>
 			<AutoDrainsInstalled>false</AutoDrainsInstalled>
 			<SlipstreamType>None</SlipstreamType>
-			<CMMType>Standard</CMMType>
+			<CMMType></CMMType>
 			<CMMSupplyID></CMMSupplyID>
 			<EvaporatorType>STD</EvaporatorType>
 		</Item>
@@ -443,6 +444,7 @@
 					<PlatingPowerSupplyBID>Power4-1</PlatingPowerSupplyBID>
 					<LinmotID>LNM1-2</LinmotID>
 					<SubType>Stratus</SubType>
+					<PumpType>Standard</PumpType>
 				</Item>
 			</MetalCells>
 			<CellPosition>14</CellPosition>
@@ -499,6 +501,7 @@
 					<PlatingPowerSupplyBID>Power6-1</PlatingPowerSupplyBID>
 					<LinmotID>LNM1-3</LinmotID>
 					<SubType>Stratus</SubType>
+					<PumpType>Standard</PumpType>
 				</Item>
 			</MetalCells>
 			<CellPosition>15</CellPosition>
@@ -513,7 +516,7 @@
 			<ChemReplenPumps>2</ChemReplenPumps>
 			<AutoDrainsInstalled>false</AutoDrainsInstalled>
 			<SlipstreamType>None</SlipstreamType>
-			<CMMType>Standard</CMMType>
+			<CMMType></CMMType>
 			<CMMSupplyID></CMMSupplyID>
 			<EvaporatorType>STD</EvaporatorType>
 		</Item>
@@ -537,6 +540,7 @@
 					<PlatingPowerSupplyBID>Power8-1</PlatingPowerSupplyBID>
 					<LinmotID>LNM1-4</LinmotID>
 					<SubType>Stratus</SubType>
+					<PumpType>Regulate</PumpType>
 				</Item>
 			</MetalCells>
 			<CellPosition>16</CellPosition>
@@ -551,7 +555,7 @@
 			<ChemReplenPumps>2</ChemReplenPumps>
 			<AutoDrainsInstalled>false</AutoDrainsInstalled>
 			<SlipstreamType>None</SlipstreamType>
-			<CMMType>Standard</CMMType>
+			<CMMType></CMMType>
 			<CMMSupplyID></CMMSupplyID>
 			<EvaporatorType>STD</EvaporatorType>
 		</Item>

+ 2 - 2
CyberX8_RT/Config/System.sccfg

@@ -465,8 +465,8 @@
 		<config default="2.5" name="PHSampleTime" nameView="PHSampleTime" description="PH sample time" max="10" min="0" paramter="" tag="" unit="s" type="Double"></config>
 		<config default="20" name="PHSamples" nameView="PHSamples" description="PH sample count" max="50" min="0" paramter="" tag="" unit="" type="Integer"></config>
 		<config default="20" name="LevelAvgSamples" nameView="LevelAvgSamples" description="Level average sample" max="100" min="0" paramter="" tag="" unit="" type="Integer"></config>
-		<config default="5000" name="CADefaultPumpSpeed" nameView="CADefaultPumpSpeed" description="CA pump default speed" max="7200" min="0" paramter="" tag="" unit="" type="Double"></config>
-		<config default="7200" name="CAMaxPumpSpeed" nameView="CAMaxPumpSpeed" description="CA Max Pump Speed" max="10000" min="1" paramter="" tag="" unit="rpm" type="Double"></config>
+		<config default="5000" name="DefaultPumpSpeed" nameView="DefaultPumpSpeed" description="pump default speed" max="7200" min="0" paramter="" tag="" unit="" type="Double"></config>
+		<config default="7200" name="MaxPumpSpeed" nameView="MaxPumpSpeed" description="Max Pump Speed" max="10000" min="1" paramter="" tag="" unit="rpm" type="Double"></config>
 		<config default="3" name="ANDefaultPumpSpeed" nameView="ANDefaultPumpSpeed" description="AN pump default speed" max="5" min="0" paramter="" tag="" unit="" type="Double"></config>
 		<config default="5" name="ANOverFlow" nameView="ANOverFlow" description="AN Pump ignor AN over flow " max="10" min="0" paramter="" tag="" unit="" type="Double"></config>
 		<config default="3" name="DrainSpeed" nameView="DrainSpeed" description="AN drain pump default speed" max="5" min="0" paramter="" tag="" unit="" type="Double"></config>

+ 128 - 4
CyberX8_RT/Devices/Metal/StandardHotMetalDevice.cs

@@ -18,6 +18,9 @@ using System.Linq;
 using System.Reflection;
 using System.Diagnostics;
 using MECF.Framework.Common.IOCore;
+using Aitex.Core.RT.SCCore;
+using CyberX8_RT.Devices.PowerSupplier;
+using MECF.Framework.Common.ToolLayout;
 
 
 namespace CyberX8_RT.Devices.Metal
@@ -35,6 +38,9 @@ namespace CyberX8_RT.Devices.Metal
         private const string CELL_FLOW = "CellFlow";
         private const string WH_CLAMP = "WaferHolderClamp";
         private const string CIRCULATION = "Circulation";
+        private const string REGULATE_PUMP_SIGNAL_IN = "RegulatePumpSignalIn";
+        private const string REGULATE_PUMP_SPEED = "RegulatePumpSpeed";
+        private const string REGULATE_PUMP = "RegulatPump";
         #endregion
         #region 内部变量
         /// <summary>
@@ -57,6 +63,18 @@ namespace CyberX8_RT.Devices.Metal
         /// Flow Valve计时
         /// </summary>
         private Stopwatch _flowValveStopWatch = new Stopwatch();
+        /// <summary>
+        /// 调速泵Pump速度
+        /// </summary>
+        private double _regulatePumpSpeed;
+        /// <summary>
+        /// 是否为调速类型的pump
+        /// </summary>
+        private bool _isRegulatePump = false;
+        /// <summary>
+        /// Metal项
+        /// </summary>
+        private MetalItem _metalItem;
         #endregion
 
         #region 属性
@@ -65,6 +83,10 @@ namespace CyberX8_RT.Devices.Metal
         /// </summary>
         public StandardHotMetalDeviceData MetalDeviceData { get { return _metalDeviceData; } }
         /// <summary>
+        /// 是否调速泵
+        /// </summary>
+        public bool IsRegulatePump { get { return _isRegulatePump; } }
+        /// <summary>
         /// Flow Valve稳定状态
         /// </summary>
         public bool FlowValveStable { get { return _metalDeviceData.Circulation && _flowValveStopWatch.ElapsedMilliseconds >= 3000; } }
@@ -101,6 +123,12 @@ namespace CyberX8_RT.Devices.Metal
             {
                 LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Persistent Value Object is not exist");
             }
+            _metalItem = MetalItemManager.Instance.GetMetalItem(Module);
+            if (_metalItem != null)
+            {
+                _isRegulatePump = "Regulate" == _metalItem.PumpType;
+            }
+            _regulatePumpSpeed = SC.GetValue<double>("Reservoir.DefaultPumpSpeed");
         }
         /// <summary>
         /// 初始化Routine
@@ -119,6 +147,9 @@ namespace CyberX8_RT.Devices.Metal
             DATA.Subscribe($"{Module}.WaferShuttleClamped", () => _metalDeviceData.WaferHolderClamp, SubscriptionAttribute.FLAG.IgnoreSaveDB);
             DATA.Subscribe($"{Module}.CellFlow", () => _metalDeviceData.CellFlow, SubscriptionAttribute.FLAG.IgnoreSaveDB);
             DATA.Subscribe($"{Module}.Circulation", () => _metalDeviceData.Circulation, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.IsRegulatePump", () => _isRegulatePump, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.PumpSpeed", () => _regulatePumpSpeed, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+
         }
         /// <summary>
         /// 订阅变量数值发生变化
@@ -129,6 +160,7 @@ namespace CyberX8_RT.Devices.Metal
             BeckhoffIoSubscribeUpdateVariable(CELL_FLOW);
             BeckhoffIoSubscribeUpdateVariable(WH_CLAMP);
             BeckhoffIoSubscribeUpdateVariable(CIRCULATION);
+            BeckhoffIoSubscribeUpdateVariable(REGULATE_PUMP_SIGNAL_IN);
         }
         /// <summary>
         /// 订阅Operation
@@ -136,14 +168,15 @@ namespace CyberX8_RT.Devices.Metal
         protected override void InitializeOperation()
         {
             base.InitializeOperation();
-            OP.Subscribe($"{Module}.PumpEnable", (cmd, args) => { return PumpOnOperation(cmd, args); });
-            OP.Subscribe($"{Module}.PumpDisable", (cmd, args) => { return PumpOffOperation(cmd, args); });
+            OP.Subscribe($"{Module}.PumpEnable", OpenPump);
+            OP.Subscribe($"{Module}.PumpDisable", ClosePump);
             OP.Subscribe($"{Module}.CellSwitchToBypass", (cmd, args) => { return SwitchToBypass(cmd, args); });
             OP.Subscribe($"{Module}.CellSwitchToFlow", (cmd, args) => { return SwitchToFlow(cmd, args); });
             OP.Subscribe($"{Module}.ClampOn", (cmd, args) => { return WaferHolderClampOn(cmd, args); });
             OP.Subscribe($"{Module}.ClampOff", (cmd, args) => { return WaferHolderClampOff(cmd, args); });
             OP.Subscribe($"{Module}.WaferHolderClampOn", (cmd, args) => { return WaferHolderClampOn(cmd, args); });
             OP.Subscribe($"{Module}.WaferHolderUnclampOn", (cmd, args) => { return WaferHolderClampOff(cmd, args); });
+            OP.Subscribe($"{Module}.RegulatPumpSpeed", RegulatePumpSpeedOperation);
         }
 
         /// <summary>
@@ -185,7 +218,98 @@ namespace CyberX8_RT.Devices.Metal
                 }
             }
         }
+        public bool OpenPump(string cmd, Object[] args)
+        {
+            bool result = false;
+            if (_isRegulatePump)
+            {
+                result = RegulatePumpOn(cmd, args);
+            }
+            else
+            {
+                result = PumpOnOperation(cmd, args);
+            }
+            return result;
+        }
+        public bool ClosePump(string cmd, Object[] args)
+        {
+            bool result = false;
+            if (_isRegulatePump)
+            {
+                result = RegulatePumpOff(cmd, args);
+            }
+            else
+            {
+                result = PumpOffOperation(cmd, args);
+            }
+            return result;
+        }
 
+        #region Regulat Pump
+        /// <summary>
+        /// 调速pump
+        /// </summary>
+        /// <param name="cmd"></param>
+        /// <param name="args"></param>
+        /// <returns></returns>
+        private bool RegulatePumpSpeedOperation(string cmd, object[] args)
+        {
+            double MaxPumpSpeed = 0;
+            if (SC.ContainsItem("Reservoir.MaxPumpSpeed"))
+            {
+                MaxPumpSpeed = SC.GetValue<double>("Reservoir.MaxPumpSpeed");
+            }
+            if (double.TryParse(args[0].ToString(), out double speed))
+            {
+                _regulatePumpSpeed = speed;
+                if (_regulatePumpSpeed > MaxPumpSpeed)
+                {
+                    _regulatePumpSpeed = SC.GetValue<double>("Reservoir.DefaultPumpSpeed");//恢复成默认泵速
+                    LOG.WriteLog(eEvent.WARN_METAL, Module, $"Pump speed:{_regulatePumpSpeed} is over max pump speed {MaxPumpSpeed}!");
+                    return false;
+                }
+                return RegulatePumpSpeed(_regulatePumpSpeed);
+            }
+            else
+            {
+                LOG.WriteLog(eEvent.ERR_METAL, Module, $"{args[0]} is nor invalid speed");
+                return false;
+            }
+        }
+        /// <summary>
+        /// 设置泵速
+        /// </summary>
+        /// <param name="PumpSpeed"></param>
+        /// <returns></returns>
+        public bool RegulatePumpSpeed(double PumpSpeed)
+        {
+            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{REGULATE_PUMP_SPEED}");
+            return IOModuleManager.Instance.WriteIoValue(ioName, PumpSpeed);
+        }
+        /// <summary>
+        /// Pump On
+        /// </summary>
+        /// <param name="cmd"></param>
+        /// <param name="args"></param>
+        /// <returns></returns>
+        private bool RegulatePumpOn(string cmd, object[] args)
+        {
+            string enableIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{REGULATE_PUMP}");
+            return IOModuleManager.Instance.WriteIoValue(enableIOName, true);
+        }
+        /// <summary>
+        /// Pump Off
+        /// </summary>
+        /// <param name="cmd"></param>
+        /// <param name="args"></param>
+        /// <returns></returns>
+        private bool RegulatePumpOff(string cmd, object[] args)
+        {
+            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{REGULATE_PUMP}");
+            return IOModuleManager.Instance.WriteIoValue(ioName, false);
+        }
+
+        #endregion
         #region CellPump
         /// <summary>
         /// Cell Pump On操作
@@ -290,7 +414,7 @@ namespace CyberX8_RT.Devices.Metal
         {
             if (_metalDeviceData.CellPump)
             {
-                PumpOffOperation("", null);
+                ClosePump("", null);
             }
         }
 
@@ -309,7 +433,7 @@ namespace CyberX8_RT.Devices.Metal
                     if (rsState == RState.Failed || rsState == RState.Timeout)
                     {
                         _status = RState.Failed;
-                        PumpOff();
+                        ClosePump("", null);
                         _currentOperation = MetalOperation.None;
                     }
                     else if (rsState == RState.End)

+ 42 - 27
CyberX8_RT/Devices/Reservoir/StandardHotReservoirDevice.cs

@@ -66,6 +66,7 @@ namespace CyberX8_RT.Devices.Reservoir
         private const string RESERVOIRDEVICEDATA = "ReservoirDeviceData";
         private const string REPLEN_LEVEL = "ReplenLevel";
         private const string RESPOWERON = "ResPowerOn";
+        private const string HEDPOWERON = "HedPowerOn";
         private const double PUMP_SPEED_CONVERT = 0.0672;
         private const int ENABLE = 5;
         #endregion
@@ -197,6 +198,7 @@ namespace CyberX8_RT.Devices.Reservoir
         private bool _isAutoDIReplenError = false;
         private bool _isSafetyHigh = false;
         private bool _isSystemAutoMode = false;
+        private bool _reservoirPowerOn = false;
         /// <summary>
         /// 用于控制打印错误log
         /// </summary>
@@ -461,7 +463,7 @@ namespace CyberX8_RT.Devices.Reservoir
                     }
                     if (metalDevice.MetalDeviceData.CellFlow > 0)
                     {
-                        metalDevice.PumpOff();
+                        metalDevice.ClosePump("", null);
                     }
                     //水位过低时将起对应的metal也要切成error
                     MetalEntity metalEntity = Singleton<RouteManager>.Instance.GetModule<MetalEntity>(metalDevice.DeviceID);
@@ -708,6 +710,7 @@ namespace CyberX8_RT.Devices.Reservoir
             DATA.Subscribe($"{Module}.HedFlow", () => _reservoirData.HedFlow, SubscriptionAttribute.FLAG.IgnoreSaveDB);
             DATA.Subscribe($"{Module}.PHEnable", () => _reservoirData.PHFlowValve, SubscriptionAttribute.FLAG.IgnoreSaveDB);
             DATA.Subscribe($"{Module}.IsDIReplenInFault", () => _isDiReplenInFault, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.ReservoirPowerOn", () => _reservoirPowerOn, SubscriptionAttribute.FLAG.IgnoreSaveDB);
         }
         /// <summary>
         /// 初始化操作
@@ -1042,15 +1045,27 @@ namespace CyberX8_RT.Devices.Reservoir
         /// 打开继电器
         /// </summary>
         /// <returns></returns>
-        public bool ResPowerOn()
+        public void ResPowerOn()
         {
             bool result = false;
             string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{RESPOWERON}");
-            if (!string.IsNullOrEmpty("ioName"))
+            if (!string.IsNullOrEmpty(ioName))
             {
                 result = IOModuleManager.Instance.WriteIoValue(ioName, true);
+                if (!result)
+                {
+                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Open {Module} Power Relay failed");
+                }
+            }
+            ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{HEDPOWERON}");
+            if (!string.IsNullOrEmpty(ioName))
+            {
+                result = IOModuleManager.Instance.WriteIoValue(ioName, true);
+                if (!result)
+                {
+                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Open {Module} Hed Power Relay failed");
+                }
             }
-            return result;
         }
         /// <summary>
         /// 检验DiReplen前置条件
@@ -1773,29 +1788,29 @@ namespace CyberX8_RT.Devices.Reservoir
                    $"MembraneUsage", $"{Module} usage:{reservoirUsage.MembranceUsage} is over MembraneTotalAmpHoursWarningLimit:{membraneTotalAmpHoursWarningLimit}");
             }
             //ANBathTotalAmpHoursCheck
-            double anBathTotalAmpHoursWarningLimit = 0;
-            if (SC.ContainsItem($"Reservoir.{Module}.ANBathTotalAmpHoursWarningLimit"))
-            {
-                anBathTotalAmpHoursWarningLimit = (double)SC.GetValue<double>($"Reservoir.{Module}.ANBathTotalAmpHoursWarningLimit");
-            }
-            double anBathTotalAmpHoursFaultLimit = 0;
-            if (SC.ContainsItem($"Reservoir.{Module}.ANBathTotalAmpHoursFaultLimit"))
-            {
-                anBathTotalAmpHoursFaultLimit = (double)SC.GetValue<double>($"Reservoir.{Module}.ANBathTotalAmpHoursFaultLimit");
-            }
-            if (reservoirUsage.AnodeUsage > anBathTotalAmpHoursFaultLimit && anBathTotalAmpHoursFaultLimit != 0)
-            {
-                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} Anolyte Bath Usage(AHr):{reservoirUsage.AnodeUsage} is over config item ANBathTotalAmpHoursFaultLimit:{anBathTotalAmpHoursFaultLimit}");
-                reservoirEntity.PostMsg(ReservoirMsg.Error);
-                AlarmListManager.Instance.AddDataError(Module,
-                    $"AnodeUsage", $"{Module} usage:{reservoirUsage.AnodeUsage} is over ANBathTotalAmpHoursFaultLimit:{anBathTotalAmpHoursFaultLimit}");
-            }
-            else if (reservoirUsage.AnodeUsage > anBathTotalAmpHoursWarningLimit && anBathTotalAmpHoursWarningLimit != 0)
-            {
-                LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} Anolyte Bath Usage(AHr):{reservoirUsage.AnodeUsage} is over config item ANBathTotalAmpHoursWarningLimit:{anBathTotalAmpHoursWarningLimit}");
-                AlarmListManager.Instance.AddWarn(Module,
-                    $"AnodeUsage", $"{Module} usage:{reservoirUsage.AnodeUsage} is over ANBathTotalAmpHoursWarningLimit:{anBathTotalAmpHoursWarningLimit}");
-            }
+            //double anBathTotalAmpHoursWarningLimit = 0;
+            //if (SC.ContainsItem($"Reservoir.{Module}.ANBathTotalAmpHoursWarningLimit"))
+            //{
+            //    anBathTotalAmpHoursWarningLimit = (double)SC.GetValue<double>($"Reservoir.{Module}.ANBathTotalAmpHoursWarningLimit");
+            //}
+            //double anBathTotalAmpHoursFaultLimit = 0;
+            //if (SC.ContainsItem($"Reservoir.{Module}.ANBathTotalAmpHoursFaultLimit"))
+            //{
+            //    anBathTotalAmpHoursFaultLimit = (double)SC.GetValue<double>($"Reservoir.{Module}.ANBathTotalAmpHoursFaultLimit");
+            //}
+            //if (reservoirUsage.AnodeUsage > anBathTotalAmpHoursFaultLimit && anBathTotalAmpHoursFaultLimit != 0)
+            //{
+            //    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} Anolyte Bath Usage(AHr):{reservoirUsage.AnodeUsage} is over config item ANBathTotalAmpHoursFaultLimit:{anBathTotalAmpHoursFaultLimit}");
+            //    reservoirEntity.PostMsg(ReservoirMsg.Error);
+            //    AlarmListManager.Instance.AddDataError(Module,
+            //        $"AnodeUsage", $"{Module} usage:{reservoirUsage.AnodeUsage} is over ANBathTotalAmpHoursFaultLimit:{anBathTotalAmpHoursFaultLimit}");
+            //}
+            //else if (reservoirUsage.AnodeUsage > anBathTotalAmpHoursWarningLimit && anBathTotalAmpHoursWarningLimit != 0)
+            //{
+            //    LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} Anolyte Bath Usage(AHr):{reservoirUsage.AnodeUsage} is over config item ANBathTotalAmpHoursWarningLimit:{anBathTotalAmpHoursWarningLimit}");
+            //    AlarmListManager.Instance.AddWarn(Module,
+            //        $"AnodeUsage", $"{Module} usage:{reservoirUsage.AnodeUsage} is over ANBathTotalAmpHoursWarningLimit:{anBathTotalAmpHoursWarningLimit}");
+            //}
             //BathTotalAmpHoursCheck
             double bathTotalAmpHoursWarningLimit = 0;
             if (SC.ContainsItem($"Reservoir.{Module}.BathTotalAmpHoursWarningLimit"))

+ 1 - 1
CyberX8_RT/Modules/Metal/MetalEntity.cs

@@ -1046,7 +1046,7 @@ namespace CyberX8_RT.Modules.Metal
                     bool result = device.SwitchToFlow("", null);
                     if (result)
                     {
-                        return device.PumpOnOperation("", null);
+                        return device.OpenPump("", null);
                     }
                 }
                 return false;

+ 1 - 1
CyberX8_RT/Modules/Metal/StandardHotInitializeRoutine.cs

@@ -125,7 +125,7 @@ namespace CyberX8_RT.Modules.Metal
             {
                 LOG.WriteLog(eEvent.ERR_METAL, Module, $"Flow {_metalDevice.MetalDeviceData.CellFlow} is less than {_cellFlowStartLowLimit}");
                 _metalDevice.SwitchToBypass("", null);
-                _metalDevice.PumpOff();
+                _metalDevice.ClosePump("", null);
                 return false;
             }
             return true;

+ 5 - 5
CyberX8_RT/Modules/Reservoir/ReservoirEntity.cs

@@ -305,11 +305,11 @@ namespace CyberX8_RT.Modules.Reservoir
             DATA.Subscribe($"{Module}.BathTotalAmpHours.WarningLimit", () => SC.GetValue<double>($"Reservoir.{Module}.BathTotalAmpHoursWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
             DATA.Subscribe($"{Module}.BathTotalAmpHours.FaultLimit", () => SC.GetValue<double>($"Reservoir.{Module}.BathTotalAmpHoursFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
             DATA.Subscribe($"{Module}.ANBathTotalAmpHours", () => ReservoirUsage != null ? ReservoirUsage.AnodeUsage : 0, SubscriptionAttribute.FLAG.IgnoreSaveDB);
-            if (ReservoirItemManager.Instance.GetReservoirItem(Module.ToString()).CMMType != "Standard")
-            {
-                DATA.Subscribe($"{Module}.ANBathTotalAmpHours.WarningLimit", () => SC.GetValue<double>($"Reservoir.{Module}.ANBathTotalAmpHoursWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
-                DATA.Subscribe($"{Module}.ANBathTotalAmpHours.FaultLimit", () => SC.GetValue<double>($"Reservoir.{Module}.ANBathTotalAmpHoursFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
-            }
+            //if (ReservoirItemManager.Instance.GetReservoirItem(Module.ToString()).CMMType != "Standard")
+            //{
+            //    DATA.Subscribe($"{Module}.ANBathTotalAmpHours.WarningLimit", () => SC.GetValue<double>($"Reservoir.{Module}.ANBathTotalAmpHoursWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            //    DATA.Subscribe($"{Module}.ANBathTotalAmpHours.FaultLimit", () => SC.GetValue<double>($"Reservoir.{Module}.ANBathTotalAmpHoursFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            //}
             DATA.Subscribe($"{Module}.MembraneTotalAmpHours", () => ReservoirUsage != null ? ReservoirUsage.MembranceUsage : 0, SubscriptionAttribute.FLAG.IgnoreSaveDB);
             DATA.Subscribe($"{Module}.MembraneTotalAmpHours.WarningLimit", () => SC.GetValue<double>($"Reservoir.{Module}.MembraneTotalAmpHoursWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
             DATA.Subscribe($"{Module}.MembraneTotalAmpHours.FaultLimit", () => SC.GetValue<double>($"Reservoir.{Module}.MembraneTotalAmpHoursFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);

+ 39 - 10
CyberX8_RT/Modules/Reservoir/StandardHotReservoirInitializeRoutine.cs

@@ -14,6 +14,7 @@ using CyberX8_RT.Devices.Metal;
 using CyberX8_RT.Devices.PowerSupplier;
 using CyberX8_RT.Devices.Reservoir;
 using CyberX8_RT.Devices.Temperature;
+using MECF.Framework.Common.ToolLayout;
 
 namespace CyberX8_RT.Modules.Reservoir
 {
@@ -57,6 +58,7 @@ namespace CyberX8_RT.Modules.Reservoir
         private CellPowerSupplier _cellPowerSupplier;
         private TemperatureController _temperatureController;
         private int _autoHedDelay = 0;
+        private bool _isRegulatePump;
         /// <summary>
         /// CMM Check Flow延时
         /// </summary>
@@ -108,7 +110,8 @@ namespace CyberX8_RT.Modules.Reservoir
             //Cell Pump
             Runner.RunIf(InitializeStep.AutoDiReplen, _recipe.DIReplenEnable, CheckFacilitiesDiReplenStatus, _delay_1ms)
                 .Run(InitializeStep.CellPump, CellsPumpOn, _delay_1ms)
-                .WaitWithStopCondition(InitializeStep.WaitCellPump, CheckPumpOnEndStatus, CheckPumpOnStopStatus)
+                .WaitWithStopConditionIf(InitializeStep.WaitCellPump, !_isRegulatePump, CheckPumpOnEndStatus, CheckPumpOnStopStatus)
+                .WaitIf(InitializeStep.WaitCellPump, _isRegulatePump, CheckRegulatePumpOn,_delay_3m)
                 .Run(InitializeStep.CheckCellFlow, CheckCellFlow, _delay_1ms)
                 //Manual cell Bypass同时disable HED
                 .RunIf(InitializeStep.ManualCellByPass, _reservoirDevice.OperationMode == MANUAL, CellsByPassEnableHed, _delay_1ms)
@@ -167,7 +170,7 @@ namespace CyberX8_RT.Modules.Reservoir
             for (int i = 0; i < _metalDevices.Count; i++)
             {
                 StandardHotMetalDevice hotMetalDevice = _metalDevices[i];
-                hotMetalDevice.PumpOnOperation("", null);
+                hotMetalDevice.OpenPump("", null);
             }
             return true;
         }
@@ -209,7 +212,26 @@ namespace CyberX8_RT.Modules.Reservoir
                 return false;
             }
         }
-
+        private bool CheckRegulatePumpOn()
+        {
+            int totalCount = 0;
+            for (int i = 0; i < _metalDevices.Count; i++)
+            {
+                StandardHotMetalDevice hotMetalDevice = _metalDevices[i];
+                if (hotMetalDevice.MetalDeviceData.RegulatePumpSignalIn)
+                {
+                    totalCount++;
+                }
+            }
+            if (totalCount >= _metalDevices.Count)
+            {
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
         /// <summary>
         /// 检验metal Pump停止状态
         /// </summary>
@@ -235,7 +257,7 @@ namespace CyberX8_RT.Modules.Reservoir
             for (int i = 0; i < _metalDevices.Count; i++)
             {
                 StandardHotMetalDevice hotMetalDevice = _metalDevices[i];
-                hotMetalDevice.PumpOff();
+                hotMetalDevice.ClosePump("",null);
             }
         }
         /// <summary>
@@ -312,7 +334,7 @@ namespace CyberX8_RT.Modules.Reservoir
         /// <returns></returns>
         private bool CheckAutoEnableCMM()
         {
-            if (_reservoirDevice.OperationMode != AUTO)
+            if (_reservoirDevice.OperationMode != AUTO || ReservoirItemManager.Instance.GetReservoirItem(Module.ToString()).CMMType != "Standard")
             {
                 return false;
             }
@@ -613,6 +635,10 @@ namespace CyberX8_RT.Modules.Reservoir
             {
                 _metalDevices.Add((StandardHotMetalDevice)lstDevice[i]);
             }
+            if (_metalDevices.Count > 0) 
+            {
+                _isRegulatePump = _metalDevices[0].IsRegulatePump;
+            }
             _reservoirDevice = DEVICE.GetDevice<StandardHotReservoirDevice>(Module.ToString());
             _recipe = _reservoirDevice.Recipe;
             if (!(objs[1] is null))
@@ -625,11 +651,14 @@ namespace CyberX8_RT.Modules.Reservoir
             {
                 return RState.Failed;
             }
-            _cmmFlowHighFault = SC.GetValue<double>($"Reservoir.{Module}.CMMFlowHighFault");
-            _cmmFlowHighWarning = SC.GetValue<double>($"Reservoir.{Module}.CMMFlowHighWarning");
-            _cmmFlowLowFault = SC.GetValue<double>($"Reservoir.{Module}.CMMFlowLowFault");
-            _cmmFlowLowWarning = SC.GetValue<double>($"Reservoir.{Module}.CMMFlowLowWarning");
-            _cmmFlowCheckDelay = SC.GetValue<int>($"Reservoir.{Module}.CMMFlowCheckDelaySeconds");
+            if (ReservoirItemManager.Instance.GetReservoirItem(Module.ToString()).CMMType == "Standard")
+            {
+                _cmmFlowHighFault = SC.GetValue<double>($"Reservoir.{Module}.CMMFlowHighFault");
+                _cmmFlowHighWarning = SC.GetValue<double>($"Reservoir.{Module}.CMMFlowHighWarning");
+                _cmmFlowLowFault = SC.GetValue<double>($"Reservoir.{Module}.CMMFlowLowFault");
+                _cmmFlowLowWarning = SC.GetValue<double>($"Reservoir.{Module}.CMMFlowLowWarning");
+                _cmmFlowCheckDelay = SC.GetValue<int>($"Reservoir.{Module}.CMMFlowCheckDelaySeconds");
+            }
             if (_recipe.CMMEnable)
             {
                 _persistentValue = ReservoirsPersistentManager.Instance.GetReservoirsPersistentValue(Module);

+ 6 - 0
CyberX8_Simulator/Devices/WagoSocketSimulator.cs

@@ -291,6 +291,12 @@ namespace CyberX8_Simulator.Devices
                 value = _doNameWagoDODic["c_SRD2_WATER_ON"].Invert ? !value : value;
                 UpdataAIShorts("r_SRD2_WATER_FLOW", value ? 30000 : 3277);
             }
+            //metal 4 pump
+            if (DONameIndexDic.ContainsKey("c_METAL4_PUMP_ON") && position == DONameIndexDic["c_METAL4_PUMP_ON"])
+            {
+                value = _doNameWagoDODic["c_METAL4_PUMP_ON"].Invert ? !value : value;
+                UpdataDIBytes("r_METAL4_PUMP_ON", value ? 1 : 0);
+            }
         }
         /// <summary>
         /// 初始化字典

+ 8 - 0
Framework/Common/CommonData/Metal/StandardHotMetalDeviceData.cs

@@ -13,6 +13,10 @@ namespace MECF.Framework.Common.CommonData.Metal
         private bool _isDataInitialized;
 
         private bool _cellPump;
+        
+        private bool _regulatePumpSignalIn;
+
+        private int _regulatePumpSpeed;
 
         private double _cellFlow;
 
@@ -25,8 +29,12 @@ namespace MECF.Framework.Common.CommonData.Metal
         public bool IsDataInitialized { get { return _isDataInitialized; } set { _isDataInitialized = value; InvokePropertyChanged(nameof(IsDataInitialized)); } }
 
         public bool CellPump { get { return _cellPump; } set { _cellPump = value;InvokePropertyChanged(nameof(CellPump)); } }
+       
+        public bool RegulatePumpSignalIn { get { return _regulatePumpSignalIn; } set { _regulatePumpSignalIn = value;InvokePropertyChanged(nameof(RegulatePumpSignalIn)); } }
 
         public double CellFlow { get { return _cellFlow; } set { _cellFlow = value;InvokePropertyChanged(nameof(CellFlow)); } }
+        
+        public int RegulatePumpSpeed { get { return _regulatePumpSpeed; } set { _regulatePumpSpeed = value;InvokePropertyChanged(nameof(RegulatePumpSpeed)); } }
 
         public bool WaferHolderClamp { get { return _waferHolderClamp; } set { _waferHolderClamp = value; InvokePropertyChanged(nameof(WaferHolderClamp)); } }
         /// <summary>

+ 4 - 0
Framework/Common/ToolLayout/MetalItem.cs

@@ -29,5 +29,9 @@ namespace MECF.Framework.Common.ToolLayout
         /// Power Supply B ID
         /// </summary>
         public string PlatingPowerSupplyBID { get; set; }
+        /// <summary>
+        /// pump类型
+        /// </summary>
+        public string PumpType { get; set; }
     }
 }

+ 1 - 0
Framework/Common/ToolLayout/MetalItemManager.cs

@@ -48,6 +48,7 @@ namespace MECF.Framework.Common.ToolLayout
             metalItem.PlatingPowerSupplyAID = metalItemElement.SelectSingleNode("PlatingPowerSupplyAID").InnerText;
             metalItem.PlatingPowerSupplyBID = metalItemElement.SelectSingleNode("PlatingPowerSupplyBID").InnerText;
             metalItem.LinmotID = metalItemElement.SelectSingleNode("LinmotID").InnerText;
+            metalItem.PumpType = metalItemElement.SelectSingleNode("PumpType").InnerText;
             string key = $"{PREFIX}{metalItem.MetalID}";
             metalItem.ModuleName = key;
             metalItem.ModuleType = ModuleType.Metal.ToString();