新增系统配置PM.PM1.Heater.ForceDisableInnerHeater,允许用户强制禁用InnerHeater。

新增系统配置PM.PM1.Heater.Recipe.ForceSkipPowerModeStep,允许Recipe在Power模式加温时,温度到达设定值后强制跳步。
更名系统配置项System.OfflineNotifyTimeout为System.ModuleOfflineTimeout。
修正PMProcessView中可能无法加载Recipe的问题。
修正RecipeData中当关闭Cascade加载模式时,可能在非UI线程添加Step的问题。
This commit is contained in:
DESKTOP-GPE37UV\THINKAPD 2022-12-08 14:50:57 +08:00
parent 977b615cea
commit 23baac74da
6 changed files with 106 additions and 65 deletions

View File

@ -61,7 +61,7 @@ namespace MECF.Framework.RT.Core
return true;
// 如果是Auto模式启用超时机制。
var timeoutSec = SC.GetValue<int>("System.OfflineNotifyTimeout");
var timeoutSec = SC.GetValue<int>("System.ModuleOfflineTimeout");
if (timeoutSec <= 0)
timeoutSec = 0;

View File

@ -972,7 +972,14 @@ namespace MECF.Framework.UI.Client.CenterViews.Editors.Recipe
if (t != null)
await t;
else
Steps.Add(step);
{
// 确保在UI线程上执行
Application.Current?.Dispatcher.Invoke(() =>
{
Steps.Add(step);
});
}
stepId++;
}

View File

@ -194,7 +194,17 @@ namespace SicPM.Devices
OP.Subscribe($"{Module}.{Name}.SetPSUEnable", (function, args) =>
{
bool isTrue = Convert.ToBoolean(args[0]);
var forceDisable = SC.GetValue<bool>($"PM.{Module}.Heater.ForceDisableInnerHeater");
var isTrue = Convert.ToBoolean(args[0]);
// 如果系统设置中将InnerHeater设置为强制关闭则不要打开InnerHeater输出
if (forceDisable)
{
isTrue = false;
EV.PostWarningLog(Module, "Inner heater is forcibly disabled");
}
SetPSUEnable(isTrue, out reason);
return true;
});

View File

@ -1030,26 +1030,53 @@ namespace SicPM.RecipeExecutions
if (nextStep.IsDummyStep)
nextStep = PMDevice.RecipeRunningInfo.RecipeStepList[_currentStepNumber + 2];
if (!currentStep.RecipeCommands.ContainsKey("TC1.SetHeaterMode") || !nextStep.RecipeCommands.ContainsKey("TC1.SetHeaterMode"))
if (!currentStep.RecipeCommands.ContainsKey("TC1.SetHeaterMode") ||
!nextStep.RecipeCommands.ContainsKey("TC1.SetHeaterMode"))
return;
HeaterControlMode currentPSUMode = (HeaterControlMode)Enum.Parse(typeof(HeaterControlMode), currentStep.RecipeCommands["TC1.SetHeaterMode"]);
HeaterControlMode nextPSUMode = (HeaterControlMode)Enum.Parse(typeof(HeaterControlMode), nextStep.RecipeCommands["TC1.SetHeaterMode"]);
HeaterControlMode currentPSUMode = (HeaterControlMode)Enum.Parse(typeof(HeaterControlMode),
currentStep.RecipeCommands["TC1.SetHeaterMode"]);
HeaterControlMode nextPSUMode = (HeaterControlMode)Enum.Parse(typeof(HeaterControlMode),
nextStep.RecipeCommands["TC1.SetHeaterMode"]);
if (currentPSUMode == HeaterControlMode.Power && nextPSUMode != HeaterControlMode.Power)
{
float PSUL2InputTemp =(float)DATA.Poll($"{Module}.TC1.L2InputTempSetPoint"); // (float)DATA.Poll($"{Module}.TC1.L1PVFeedBack"); 测试用
var PsuL2TempPv =
(float)DATA.Poll(
$"{Module}.TC1.L2InputTempSetPoint"); // (float)DATA.Poll($"{Module}.TC1.L1PVFeedBack"); 测试用
float nextL2Temp = Convert.ToSingle(nextStep.RecipeCommands["TC1.SetL2TargetSP"]);
if (nextL2Temp > PSUL2InputTemp && nextL2Temp - PSUL2InputTemp < Math.Abs(_tempOffset))
// 根据系统配置决定Power模式加热时是否强制跳步。
var forceSkip = SC.GetValue<bool>("PM.PM1.Heater.Recipe.ForceSkipPowerModeStep");
if (forceSkip)
{
SkipCurrentRecipeStep();
// 如果温差小于阈值,则跳步
var PsuL2TempSp = Convert.ToSingle(currentStep.RecipeCommands["TC1.SetL2TargetSP"]);
if (Math.Abs(PsuL2TempPv - PsuL2TempSp) < Math.Abs(_tempOffset))
{
SkipCurrentRecipeStep();
EV.PostInfoLog(Module, $"Current PSU middle temperature is {PSUL2InputTemp}℃ and Power mode, next step PSU middle temperature setpoint is {nextL2Temp}℃ and {nextPSUMode} mode." +
$" TempOffset is {_tempOffset}℃. Need jump step!");
EV.PostInfoLog(Module,
$"Current PSU middle temperature is {PsuL2TempPv}℃ and Power mode, and it's target is {PsuL2TempSp}℃," +
$" TempOffset is {_tempOffset}℃. Need jump step!");
}
}
else
{
var nextL2Temp = Convert.ToSingle(nextStep.RecipeCommands["TC1.SetL2TargetSP"]);
if (nextL2Temp > PsuL2TempPv && nextL2Temp - PsuL2TempPv < Math.Abs(_tempOffset))
{
SkipCurrentRecipeStep();
EV.PostInfoLog(Module,
$"Current PSU middle temperature is {PsuL2TempPv}℃ and Power mode, next step PSU middle temperature setpoint is {nextL2Temp}℃ and {nextPSUMode} mode." +
$" TempOffset is {_tempOffset}℃. Need jump step!");
}
}
}
}
}

View File

@ -22,7 +22,7 @@
<config default="false" name="BypassEnableTable" description="Bypass EnableTable" max="" min="" paramter="" tag="" unit="" type="Bool" />
<config default="true" name="RecipeCascadeLoading" description="启用瀑布流方式加载Recipe" max="" min="" paramter="" tag="" unit="" type="Bool" />
<config default="false" name="RecipeSaveToDB" description="Recipe文件保存到数据库" max="" min="" paramter="" tag="" unit="" type="Bool" />
<config default="300" name="OfflineNotifyTimeout" description="模块离线超过该指定时间后产生警告" max="100000" min="0" paramter="" tag="" unit="s" type="Integer" />
<config default="300" name="ModuleOfflineTimeout" description="模块离线超过该指定时间后产生警告" max="100000" min="0" paramter="" tag="" unit="s" type="Integer" />
<configs name="Scheduler">
@ -166,12 +166,18 @@
<config default="900" name="PickPVMiddleTempLimit" description="从PM取盘时,需要等待温度低于此数值" max="2000" min="0" paramter="" tag="" unit="℃" type="Double" />
<config default="900" name="PickPVOuterTempLimit" description="从PM取盘时,需要等待温度低于此数值" max="2000" min="0" paramter="" tag="" unit="℃" type="Double" />
<config default="1.0" name="PSU1Y" description="底部恒功率模式控制方案PSU1百分比" max="99999" min="0" paramter="" tag="" unit="" visible="false" type="Double" />
<config default="1.0" name="PSU2Y" description="底部恒功率模式控制方案PSU2百分比" max="99999" min="0" paramter="" tag="" unit="" visible="false" type="Double" />
<config default="1.0" name="PSU3Y" description="底部恒功率模式控制方案PSU3百分比" max="99999" min="0" paramter="" tag="" unit="" visible="false" type="Double" />
<config default="0.5" name="PSU1Power" description="底部恒功率模式控制方案PSU1功率" max="99999" min="0" paramter="" tag="" unit="" visible="false" type="Double" />
<config default="6.0" name="PSU2Power" description="底部恒功率模式控制方案PSU2功率" max="99999" min="0" paramter="" tag="" unit="" visible="false" type="Double" />
<config default="6.0" name="PSU3Power" description="底部恒功率模式控制方案PSU3功率" max="99999" min="0" paramter="" tag="" unit="" visible="false" type="Double" />
<config default="1.0" name="PSU1Y" description="底部恒功率模式控制方案PSU1百分比" max="99999" min="0" paramter="" tag="" unit="" visible="false" type="Double" />
<config default="1.0" name="PSU2Y" description="底部恒功率模式控制方案PSU2百分比" max="99999" min="0" paramter="" tag="" unit="" visible="false" type="Double" />
<config default="1.0" name="PSU3Y" description="底部恒功率模式控制方案PSU3百分比" max="99999" min="0" paramter="" tag="" unit="" visible="false" type="Double" />
<config default="0.5" name="PSU1Power" description="底部恒功率模式控制方案PSU1功率" max="99999" min="0" paramter="" tag="" unit="" visible="false" type="Double" />
<config default="6.0" name="PSU2Power" description="底部恒功率模式控制方案PSU2功率" max="99999" min="0" paramter="" tag="" unit="" visible="false" type="Double" />
<config default="6.0" name="PSU3Power" description="底部恒功率模式控制方案PSU3功率" max="99999" min="0" paramter="" tag="" unit="" visible="false" type="Double" />
<config default="false" name="ForceDisableInnerHeater" description="强制禁用InnerHeater" max="" min="" paramter="" tag="" unit="" visible="true" type="Bool" />
<configs name="Recipe">
<config default="false" name="ForceSkipPowerModeStep" description="如果加热器在当前Recipe步骤中工作在功率模式温度到达后强制跳步" max="" min="" paramter="" tag="" unit="" visible="true" type="Bool" />
</configs>
</configs>
<configs name="ProcessIdle">

View File

@ -105,9 +105,6 @@ namespace SicUI.Models.PMs
{
_currectProcessingRecipe = value;
DisplayingRecipeName = value;
// 加载Recipe
_progressLoadRecipe.Report(value);
}
}
}
@ -227,10 +224,19 @@ namespace SicUI.Models.PMs
}
}
private string _displayingRecipeName;
public string DisplayingRecipeName
{
get;
set;
get => _displayingRecipeName;
private set
{
if (_displayingRecipeName != value)
{
_displayingRecipeName = value;
_progressLoadRecipe.Report(value);
NotifyOfPropertyChange();
}
}
}
public bool IsRecipeLoading { get; set; }
@ -358,10 +364,10 @@ namespace SicUI.Models.PMs
if (String.IsNullOrEmpty(DisplayingRecipeName))
{
needLoadRecipe = false;
DisplayingRecipeName =
var recipeName =
(string)QueryDataClient.Instance.Service.GetConfig($"PM.{SystemName}.LastRecipeName");
_progressLoadRecipe.Report(DisplayingRecipeName);
DisplayingRecipeName = recipeName;
}
//流量需要乘以此系数
@ -482,15 +488,16 @@ namespace SicUI.Models.PMs
}
// 自动滚到当前做工艺的Step
var dg = ((PMProcessView)View).dgCustom;
var dg = ((PMProcessView)View)?.dgCustom;
if (currentStepNum > 0)
{
var stepScrollTo = currentStepNum - 1;
if (stepScrollTo < 0)
stepScrollTo = 0;
dg.ScrollIntoView(CurrentRecipe.Steps[stepScrollTo]);
dg?.ScrollIntoView(CurrentRecipe.Steps[stepScrollTo]);
}
}
@ -519,28 +526,12 @@ namespace SicUI.Models.PMs
UpdateRecipeFormat();
LoadRecipe(recipeName)
.ContinueWith(t =>
{
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
// 刷新Recipe工艺状态
UpdateRecipeStepProcessedStatus(RecipeStepNumber);
}));
}).ContinueWith(t =>
{
Application.Current.Dispatcher.Invoke(() =>
{
lock (_lockerLoadingRecipe)
{
IsRecipeLoading = false;
}
});
});
LoadRecipe(recipeName);
UpdateRecipeStepProcessedStatus(RecipeStepNumber);
lock (_lockerLoadingRecipe)
{
IsRecipeLoading = false;
}
}
@ -572,7 +563,7 @@ namespace SicUI.Models.PMs
{
base.Poll();
var lastRecipe = (string)QueryDataClient.Instance.Service.GetConfig($"PM.{SystemName}.LastRecipeName");
/*var lastRecipe = (string)QueryDataClient.Instance.Service.GetConfig($"PM.{SystemName}.LastRecipeName");
if (!string.IsNullOrEmpty(lastRecipe))
{
@ -580,8 +571,9 @@ namespace SicUI.Models.PMs
if (CurrentRecipe.FullName == lastRecipe)
return;
_progressLoadRecipe.Report(lastRecipe);
}
if(!IsRecipeLoading)
_progressLoadRecipe.Report(lastRecipe);
}*/
}
catch (Exception ex)
{
@ -596,7 +588,6 @@ namespace SicUI.Models.PMs
if (needLoadRecipe)
{
needLoadRecipe = false;
_progressLoadRecipe.Report(DisplayingRecipeName);
/*UpdateRecipeFormat();
OnViewLoaded(View);
LoadRecipe(DisplayingRecipeName);*/
@ -874,21 +865,21 @@ namespace SicUI.Models.PMs
if ((bool)bret)
{
DisplayingRecipeName = dialog.DialogResult;
var recipeName = dialog.DialogResult;
if (DisplayingRecipeName.StartsWith("Sic\\Process"))
if (recipeName.StartsWith("Sic\\Process"))
{
CurrentProcessType = "Process";
}
else if (DisplayingRecipeName.StartsWith("Sic\\Routine"))
else if (recipeName.StartsWith("Sic\\Routine"))
{
CurrentProcessType = "Routine";
}
InvokeClient.Instance.Service.DoOperation($"{SystemName}.SelectRecipe", DisplayingRecipeName);
InvokeClient.Instance.Service.DoOperation("System.SetConfig", $"PM.{SystemName}.LastRecipeName", DisplayingRecipeName); // 记录最后一次工艺文件名称
DisplayingRecipeName = recipeName;
_progressLoadRecipe.Report(DisplayingRecipeName);
InvokeClient.Instance.Service.DoOperation($"{SystemName}.SelectRecipe", recipeName);
InvokeClient.Instance.Service.DoOperation("System.SetConfig", $"PM.{SystemName}.LastRecipeName", recipeName); // 记录最后一次工艺文件名称
}
}
@ -1021,7 +1012,7 @@ namespace SicUI.Models.PMs
return dispatcher;
}
private async Task LoadRecipe(string selectedRecipePath)
private void LoadRecipe(string selectedRecipePath)
{
CurrentRecipe.Clear();
@ -1042,8 +1033,8 @@ namespace SicUI.Models.PMs
CurrentRecipe.RecipeChamberType = _columnBuilder.RecipeChamberType;
CurrentRecipe.RecipeVersion = _columnBuilder.RecipeVersion;
await CurrentRecipe.InitData(prefixPath, recipeName, recipeContent, Columns,
_columnBuilder.Configs, SystemName, GetLoadingDispatcher(), _isHideRecipeValue);
CurrentRecipe.InitData(prefixPath, recipeName, recipeContent, Columns,
_columnBuilder.Configs, SystemName, null, _isHideRecipeValue);
// 显示Cell访问白名单中的参数
SetRecipeValueVisibilityByCurrentRole();