Refactoring : TestBenchFramework --> TBF ver. 2.18.789
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
using TBF.BenchControl.GenericDevices;
|
||||
|
||||
namespace TBF.BenchControl.Elde.RegulValveTandem
|
||||
{
|
||||
public class ChangeRegulValvePositionOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(ChangeRegulValvePositionOp));
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("ChangeRegulValvePositionOp({0},{1}s)", regulValve.Name, timePulseSec.ToString("F2"));
|
||||
}
|
||||
|
||||
/// Set by the constructor
|
||||
readonly ControlBoardDev controlBoard;
|
||||
readonly Elde.RegulValve.RegulValve regulValve;
|
||||
readonly int regulValveNr;
|
||||
readonly float timePulseSec;
|
||||
|
||||
/// <summary>
|
||||
/// Set required water flow.
|
||||
/// Events: FlowSet, FlowTimeOut
|
||||
/// </summary>
|
||||
/// <param name="ControlBoard">Control board device</param>
|
||||
/// <param name="_regulValve">Regulation valve component</param>
|
||||
/// <param name="posLoPct">Lower limit of the position to be achieved</param>
|
||||
/// <param name="posHiPct">Upper limit of the position to be achieved</param>
|
||||
/// <param name="timeout">Timeout in sec. for setting the flow</param>
|
||||
/// <remarks>Only Elde.Valve flow are used, other flow on the lists are ignored</remarks>
|
||||
public ChangeRegulValvePositionOp(ControlBoardDev controlBoard, IRegulValve _regulValve, float timePulseSec)
|
||||
{
|
||||
if (controlBoard == null) throw new ArgumentNullException("ctrlBoard");
|
||||
this.controlBoard = controlBoard;
|
||||
|
||||
regulValve = _regulValve as Elde.RegulValve.RegulValve;
|
||||
if (regulValve == null) throw new ArgumentNullException("regValve is null or not Elde");
|
||||
regulValveNr = this.regulValve.Idx1;
|
||||
|
||||
this.timePulseSec = timePulseSec;
|
||||
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
float positionPct = controlBoard.RValvePosition(regulValveNr);
|
||||
log.WarnFormat("RV#={0}, actPos={1}%", regulValveNr, positionPct.ToString("F1"));
|
||||
|
||||
controlBoard.ValveMove(regulValveNr,
|
||||
RegulValveMode.PulseWidth,
|
||||
new float[2] { timePulseSec, timePulseSec },
|
||||
regulValve.StableTime);
|
||||
}
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>
|
||||
/// Event.SetFlowDone
|
||||
/// </returns>
|
||||
public Event Run()
|
||||
{
|
||||
float positionPct = controlBoard.RValvePosition(regulValveNr);
|
||||
log.WarnFormat("RV#={0}, actPos={1}%", regulValveNr, positionPct.ToString("F1"));
|
||||
|
||||
return Event.PositionReached;
|
||||
}
|
||||
|
||||
/// <summary>Stop this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
using TBF.BenchControl.Generic;
|
||||
using TBF.Boxes;
|
||||
|
||||
namespace TBF.BenchControl.Elde.RegulValveTandem
|
||||
{
|
||||
public class RegulValveTandem : ComponentBase, GenericDevices.IRegulValve
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(RegulValveTandem));
|
||||
public override string ToString() { return string.Format("RegulValve({0})", Cfg.ToString(1)); }
|
||||
|
||||
public readonly RegulValveTandemCfg RegulValveTandemCfg;
|
||||
|
||||
IDictionary<float, float> dict;
|
||||
public IDictionary<float, float> Dict { get { return dict; } }
|
||||
|
||||
ControlBoardDev controlBoard { get { return regulValve.ControlBoard; } }
|
||||
public ValveCategory Category { get { return RegulValveTandemCfg.Category; } }
|
||||
|
||||
readonly RegulValve.RegulValve regulValve;
|
||||
readonly RegulValve.RegulValve fixedRV;
|
||||
|
||||
readonly float fixedPctLo; /// [%]
|
||||
readonly float fixedPctHi; /// [%]
|
||||
|
||||
public int FlowStableSec { get { return RegulValveTandemCfg.FlowStableSec; } } /// 0..60 sec
|
||||
///
|
||||
public bool IsCoax { get { return false; } }
|
||||
|
||||
public float Position
|
||||
{
|
||||
get { return regulValve.Position; }
|
||||
}
|
||||
|
||||
|
||||
public RegulValveTandem()
|
||||
{
|
||||
}
|
||||
|
||||
public RegulValveTandem(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
|
||||
: base(cfg)
|
||||
{
|
||||
RegulValveTandemCfg = cfg as RegulValveTandemCfg;
|
||||
|
||||
regulValve = (RegulValve.RegulValve)TbfComponents.FindComponent(RegulValveTandemCfg.RegulValveName, components);
|
||||
if (regulValve == null) throw new Exception("Cannot find regulation valve");
|
||||
|
||||
fixedRV = (RegulValve.RegulValve)TbfComponents.FindComponent(RegulValveTandemCfg.FixedRVName, components);
|
||||
if (fixedRV == null) throw new Exception("Cannot find fixed RV");
|
||||
|
||||
fixedPctLo = Math.Max(0.0f, RegulValveTandemCfg.FixedRVPosition - 3.0f);
|
||||
fixedPctHi = Math.Min(100.0f, RegulValveTandemCfg.FixedRVPosition + 3.0f);
|
||||
|
||||
this.dict = new Dictionary<float, float>();
|
||||
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operation to set the water flow within tolerances
|
||||
/// Events: Event.None, Event.FlowReached, Event.FlowTimeOut
|
||||
/// </summary>
|
||||
/// <param name="flowMeter">Flowmeter component</param>
|
||||
/// <param name="requiredFlowLo">Lower limit of the required flow [m3/h]</param>
|
||||
/// <param name="requiredFlowHi">Higher limit of the required flow [m3/h]</param>
|
||||
/// <param name="pidCoef">PID coefficient (float)</param>
|
||||
/// <param name="measuredFlow">Measured flow [m3/h]</param>
|
||||
/// <param name="timeout">Timeout in [s]</param>
|
||||
/// <returns>SetFlowOp instance</returns>
|
||||
public IOperation SetFlowOp(GenericDevices.IFlowMeter flowMeter, float requiredFlowLo, float requiredFlowHi,
|
||||
float pidCoef, DoubleBox measuredFlow, int timeout)
|
||||
{
|
||||
return new SetFlowOp(controlBoard, regulValve, fixedRV, fixedPctLo, fixedPctHi,
|
||||
flowMeter, requiredFlowLo, requiredFlowHi, pidCoef, measuredFlow, timeout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operation to set the water flow within tolerances. Leave the measurement running.
|
||||
/// Events: Event.None, Event.FlowReached, Event.FlowTimeOut
|
||||
/// </summary>
|
||||
/// <param name="flowMeter">Flowmeter component</param>
|
||||
/// <param name="requiredFlowLo">Lower limit of the required flow [m3/h]</param>
|
||||
/// <param name="requiredFlowHi">Higher limit of the required flow [m3/h]</param>
|
||||
/// <param name="measuredFlow">Measured flow [m3/h]</param>
|
||||
/// <param name="timeout">Timeout in [s]</param>
|
||||
/// <returns>SetFlowOp instance</returns>
|
||||
public IOperation SetFlowAndMeasureOp(GenericDevices.IFlowMeter flowMeter, float requiredFlowLo, float requiredFlowHi,
|
||||
float pidCoef, DoubleBox measuredFlow, int timeout, float filterConstant)
|
||||
{
|
||||
return new SetFlowOp(controlBoard, regulValve, fixedRV, fixedPctLo, fixedPctHi,
|
||||
flowMeter, requiredFlowLo, requiredFlowHi, pidCoef, measuredFlow, timeout, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operation to set the regulation valve to a required position
|
||||
/// Events: Event.None
|
||||
/// </summary>
|
||||
/// <param name="flowLo">Lower limit of the required valve position in [%]</param>
|
||||
/// <param name="flowLo">Higher limit of the required valve position in [%]</param>
|
||||
/// <returns>SetPositionOp instance</returns>
|
||||
public IOperation SetRegulValvePositionOp(float pctLo, float pctHi, int timeoutMs)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IOperation ChangeRegulValvePositionOp(float timePulseSec)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2016 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Xml.Serialization;
|
||||
using TBF.BenchControl.Generic;
|
||||
|
||||
namespace TBF.BenchControl.Elde.RegulValveTandem
|
||||
{
|
||||
public class RegulValveTandemCfg : ComponentCfgBase, IChildComponentCfg
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(RegulValveTandemCfg) })[0];
|
||||
protected override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl() { return new RegulValveTandemCfgCtrl(); }
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public ValveCategory Category; /// Feeding, Output or All
|
||||
public string RegulValveName; /// Name of the regulation valve used to control the flow
|
||||
public string FixedRVName; /// Name of the regulation valve with a fixed position
|
||||
public float FixedRVPosition; /// Fixed RV position 0 .. 100 in [%]
|
||||
public bool StoredPositionReuse; /// true = store and re-use previous regulation valve positions
|
||||
public int FlowStableSec; /// 0..60 sec
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
RegulValveTandemCfg()
|
||||
{
|
||||
}
|
||||
|
||||
public RegulValveTandemCfg(string name, IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Name = name;
|
||||
Factory = factory;
|
||||
ParentName = string.Empty;
|
||||
Category = ValveCategory.Output;
|
||||
RegulValveName = "RV1";
|
||||
FixedRVName = "RV2";
|
||||
FixedRVPosition = 50.0f;
|
||||
StoredPositionReuse = false;
|
||||
FlowStableSec = 5;
|
||||
}
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
return string.Format("Name={0}, RegulVName={1}, FixedRVName={2}, FixedRVPos={3}%, PosReuse={4}, FlowStable={5}s",
|
||||
Name,
|
||||
RegulValveName,
|
||||
FixedRVName,
|
||||
FixedRVPosition.ToString("F0"),
|
||||
StoredPositionReuse,
|
||||
FlowStableSec);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using log4net;
|
||||
using TBF.BenchControl.Generic;
|
||||
|
||||
namespace TBF.BenchControl.Elde.RegulValveTandem
|
||||
{
|
||||
public partial class RegulValveTandemCfgCtrl : UserControl, IComponentCfgCtrl
|
||||
{
|
||||
static readonly ILog log = LogManager.GetLogger(typeof(RegulValveTandemCfgCtrl));
|
||||
|
||||
ComponentParametersDlg parent;
|
||||
|
||||
public bool ShowMore { get { return true; } }
|
||||
|
||||
RegulValveTandemCfg config;
|
||||
public IComponentCfg Config
|
||||
{
|
||||
get { return config as IComponentCfg; }
|
||||
set
|
||||
{
|
||||
config = value as RegulValveTandemCfg;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public RegulValveTandemCfgCtrl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void RegulationValveCfgCtrl_Load(object sender, EventArgs e)
|
||||
{
|
||||
parent = ParentForm as ComponentParametersDlg;
|
||||
if (parent == null) return;
|
||||
|
||||
if (parent.TbfComponents != null)
|
||||
{
|
||||
foreach (var cmpnt in parent.TbfComponents)
|
||||
{
|
||||
if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Elde.RegulValve.RegulValveFactory)
|
||||
{
|
||||
regulValveNameComboBox.Items.Add(cmpnt.Name);
|
||||
fixedRVNameComboBox.Items.Add(cmpnt.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
categoryComboBox.Items.Add(ValveCategory.All.ToString());
|
||||
categoryComboBox.Items.Add(ValveCategory.Feeding.ToString());
|
||||
categoryComboBox.Items.Add(ValveCategory.Output.ToString());
|
||||
|
||||
Redraw();
|
||||
}
|
||||
|
||||
public void Closing()
|
||||
{
|
||||
}
|
||||
|
||||
void Redraw()
|
||||
{
|
||||
if (config == null) return; /// Control was not loaded, settings were not changed
|
||||
|
||||
classNameLabel.Text = config.Factory.ClassName;
|
||||
nameTextBox.Text = config.Name;
|
||||
categoryComboBox.Text = config.Category.ToString();
|
||||
regulValveNameComboBox.Text = string.IsNullOrEmpty(config.RegulValveName) ? "---" : config.RegulValveName;
|
||||
fixedRVNameComboBox.Text = string.IsNullOrEmpty(config.FixedRVName) ? "---" : config.FixedRVName;
|
||||
fixedRVPositionTextBox.Text = config.FixedRVPosition.ToString("F0");
|
||||
storedPosReuseCheckBox.Checked = config.StoredPositionReuse;
|
||||
flowStableSecTextBox.Text = config.FlowStableSec.ToString();
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
nameTextBox.Enabled = true;
|
||||
categoryComboBox.Enabled = true;
|
||||
regulValveNameComboBox.Enabled = true;
|
||||
fixedRVNameComboBox.Enabled = true;
|
||||
fixedRVPositionTextBox.Enabled = true;
|
||||
storedPosReuseCheckBox.Enabled = true;
|
||||
flowStableSecTextBox.Enabled = true;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
if (!categoryComboBox.Text.Equals(ValveCategory.All.ToString()) &&
|
||||
!categoryComboBox.Text.Equals(ValveCategory.Feeding.ToString()) &&
|
||||
!categoryComboBox.Text.Equals(ValveCategory.Output.ToString()))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Category'";
|
||||
}
|
||||
|
||||
if (!regulValveNameComboBox.Items.Contains(regulValveNameComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Regulation valve'";
|
||||
}
|
||||
|
||||
if (!fixedRVNameComboBox.Items.Contains(fixedRVNameComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Fixed reg. valve'";
|
||||
}
|
||||
|
||||
int dummy;
|
||||
if (!int.TryParse(fixedRVPositionTextBox.Text, out dummy) || dummy < 0 || dummy > 100)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Stable time' should be between 200 and 1500 ms in 50 ms steps";
|
||||
}
|
||||
|
||||
if (!int.TryParse(flowStableSecTextBox.Text, out dummy) || dummy < 0 || dummy > 60)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Flow stable' should be between 0 and 60 sec";
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags UpdateCfg()
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
|
||||
///
|
||||
if (!config.Name.Equals(nameTextBox.Text))
|
||||
{
|
||||
config.Name = nameTextBox.Text;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
ValveCategory newCategory;
|
||||
if (categoryComboBox.Text.Equals(ValveCategory.All.ToString())) newCategory = ValveCategory.All;
|
||||
else if (categoryComboBox.Text.Equals(ValveCategory.Feeding.ToString())) newCategory = ValveCategory.Feeding;
|
||||
else if (categoryComboBox.Text.Equals(ValveCategory.Bench.ToString())) newCategory = ValveCategory.Bench;
|
||||
else if (categoryComboBox.Text.Equals(ValveCategory.Output.ToString())) newCategory = ValveCategory.Output;
|
||||
else newCategory = ValveCategory.None;
|
||||
if (newCategory != config.Category)
|
||||
{
|
||||
config.Category = newCategory;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
string str = regulValveNameComboBox.Text.Equals("---") ? string.Empty : regulValveNameComboBox.Text;
|
||||
if (!config.RegulValveName.Equals(str))
|
||||
{
|
||||
config.RegulValveName = str;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
str = fixedRVNameComboBox.Text.Equals("---") ? string.Empty : fixedRVNameComboBox.Text;
|
||||
if (!config.FixedRVName.Equals(str))
|
||||
{
|
||||
config.FixedRVName = str;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
int tmp = int.Parse(fixedRVPositionTextBox.Text);
|
||||
if (config.FixedRVPosition != (float)tmp)
|
||||
{
|
||||
config.FixedRVPosition = (float)tmp;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
bool btmp = storedPosReuseCheckBox.Checked;
|
||||
if (config.StoredPositionReuse != btmp)
|
||||
{
|
||||
config.StoredPositionReuse = btmp;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
tmp = int.Parse(flowStableSecTextBox.Text);
|
||||
if (config.FlowStableSec != tmp)
|
||||
{
|
||||
config.FlowStableSec = tmp;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
||||
///
|
||||
namespace TBF.BenchControl.Elde.RegulValveTandem
|
||||
{
|
||||
partial class RegulValveTandemCfgCtrl
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.regulValveNameLabel = new System.Windows.Forms.Label();
|
||||
this.nameTextBox = new System.Windows.Forms.TextBox();
|
||||
this.nameLabel = new System.Windows.Forms.Label();
|
||||
this.classNameLabel = new System.Windows.Forms.Label();
|
||||
this.regulValveNameComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.storedPosReuseCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.flowStableSecTextBox = new System.Windows.Forms.TextBox();
|
||||
this.flowStableSecLabel = new System.Windows.Forms.Label();
|
||||
this.fixedRVNameComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.fixedRVNameLabel = new System.Windows.Forms.Label();
|
||||
this.fixedRVPositionTextBox = new System.Windows.Forms.TextBox();
|
||||
this.fixedRVPositionLabel = new System.Windows.Forms.Label();
|
||||
this.categoryComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.categoryLabel = new System.Windows.Forms.Label();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// regulValveNameLabel
|
||||
//
|
||||
this.regulValveNameLabel.AutoSize = true;
|
||||
this.regulValveNameLabel.Location = new System.Drawing.Point(28, 93);
|
||||
this.regulValveNameLabel.Name = "regulValveNameLabel";
|
||||
this.regulValveNameLabel.Size = new System.Drawing.Size(87, 13);
|
||||
this.regulValveNameLabel.TabIndex = 5;
|
||||
this.regulValveNameLabel.Text = "Regulation valve";
|
||||
//
|
||||
// nameTextBox
|
||||
//
|
||||
this.nameTextBox.Enabled = false;
|
||||
this.nameTextBox.Location = new System.Drawing.Point(138, 41);
|
||||
this.nameTextBox.Name = "nameTextBox";
|
||||
this.nameTextBox.Size = new System.Drawing.Size(130, 20);
|
||||
this.nameTextBox.TabIndex = 2;
|
||||
//
|
||||
// nameLabel
|
||||
//
|
||||
this.nameLabel.AutoSize = true;
|
||||
this.nameLabel.Location = new System.Drawing.Point(28, 44);
|
||||
this.nameLabel.Name = "nameLabel";
|
||||
this.nameLabel.Size = new System.Drawing.Size(35, 13);
|
||||
this.nameLabel.TabIndex = 1;
|
||||
this.nameLabel.Text = "Name";
|
||||
//
|
||||
// classNameLabel
|
||||
//
|
||||
this.classNameLabel.AutoSize = true;
|
||||
this.classNameLabel.Location = new System.Drawing.Point(135, 14);
|
||||
this.classNameLabel.Name = "classNameLabel";
|
||||
this.classNameLabel.Size = new System.Drawing.Size(89, 13);
|
||||
this.classNameLabel.TabIndex = 0;
|
||||
this.classNameLabel.Text = "ComponentName";
|
||||
//
|
||||
// regulValveNameComboBox
|
||||
//
|
||||
this.regulValveNameComboBox.Enabled = false;
|
||||
this.regulValveNameComboBox.FormattingEnabled = true;
|
||||
this.regulValveNameComboBox.Location = new System.Drawing.Point(138, 90);
|
||||
this.regulValveNameComboBox.Name = "regulValveNameComboBox";
|
||||
this.regulValveNameComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.regulValveNameComboBox.TabIndex = 6;
|
||||
//
|
||||
// storedPosReuseCheckBox
|
||||
//
|
||||
this.storedPosReuseCheckBox.AutoSize = true;
|
||||
this.storedPosReuseCheckBox.Enabled = false;
|
||||
this.storedPosReuseCheckBox.Location = new System.Drawing.Point(31, 171);
|
||||
this.storedPosReuseCheckBox.Name = "storedPosReuseCheckBox";
|
||||
this.storedPosReuseCheckBox.Size = new System.Drawing.Size(162, 17);
|
||||
this.storedPosReuseCheckBox.TabIndex = 11;
|
||||
this.storedPosReuseCheckBox.Text = "Enable stored position re-use";
|
||||
this.storedPosReuseCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// flowStableSecTextBox
|
||||
//
|
||||
this.flowStableSecTextBox.Enabled = false;
|
||||
this.flowStableSecTextBox.Location = new System.Drawing.Point(138, 194);
|
||||
this.flowStableSecTextBox.Name = "flowStableSecTextBox";
|
||||
this.flowStableSecTextBox.Size = new System.Drawing.Size(46, 20);
|
||||
this.flowStableSecTextBox.TabIndex = 13;
|
||||
//
|
||||
// flowStableSecLabel
|
||||
//
|
||||
this.flowStableSecLabel.AutoSize = true;
|
||||
this.flowStableSecLabel.Location = new System.Drawing.Point(28, 197);
|
||||
this.flowStableSecLabel.Name = "flowStableSecLabel";
|
||||
this.flowStableSecLabel.Size = new System.Drawing.Size(74, 13);
|
||||
this.flowStableSecLabel.TabIndex = 12;
|
||||
this.flowStableSecLabel.Text = "Flow stable [s]";
|
||||
//
|
||||
// fixedRVNameComboBox
|
||||
//
|
||||
this.fixedRVNameComboBox.Enabled = false;
|
||||
this.fixedRVNameComboBox.FormattingEnabled = true;
|
||||
this.fixedRVNameComboBox.Location = new System.Drawing.Point(138, 115);
|
||||
this.fixedRVNameComboBox.Name = "fixedRVNameComboBox";
|
||||
this.fixedRVNameComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.fixedRVNameComboBox.TabIndex = 8;
|
||||
//
|
||||
// fixedRVNameLabel
|
||||
//
|
||||
this.fixedRVNameLabel.AutoSize = true;
|
||||
this.fixedRVNameLabel.Location = new System.Drawing.Point(28, 118);
|
||||
this.fixedRVNameLabel.Name = "fixedRVNameLabel";
|
||||
this.fixedRVNameLabel.Size = new System.Drawing.Size(82, 13);
|
||||
this.fixedRVNameLabel.TabIndex = 7;
|
||||
this.fixedRVNameLabel.Text = "Fixed reg. valve";
|
||||
//
|
||||
// fixedRVPositionTextBox
|
||||
//
|
||||
this.fixedRVPositionTextBox.Enabled = false;
|
||||
this.fixedRVPositionTextBox.Location = new System.Drawing.Point(138, 140);
|
||||
this.fixedRVPositionTextBox.Name = "fixedRVPositionTextBox";
|
||||
this.fixedRVPositionTextBox.Size = new System.Drawing.Size(46, 20);
|
||||
this.fixedRVPositionTextBox.TabIndex = 10;
|
||||
//
|
||||
// fixedRVPositionLabel
|
||||
//
|
||||
this.fixedRVPositionLabel.AutoSize = true;
|
||||
this.fixedRVPositionLabel.Location = new System.Drawing.Point(28, 143);
|
||||
this.fixedRVPositionLabel.Name = "fixedRVPositionLabel";
|
||||
this.fixedRVPositionLabel.Size = new System.Drawing.Size(89, 13);
|
||||
this.fixedRVPositionLabel.TabIndex = 9;
|
||||
this.fixedRVPositionLabel.Text = "Fixed RV position";
|
||||
//
|
||||
// categoryComboBox
|
||||
//
|
||||
this.categoryComboBox.Enabled = false;
|
||||
this.categoryComboBox.FormattingEnabled = true;
|
||||
this.categoryComboBox.Location = new System.Drawing.Point(138, 65);
|
||||
this.categoryComboBox.Name = "categoryComboBox";
|
||||
this.categoryComboBox.Size = new System.Drawing.Size(81, 21);
|
||||
this.categoryComboBox.TabIndex = 4;
|
||||
//
|
||||
// categoryLabel
|
||||
//
|
||||
this.categoryLabel.AutoSize = true;
|
||||
this.categoryLabel.Location = new System.Drawing.Point(28, 68);
|
||||
this.categoryLabel.Name = "categoryLabel";
|
||||
this.categoryLabel.Size = new System.Drawing.Size(49, 13);
|
||||
this.categoryLabel.TabIndex = 3;
|
||||
this.categoryLabel.Text = "Category";
|
||||
//
|
||||
// RegulValveTandemCfgCtrl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.categoryComboBox);
|
||||
this.Controls.Add(this.categoryLabel);
|
||||
this.Controls.Add(this.fixedRVPositionTextBox);
|
||||
this.Controls.Add(this.fixedRVPositionLabel);
|
||||
this.Controls.Add(this.fixedRVNameComboBox);
|
||||
this.Controls.Add(this.fixedRVNameLabel);
|
||||
this.Controls.Add(this.flowStableSecTextBox);
|
||||
this.Controls.Add(this.flowStableSecLabel);
|
||||
this.Controls.Add(this.storedPosReuseCheckBox);
|
||||
this.Controls.Add(this.regulValveNameComboBox);
|
||||
this.Controls.Add(this.regulValveNameLabel);
|
||||
this.Controls.Add(this.nameTextBox);
|
||||
this.Controls.Add(this.nameLabel);
|
||||
this.Controls.Add(this.classNameLabel);
|
||||
this.Name = "RegulValveTandemCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(300, 700);
|
||||
this.Load += new System.EventHandler(this.RegulationValveCfgCtrl_Load);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label regulValveNameLabel;
|
||||
private System.Windows.Forms.TextBox nameTextBox;
|
||||
private System.Windows.Forms.Label nameLabel;
|
||||
private System.Windows.Forms.Label classNameLabel;
|
||||
private System.Windows.Forms.ComboBox regulValveNameComboBox;
|
||||
private System.Windows.Forms.CheckBox storedPosReuseCheckBox;
|
||||
private System.Windows.Forms.TextBox flowStableSecTextBox;
|
||||
private System.Windows.Forms.Label flowStableSecLabel;
|
||||
private System.Windows.Forms.ComboBox fixedRVNameComboBox;
|
||||
private System.Windows.Forms.Label fixedRVNameLabel;
|
||||
private System.Windows.Forms.TextBox fixedRVPositionTextBox;
|
||||
private System.Windows.Forms.Label fixedRVPositionLabel;
|
||||
private System.Windows.Forms.ComboBox categoryComboBox;
|
||||
private System.Windows.Forms.Label categoryLabel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -0,0 +1,26 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2016 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.BenchControl.Generic;
|
||||
|
||||
namespace TBF.BenchControl.Elde.RegulValveTandem
|
||||
{
|
||||
public class RegulValveTandemFactory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return "RegulationValveTandem"; } }
|
||||
|
||||
public void ResetStaticProperties() { RegulValveTandem.ResetStaticProperties(); }
|
||||
|
||||
public IComponent DummyComponent() { return new RegulValveTandem(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new RegulValveTandem(cfg, components); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new RegulValveTandemCfg("RV", this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(RegulValveTandemCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,380 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
using TBF.BenchControl.GenericDevices;
|
||||
using TBF.Boxes;
|
||||
|
||||
namespace TBF.BenchControl.Elde.RegulValveTandem
|
||||
{
|
||||
public class SetFlowOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(SetFlowOp));
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("SetFlowOp({0}, Qfrom={1}, Qto={2}, PID={3})", regulValve.Name, finalReqFlowLo, finalReqFlowHi, pidCoef);
|
||||
}
|
||||
|
||||
/// Set by the constructor
|
||||
readonly ControlBoardDev controlBoard;
|
||||
readonly Elde.RegulValve.RegulValve regulValve;
|
||||
readonly int regulValveNr;
|
||||
readonly Elde.RegulValve.RegulValve fixedRV;
|
||||
readonly int fixedRVNr;
|
||||
readonly float fixedPctLo;
|
||||
readonly float fixedPctHi;
|
||||
readonly int flowMeterNr;
|
||||
readonly float finalReqFlowLo;
|
||||
readonly float finalReqFlowHi;
|
||||
readonly float reqFlowAve;
|
||||
readonly float pidCoef;
|
||||
readonly int timeout;
|
||||
readonly bool leaveMeasurementRunning;
|
||||
|
||||
readonly float nominalFlow;
|
||||
|
||||
/// Process values
|
||||
enum OpState
|
||||
{
|
||||
Idle = 0,
|
||||
IssueSetPositionCommand,
|
||||
SettingPosition,
|
||||
IssueSetPositionCommand_FixedRV,
|
||||
SettingPosition_FixedRV,
|
||||
IssueSetFlowCommand,
|
||||
SettingFlow,
|
||||
FlowReached,
|
||||
}
|
||||
OpState opState;
|
||||
|
||||
float currentReqFlowLo;
|
||||
float currentReqFlowHi;
|
||||
float targetPositionLo;
|
||||
float targetPositionHi;
|
||||
|
||||
int expireTime;
|
||||
DoubleBox measuredFlow;
|
||||
int flowWithinBoundsTime;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set required water flow. Conditionally leave the measurement running.
|
||||
/// Events: FlowSet, FlowTimeOut
|
||||
/// </summary>
|
||||
/// <param name="ControlBoard">Control board device</param>
|
||||
/// <param name="_regulValve">Regulation valve component</param>
|
||||
/// <param name="fxdRV">Regulation valve set to a fixed position</param>
|
||||
/// <param name="fixedPctLo">Lower limit of the fixed position of the fixed reg.v.</param>
|
||||
/// <param name="fixedPctHi">Upper limit of the fixed position of the fixed reg.v.</param>
|
||||
/// <param name="flowMeter">Flowmeter component</param>
|
||||
/// <param name="requiredFlowLo">Lower limit of the flow to be achieved in [m3/h]</param>
|
||||
/// <param name="requiredFlowHi">Upper limit of the flow to be achieved in [m3/h]</param>
|
||||
/// <param name="pidCoef">PID coefficient (float)</param>
|
||||
/// <param name="timeout">Timeout for the flow setting in [s]</param>
|
||||
/// <param name="leaveMeasurementRunning">true = Leave the measurement running after op. stop</param>
|
||||
/// <remarks>Only Elde.Valve flow are used, other flow on the lists are ignored</remarks>
|
||||
public SetFlowOp(ControlBoardDev controlBoard, IRegulValve regV, IRegulValve fxdRV, float fxdPctLo, float fxdPctHi,
|
||||
IFlowMeter flowMeter, float requiredFlowLo, float requiredFlowHi, float pidCoef, DoubleBox measuredFlow,
|
||||
int timeout, bool leaveMeasurementRunning)
|
||||
{
|
||||
if (controlBoard == null) throw new ArgumentNullException("ctrlBoard");
|
||||
this.controlBoard = controlBoard;
|
||||
|
||||
regulValve = regV as Elde.RegulValve.RegulValve;
|
||||
if (regulValve == null) throw new ArgumentNullException("regValve is null or not Elde");
|
||||
regulValveNr = regulValve.Idx1;
|
||||
|
||||
fixedRV = fxdRV as Elde.RegulValve.RegulValve;
|
||||
if (fixedRV == null) throw new ArgumentNullException("regValve is null or not Elde");
|
||||
fixedRVNr = fixedRV.Idx1;
|
||||
|
||||
this.fixedPctLo = fxdPctLo;
|
||||
this.fixedPctHi = fxdPctHi;
|
||||
|
||||
if (flowMeter is Elde.FlowMeter.FlowMeter)
|
||||
{
|
||||
this.flowMeterNr = (flowMeter as Elde.FlowMeter.FlowMeter).Idx1;
|
||||
}
|
||||
else if (flowMeter is Elde.FlowMeterTwins.FlowMeter)
|
||||
{
|
||||
this.flowMeterNr = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentNullException("flowMeter is null or not Elde");
|
||||
}
|
||||
|
||||
nominalFlow = flowMeter.NominalFlow;
|
||||
|
||||
this.finalReqFlowLo = requiredFlowLo;
|
||||
this.finalReqFlowHi = requiredFlowHi;
|
||||
this.reqFlowAve = (requiredFlowLo + requiredFlowHi) / 2.0f;
|
||||
this.pidCoef = pidCoef;
|
||||
this.measuredFlow = measuredFlow;
|
||||
|
||||
this.timeout = timeout;
|
||||
|
||||
this.leaveMeasurementRunning = leaveMeasurementRunning;
|
||||
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set required water flow - Do not leave the measurement running.
|
||||
/// Events: FlowSet
|
||||
/// </summary>
|
||||
public SetFlowOp(ControlBoardDev controlBoard, IRegulValve regValve, IRegulValve fixedRV, float fixedPctLo, float fixedPctHi,
|
||||
IFlowMeter flowMeter, float requiredFlowLo, float requiredFlowHi, float pidCoef, DoubleBox measuredFlow, int timeout)
|
||||
: this(controlBoard, regValve, fixedRV, fixedPctLo, fixedPctHi, flowMeter, requiredFlowLo, requiredFlowHi, pidCoef, measuredFlow, timeout, false)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set required water flow - No timeout.
|
||||
/// Events: FlowSet
|
||||
/// </summary>
|
||||
public SetFlowOp(ControlBoardDev controlBoard, IRegulValve regValve, IRegulValve fixedRV, float fixedPctLo, float fixedPctHi,
|
||||
IFlowMeter flowMeter, float requiredFlowLo, float requiredFlowHi, float pidCoef, DoubleBox measuredFlow)
|
||||
: this(controlBoard, regValve, fixedRV, fixedPctLo, fixedPctHi, flowMeter, requiredFlowLo, pidCoef, requiredFlowHi, measuredFlow, int.MaxValue, false)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetch target position limits from the dictionary or return false
|
||||
/// </summary>
|
||||
/// <param name="avgReqFlow">Average of the flow targer range (input)</param>
|
||||
/// <param name="positionLo">Target valve position low limit (output)</param>
|
||||
/// <param name="positionHi">Target valve position high limit (output)</param>
|
||||
/// <returns>true when positions for the target flow are stored in the memory, otherwise return false</returns>
|
||||
bool FetchTargetPosition(float avgReqFlow, out float positionLo, out float positionHi)
|
||||
{
|
||||
float targetPosition;
|
||||
if (regulValve.Dict.TryGetValue(avgReqFlow, out targetPosition))
|
||||
{
|
||||
positionLo = Math.Max(targetPosition * 0.95f, 0.0f);
|
||||
positionHi = Math.Min(targetPosition * 1.05f, 100.0f);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
positionLo = 0.0f;
|
||||
positionHi = 0.0f;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void StoreTargetPosition(float avgReqFlow, float actPosition)
|
||||
{
|
||||
if (!regulValve.Dict.ContainsKey(reqFlowAve))
|
||||
{
|
||||
regulValve.Dict.Add(new KeyValuePair<float, float>(avgReqFlow, actPosition));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
double flowMtrFreq = controlBoard.ReferenceFreq;
|
||||
currentReqFlowLo = reqFlowAve;
|
||||
currentReqFlowHi = reqFlowAve;
|
||||
///
|
||||
if (flowMtrFreq != 0)
|
||||
{
|
||||
double flow = flowMtrFreq * nominalFlow / 2000.0;
|
||||
if (measuredFlow != null) measuredFlow.Val = flow;
|
||||
if (flow >= reqFlowAve) currentReqFlowLo = finalReqFlowLo;
|
||||
if (flow <= reqFlowAve) currentReqFlowHi = finalReqFlowHi;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentReqFlowLo = finalReqFlowLo; /// Unexpected case when flowMtrFreq==0
|
||||
currentReqFlowHi = finalReqFlowHi;
|
||||
}
|
||||
|
||||
flowWithinBoundsTime = 0;
|
||||
|
||||
if (regulValve.RegulValveCfg.StoredPositionReuse && FetchTargetPosition(reqFlowAve, out targetPositionLo, out targetPositionHi))
|
||||
{
|
||||
log.InfoFormat("Start(): rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3} FETCHED: posLo={4} posHi={5}",
|
||||
regulValveNr, flowMeterNr, currentReqFlowLo, currentReqFlowHi, targetPositionLo, targetPositionHi);
|
||||
|
||||
opState = OpState.IssueSetPositionCommand;
|
||||
}
|
||||
else
|
||||
{
|
||||
log.InfoFormat("Start(): rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3}",
|
||||
regulValveNr, flowMeterNr, currentReqFlowLo, currentReqFlowHi);
|
||||
|
||||
opState = OpState.IssueSetPositionCommand_FixedRV;
|
||||
}
|
||||
|
||||
expireTime = StateMachine.Time + timeout;
|
||||
if (expireTime < 0) expireTime = int.MaxValue;
|
||||
|
||||
TestMethods tm = 0;
|
||||
StopDevs sd = 0;
|
||||
// '_regulValve.RegulValveTandemCfg.PidCoef' replaced by a casted operation parameter 'pidCoef'
|
||||
controlBoard.SendCommand(Command.Start, flowMeterNr, controlBoard.Route,
|
||||
int.MaxValue, int.MaxValue, tm,
|
||||
0.0f, (int)pidCoef, 0, sd);
|
||||
}
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>
|
||||
/// Event.None, Event.FlowReached, Event.RegulValveTimeOut, Event.OpArgumentError
|
||||
/// </returns>
|
||||
public Event Run()
|
||||
{
|
||||
float rvPosition = controlBoard.RValvePosition(regulValveNr);
|
||||
float fixedRVPosition = controlBoard.RValvePosition(fixedRVNr);
|
||||
double flowMtrFreq = controlBoard.ReferenceFreq;
|
||||
double flow = flowMtrFreq * nominalFlow / 2000.0;
|
||||
|
||||
if (flowMtrFreq != 0)
|
||||
{
|
||||
if (measuredFlow != null) measuredFlow.Val = flow;
|
||||
if (flow >= reqFlowAve) currentReqFlowLo = finalReqFlowLo;
|
||||
if (flow <= reqFlowAve) currentReqFlowHi = finalReqFlowHi;
|
||||
}
|
||||
|
||||
log.InfoFormat("Run(): rv#={0} pos={1}% freq={2} flow={3} opState={4}",
|
||||
regulValveNr, rvPosition.ToString("F1"), flowMtrFreq, flow, opState);
|
||||
|
||||
if (opState == OpState.IssueSetPositionCommand)
|
||||
{
|
||||
///
|
||||
/// Done once, issues an appropriate ValveMove(...) command
|
||||
///
|
||||
controlBoard.ValveMove(regulValveNr, RegulValveMode.TargetPosition,
|
||||
new float[2] { targetPositionLo, targetPositionHi },
|
||||
regulValve.StableTime);
|
||||
|
||||
opState = OpState.SettingPosition;
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.SettingPosition)
|
||||
{
|
||||
///
|
||||
/// Repeated untill position is reached
|
||||
///
|
||||
if ((targetPositionLo <= rvPosition) && (rvPosition <= targetPositionHi))
|
||||
{
|
||||
opState = OpState.IssueSetPositionCommand_FixedRV;
|
||||
}
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.IssueSetPositionCommand_FixedRV)
|
||||
{
|
||||
///
|
||||
/// Done once, issues an appropriate ValveMove(...) command
|
||||
///
|
||||
controlBoard.ValveMove(fixedRVNr, RegulValveMode.TargetPosition,
|
||||
new float[2] { fixedPctLo, fixedPctHi },
|
||||
regulValve.StableTime);
|
||||
|
||||
opState = OpState.SettingPosition_FixedRV;
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.SettingPosition_FixedRV)
|
||||
{
|
||||
///
|
||||
/// Repeated untill position is reached
|
||||
///
|
||||
if ((fixedPctLo <= fixedRVPosition) && (fixedRVPosition <= fixedPctHi))
|
||||
{
|
||||
opState = OpState.IssueSetFlowCommand;
|
||||
}
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.IssueSetFlowCommand)
|
||||
{
|
||||
///
|
||||
/// Done once, issues an appropriate ValveMove(...) command
|
||||
///
|
||||
if (currentReqFlowLo >= currentReqFlowHi || currentReqFlowLo > nominalFlow || currentReqFlowHi <= 0)
|
||||
{
|
||||
return Event.OpArgumentError;
|
||||
}
|
||||
|
||||
log.InfoFormat("Run(): rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3}",
|
||||
regulValveNr, flowMeterNr, currentReqFlowLo, currentReqFlowHi);
|
||||
|
||||
float freqLo = 2000.0f * currentReqFlowLo / nominalFlow;
|
||||
float freqHi = 2000.0f * currentReqFlowHi / nominalFlow;
|
||||
controlBoard.ValveMove(regulValveNr, RegulValveMode.TargetFrequency,
|
||||
new float[2] { freqLo, freqHi },
|
||||
regulValve.StableTime);
|
||||
|
||||
opState = OpState.SettingFlow;
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.SettingFlow)
|
||||
{
|
||||
///
|
||||
/// Repeated untill the required flow is reached
|
||||
///
|
||||
if ((currentReqFlowLo <= flow) && (flow <= currentReqFlowHi))
|
||||
{
|
||||
if (flowWithinBoundsTime++ >= regulValve.FlowStableSec)
|
||||
{
|
||||
if (regulValve.RegulValveCfg.StoredPositionReuse)
|
||||
{
|
||||
float storedPosition;
|
||||
if (regulValve.Dict.TryGetValue(reqFlowAve, out storedPosition))
|
||||
{
|
||||
/// update the stored valve position
|
||||
StoreTargetPosition(reqFlowAve, (rvPosition + storedPosition) / 2.0f);
|
||||
log.InfoFormat("Run(): rv#={0} reqFlow={1} pos={2}% stored={3} <--- Updating a stored position",
|
||||
regulValveNr, reqFlowAve, rvPosition.ToString("F1"), storedPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
/// store the valve position
|
||||
StoreTargetPosition(reqFlowAve, rvPosition);
|
||||
log.InfoFormat("Run(): rv#={0} reqFlow={1} pos={2}% <--- Storing a new position",
|
||||
regulValveNr, reqFlowAve, rvPosition.ToString("F1"));
|
||||
}
|
||||
}
|
||||
opState = OpState.FlowReached;
|
||||
return Event.FlowReached;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Event.None;
|
||||
}
|
||||
}
|
||||
else if (StateMachine.Time > expireTime)
|
||||
{
|
||||
return Event.RegulValveTimeOut;
|
||||
}
|
||||
else
|
||||
{
|
||||
flowWithinBoundsTime = 0;
|
||||
return Event.None;
|
||||
}
|
||||
}
|
||||
else /// opState == OpState.FlowReached
|
||||
{
|
||||
return Event.FlowReached;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
opState = OpState.Idle;
|
||||
|
||||
if (leaveMeasurementRunning) return;
|
||||
|
||||
/// Stop measurement
|
||||
TestMethods tm = 0;
|
||||
StopDevs sd = StopDevs.RegValveRegulation;
|
||||
controlBoard.SendCommand(Command.Stop, flowMeterNr, controlBoard.Route,
|
||||
50000, 50000, tm,
|
||||
0.0f, 20, 0, sd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
using TBF.BenchControl.GenericDevices;
|
||||
|
||||
namespace TBF.BenchControl.Elde.RegulValveTandem
|
||||
{
|
||||
public class SetRegulValvePositionOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(SetRegulValvePositionOp));
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("SetRegulValvePositionOp({0},{1},{2})", regulValve.Name, posLoPct, posHiPct);
|
||||
}
|
||||
|
||||
/// Set by the constructor
|
||||
readonly ControlBoardDev controlBoard;
|
||||
readonly Elde.RegulValve.RegulValve regulValve;
|
||||
readonly int regulValveNr;
|
||||
readonly float posLoPct;
|
||||
readonly float posHiPct;
|
||||
readonly int timeout;
|
||||
|
||||
/// Process values
|
||||
bool firstRun;
|
||||
int expireTime;
|
||||
bool positionReached;
|
||||
|
||||
/// <summary>
|
||||
/// Set required water flow.
|
||||
/// Events: FlowSet, FlowTimeOut
|
||||
/// </summary>
|
||||
/// <param name="ControlBoard">Control board device</param>
|
||||
/// <param name="_regulValve">Regulation valve component</param>
|
||||
/// <param name="posLoPct">Lower limit of the position to be achieved</param>
|
||||
/// <param name="posHiPct">Upper limit of the position to be achieved</param>
|
||||
/// <param name="timeout">Timeout in sec. for setting the flow</param>
|
||||
/// <remarks>Only Elde.Valve flow are used, other flow on the lists are ignored</remarks>
|
||||
public SetRegulValvePositionOp(ControlBoardDev controlBoard, IRegulValve regV, float posLoPct, float posHiPct, int timeout)
|
||||
{
|
||||
if (controlBoard == null) throw new ArgumentNullException("ctrlBoard");
|
||||
this.controlBoard = controlBoard;
|
||||
|
||||
regulValve = regV as Elde.RegulValve.RegulValve;
|
||||
if (regulValve == null) throw new ArgumentNullException("regValve is null or not Elde");
|
||||
regulValveNr = this.regulValve.Idx1;
|
||||
|
||||
this.posLoPct = posLoPct;
|
||||
this.posHiPct = posHiPct;
|
||||
|
||||
this.timeout = timeout;
|
||||
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set required water flow - no timeout.
|
||||
/// Events: FlowSet
|
||||
/// </summary>
|
||||
public SetRegulValvePositionOp(ControlBoardDev controlBoard, RegulValveTandem regValve, float posLoPct, float posHiPct)
|
||||
: this(controlBoard, regValve, posLoPct, posHiPct, int.MaxValue)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
firstRun = true;
|
||||
positionReached = false;
|
||||
expireTime = StateMachine.Time + timeout;
|
||||
log.InfoFormat("Start(): RV#={0}, reqPosLo={1}%, reqPosHi={2}%", regulValveNr, posLoPct.ToString("F1"), posHiPct.ToString("F1"));
|
||||
}
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>
|
||||
/// Event.None . . . . . . . busy adjusting position
|
||||
/// Event.PositionReached . . position reached
|
||||
/// Event.OpArgumentError . . invalid required position
|
||||
/// </returns>
|
||||
public Event Run()
|
||||
{
|
||||
if (firstRun)
|
||||
{
|
||||
if (posLoPct >= posHiPct || posLoPct >= 100.0f || posHiPct <= 0)
|
||||
{
|
||||
return Event.OpArgumentError;
|
||||
}
|
||||
|
||||
firstRun = false;
|
||||
|
||||
controlBoard.ValveMove(regulValveNr,
|
||||
RegulValveMode.TargetPosition,
|
||||
new float[2] { posLoPct, posHiPct },
|
||||
regulValve.StableTime);
|
||||
return Event.None;
|
||||
}
|
||||
|
||||
if (positionReached) return Event.PositionReached;
|
||||
|
||||
float positionPct = controlBoard.RValvePosition(regulValveNr);
|
||||
log.WarnFormat("Run(): RV#={0}, actPos={1}%", regulValveNr, positionPct.ToString("F1"));
|
||||
|
||||
if (posLoPct >= posHiPct || posLoPct >= 100.0f || posHiPct <= 0)
|
||||
{
|
||||
return Event.OpArgumentError;
|
||||
}
|
||||
else if (posLoPct <= positionPct && positionPct <= posHiPct)
|
||||
{
|
||||
positionReached = true;
|
||||
return Event.PositionReached;
|
||||
}
|
||||
else if (StateMachine.Time > expireTime)
|
||||
{
|
||||
return Event.RegulValveTimeOut;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Event.None;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Stop this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
controlBoard.ValveMove(regulValveNr,
|
||||
RegulValveMode.Stop,
|
||||
new float[2] { posLoPct, posHiPct },
|
||||
regulValve.StableTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user