FixedStartMassCollection modified, ControlBoard.Elde repmoved, ver. 3.1.1624

This commit is contained in:
Milan Hanajik
2021-04-16 14:06:47 +02:00
parent 95d5d16c83
commit 847956f708
46 changed files with 113 additions and 3688 deletions
+1 -1
View File
@@ -66,7 +66,7 @@ namespace TBF.Rig.ControlBoard
/// Error .............. unspecified error while running a test
/// </summary>
/// <returns>Operation running a test</returns>
IOperation StandingStartStopTestOp(Test test, double qFrom, double qTo, int pulsesCount);
IOperation StandingStartStopTestOp(Test test, double qFrom, double qTo, int pulsesCount, bool withDiverter);
/// <summary>
-113
View File
@@ -1,113 +0,0 @@
///
/// Copyright (c) 2013-2016 Sensus Metering Systems
///
using System;
namespace TBF.Rig.ControlBoard.Legacy
{
public enum Command
{
None = 0, /// Do nothing, just transfer data (route, etc.)
Start = 1, /// Start the measurement
Stop = 2, /// Stop the measurement
ReadDivTransition = 4,
ReadExtremasOfPulses = 6,
ReadShapesOfPulses = 7,
ResetShapesOfPulses = 8,
EnduranceCycleParamsUpload = 11,
EnduranceCycleStart = 12,
EnduranceCycleStop = 13,
}
#if FUZHOU_300 || IZRAEL_200 || TORINO_50 || BADGER_MALA_TRAT || BADGER_STREDNA_TRAT || TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL || BADGER_VELKA_TRAT || PUCHONG_200 || SLM_50 || GENESIS || MALTA_WSD25 || SLM_END || WARSAW_END || BERLIN || GELSENWASSER || SLM_150 || PETERSBURG_50 || PETERSBURG_200 || DEWA_300 || ROMA_200 || KEMPNO_50 || BAHRAIN_50 || RUM_MOB || KRAKOW_50 || JUZNA_AFRIKA_50 || IZRAEL_25 || ZAMBIA || ZODINO || FEWA_50 || FILIPINY_50 || SENTEC || FUZHOU_100 || CEVAK_200 || IZRAEL_50 || ALZIR_25
public enum StatusP : ulong
{
RefFlowMeterMask = 0x7, /// bits 0,1,2
TestCompleted = 0x10, /// bit 4
TestInProgress = 0x20, /// bit 5
//DiverterError = 0x20,
MsrmntWithDivrtr = 0x80, /// bit 7
RefPulsesMsrmnt = 0x100, /// bit 8
SynchroMethod = 0x800, /// bit 11
WaterMeterCalib = 0x1000, /// bit 12
EmgcyStopActive = 0x2000, /// bit 13
MsrmntGateActive = 0x4000, /// bit 14
TimeMeasurement = 0x8000, /// bit 15
FrequencyMeasured = 0x80000, /// bit 19
CoaxRegValveBusy = 0x200000, /// bit 21
ADCError = 0x80000000, /// bit 31
TimeoutOccured = 0x100000000, /// bit 32
MeretAddresses = 0x200000000, /// bit 33
SampleBuferFull = 0x400000000, /// bit 34
ErrorTempMeter = 0x10000000000, /// bit 40
ErrorPressMeter1 = 0x1000000000000, /// bit 48
ErrorPressMeter2 = 0x2000000000000, /// bit 49
ErrorPressMeter3 = 0x4000000000000, /// bit 50
ErrorPressMeter4 = 0x8000000000000, /// bit 51
EndurCycleRunning = 0x200000000000000, /// bit 57
}
#else // DN100 || MUNICH || FUZHOU_150 || TORUN_50 || CEVAK_40 || MURES_40 || FUZHOU_50
public enum StatusP : ulong
{
RefFlowMeterMask = 0x7,
TestInProgress = 0x8,
TestCompleted = 0x10,
DiverterError = 0x20,
MsrmntWithDivrtr = 0x80,
RefPulsesMsrmnt = 0x100,
SynchroMethod = 0x800,
WaterMeterCalib = 0x1000,
EmgcyStopActive = 0x2000,
MsrmntGateActive = 0x4000,
TimeMeasurement = 0x8000,
FrequencyMeasured = 0x80000,
CoaxRegValveBusy = 0x200000, /// bit 21
ADCError = 0x80000000,
TimeoutOccured = 0x100000000,
MeretAddresses = 0x200000000,
SampleBuferFull = 0x400000000,
ErrorTempMeter = 0x10000000000,
ErrorPressMeter1 = 0x1000000000000,
ErrorPressMeter2 = 0x2000000000000,
ErrorPressMeter3 = 0x4000000000000,
ErrorPressMeter4 = 0x8000000000000,
EndurCycleRunning = 0x200000000000000, /// bit 57
}
#endif
public enum StopDevs
{
None = 0,
Reference = 0x01, /// bit 0
Diverter = 0x02, /// bit 1
GatePulse = 0x08, /// bit 3
TimeMeasurement = 0x10, /// bit 4
BypassDevCoupled2Div = 0x20, /// bit 5
RegValveRegulation = 0x80, /// bit 7
All = 0xFF,
}
public enum TestMethods
{
Diverter = 0x01, /// bit 0: 1=Mass method (diverters are used), 0=Volume method
FixedStart = 0x02, /// bit 1: 1=fixed start method, 0=flying start method
Synchro = 0x04, /// bit 2: 1=Synchro method, 0=Pulse counting
MassAndContinue = 0x10, /// bit 4: 1=Method with mass measurement followed by a volume method
}
public enum RegulValveMode : byte
{
None = 0,
PulseWidth = 1, /// Pulse width 0.05 .. 2 sec.
TargetPosition = 2, /// Low and high position (=DAC value) limits (0..100%) are specified
TargetFrequency = 3, /// Low and high frequency limits (0..2000Hz,0..2200Hz) are specified
Stop = 4, /// Stop regulation
}
public enum RegulValveState
{
Idle = 0,
PwOrFreqRegul = 2,
DacValueRegul = 3,
}
}
@@ -1,45 +0,0 @@
///
/// Copyright (c) 2013-2016 Sensus Metering Systems
///
using System.Collections.Generic;
using System.Xml.Serialization;
using TBF.Rig.Generic;
namespace TBF.Rig.ControlBoard.Legacy
{
public class ControlBoardCfg : ComponentCfgBase, IComponentCfg
{
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(ControlBoardCfg) })[0];
public override XmlSerializer GetSerializer() { return Serializer; }
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new ControlBoardCfgCtrl(); }
///
/// Serialized parameters
///
public int ComPortNr;
public int VirtualValvesRangeLo;
public int VirtualValvesRangeHi;
/// Private parameterless constructor invoked by all other (public) constructors
ControlBoardCfg()
{
Name = "CB";
ParentName = string.Empty;
ComPortNr = 1;
VirtualValvesRangeLo = 50;
VirtualValvesRangeHi = 59;
}
public ControlBoardCfg(IComponentFactory factory)
: this()
{
this.Factory = factory;
}
public string ToString(int i)
{
return string.Format("Name={0}, Com{1}, VVRangeLo={2}, VVRangeHi={3}", Name, ComPortNr, VirtualValvesRangeLo, VirtualValvesRangeHi);
}
}
}
@@ -1,155 +0,0 @@
///
/// Copyright (c) 2013-2015 Sensus Metering Systems
///
namespace TBF.Rig.ControlBoard.Legacy
{
partial class ControlBoardCfgCtrl
{
/// <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.comPortNrLabel = new System.Windows.Forms.Label();
this.comPortNrTextBox = new System.Windows.Forms.TextBox();
this.classNameLabel = new System.Windows.Forms.Label();
this.nameLabel = new System.Windows.Forms.Label();
this.nameTextBox = new System.Windows.Forms.TextBox();
this.vValveRangeLoTextBox = new System.Windows.Forms.TextBox();
this.vValveRangeLoLabel = new System.Windows.Forms.Label();
this.vValveRangeHiTextBox = new System.Windows.Forms.TextBox();
this.vValveRangeHiLabel = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// comPortNrLabel
//
this.comPortNrLabel.AutoSize = true;
this.comPortNrLabel.Location = new System.Drawing.Point(42, 85);
this.comPortNrLabel.Name = "comPortNrLabel";
this.comPortNrLabel.Size = new System.Drawing.Size(95, 13);
this.comPortNrLabel.TabIndex = 0;
this.comPortNrLabel.Text = "Serial port number:";
//
// comPortNrTextBox
//
this.comPortNrTextBox.Enabled = false;
this.comPortNrTextBox.Location = new System.Drawing.Point(166, 82);
this.comPortNrTextBox.Name = "comPortNrTextBox";
this.comPortNrTextBox.Size = new System.Drawing.Size(80, 20);
this.comPortNrTextBox.TabIndex = 1;
//
// classNameLabel
//
this.classNameLabel.AutoSize = true;
this.classNameLabel.Location = new System.Drawing.Point(163, 26);
this.classNameLabel.Name = "classNameLabel";
this.classNameLabel.Size = new System.Drawing.Size(83, 13);
this.classNameLabel.TabIndex = 2;
this.classNameLabel.Text = "ComonentName";
//
// nameLabel
//
this.nameLabel.AutoSize = true;
this.nameLabel.Location = new System.Drawing.Point(42, 60);
this.nameLabel.Name = "nameLabel";
this.nameLabel.Size = new System.Drawing.Size(35, 13);
this.nameLabel.TabIndex = 3;
this.nameLabel.Text = "Name";
//
// nameTextBox
//
this.nameTextBox.Enabled = false;
this.nameTextBox.Location = new System.Drawing.Point(166, 57);
this.nameTextBox.Name = "nameTextBox";
this.nameTextBox.Size = new System.Drawing.Size(80, 20);
this.nameTextBox.TabIndex = 4;
//
// vValveRangeLoTextBox
//
this.vValveRangeLoTextBox.Enabled = false;
this.vValveRangeLoTextBox.Location = new System.Drawing.Point(166, 107);
this.vValveRangeLoTextBox.Name = "vValveRangeLoTextBox";
this.vValveRangeLoTextBox.Size = new System.Drawing.Size(80, 20);
this.vValveRangeLoTextBox.TabIndex = 6;
//
// vValveRangeLoLabel
//
this.vValveRangeLoLabel.AutoSize = true;
this.vValveRangeLoLabel.Location = new System.Drawing.Point(42, 110);
this.vValveRangeLoLabel.Name = "vValveRangeLoLabel";
this.vValveRangeLoLabel.Size = new System.Drawing.Size(118, 13);
this.vValveRangeLoLabel.TabIndex = 5;
this.vValveRangeLoLabel.Text = "Virtual valves range Lo:";
//
// vValveRangeHiTextBox
//
this.vValveRangeHiTextBox.Enabled = false;
this.vValveRangeHiTextBox.Location = new System.Drawing.Point(166, 132);
this.vValveRangeHiTextBox.Name = "vValveRangeHiTextBox";
this.vValveRangeHiTextBox.Size = new System.Drawing.Size(80, 20);
this.vValveRangeHiTextBox.TabIndex = 8;
//
// vValveRangeHiLabel
//
this.vValveRangeHiLabel.AutoSize = true;
this.vValveRangeHiLabel.Location = new System.Drawing.Point(42, 135);
this.vValveRangeHiLabel.Name = "vValveRangeHiLabel";
this.vValveRangeHiLabel.Size = new System.Drawing.Size(116, 13);
this.vValveRangeHiLabel.TabIndex = 7;
this.vValveRangeHiLabel.Text = "Virtual valves range Hi:";
//
// ControlBoardCfgCtrl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.vValveRangeHiTextBox);
this.Controls.Add(this.vValveRangeHiLabel);
this.Controls.Add(this.vValveRangeLoTextBox);
this.Controls.Add(this.vValveRangeLoLabel);
this.Controls.Add(this.nameTextBox);
this.Controls.Add(this.nameLabel);
this.Controls.Add(this.classNameLabel);
this.Controls.Add(this.comPortNrTextBox);
this.Controls.Add(this.comPortNrLabel);
this.Name = "ControlBoardCfgCtrl";
this.Size = new System.Drawing.Size(300, 200);
this.Load += new System.EventHandler(this.ControlBoardCfgCtrl_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label comPortNrLabel;
private System.Windows.Forms.TextBox comPortNrTextBox;
private System.Windows.Forms.Label classNameLabel;
private System.Windows.Forms.Label nameLabel;
private System.Windows.Forms.TextBox nameTextBox;
private System.Windows.Forms.TextBox vValveRangeLoTextBox;
private System.Windows.Forms.Label vValveRangeLoLabel;
private System.Windows.Forms.TextBox vValveRangeHiTextBox;
private System.Windows.Forms.Label vValveRangeHiLabel;
}
}
@@ -1,105 +0,0 @@
///
/// Copyright (c) 2013-2015 Sensus Slovensko a.s.
///
using System;
using System.Windows.Forms;
using Config.Entities;
using TBF.Rig.Generic;
namespace TBF.Rig.ControlBoard.Legacy
{
public partial class ControlBoardCfgCtrl : UserControl, IComponentCfgCtrl
{
public bool ShowMore { get { return false; } }
ControlBoardCfg config;
public IComponentCfg Config
{
get { return config as IComponentCfg; }
set
{
config = value as ControlBoardCfg;
Redraw();
}
}
public ControlBoardCfgCtrl()
{
InitializeComponent();
}
private void ControlBoardCfgCtrl_Load(object sender, EventArgs e)
{
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;
comPortNrTextBox.Text = config.ComPortNr.ToString();
vValveRangeLoTextBox.Text = config.VirtualValvesRangeLo.ToString();
vValveRangeHiTextBox.Text = config.VirtualValvesRangeHi.ToString();
}
public void Unlock()
{
nameTextBox.Enabled = true;
comPortNrTextBox.Enabled = true;
vValveRangeLoTextBox.Enabled = true;
vValveRangeHiTextBox.Enabled = true;
}
/// <summary>
/// Verify current user controls for validity.
/// Called when user wants to close/save the configuration.
/// </summary>
/// <returns>See VerifyFlags</returns>
public CfgUpdateFlags VerifyCfg(ref string message)
{
CfgUpdateFlags flags = CfgUpdateFlags.None;
int dummy;
if (!int.TryParse(comPortNrTextBox.Text, out dummy) || dummy <= 0 || dummy > 999)
{
message += "Control board serial port number is invalid";
flags |= CfgUpdateFlags.Error;
}
if (!int.TryParse(vValveRangeLoTextBox.Text, out dummy) || dummy < 0 || dummy > 63)
{
message += "Virtual valves range Lo is invalid";
flags |= CfgUpdateFlags.Error;
}
if (!int.TryParse(vValveRangeHiTextBox.Text, out dummy) || dummy < 0 || dummy > 63)
{
message += "Virtual valves range Hi is invalid";
flags |= CfgUpdateFlags.Error;
}
return flags;
}
/// <summary>
/// Save settings to the configuration class.
/// </summary>
public CfgUpdateFlags UpdateCfg()
{
CfgUpdateFlags flags = CfgUpdateFlags.RestartRqrd;
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
this.Name = nameTextBox.Text;
this.config.ComPortNr = int.Parse(comPortNrTextBox.Text);
this.config.VirtualValvesRangeLo = int.Parse(vValveRangeLoTextBox.Text);
this.config.VirtualValvesRangeHi = int.Parse(vValveRangeHiTextBox.Text);
return flags;
}
}
}
@@ -1,120 +0,0 @@
<?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>
@@ -1,887 +0,0 @@
///
/// Copyright (c) 2013-2020 Sensus Slovensko a.s.
///
using System;
using System.Text;
using System.IO.Ports;
using System.Collections.Generic;
using log4net;
using Config.Entities;
using Dirichlet.Numerics;
using TBF.Rig.Generic;
using TBF.Rig.GenericDevices;
namespace TBF.Rig.ControlBoard.Legacy
{
public class CBoard : ComponentBase, IControlBoard
{
private static readonly ILog log = LogManager.GetLogger(typeof(CBoard));
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
const int FiltersCount = 8;
readonly ControlBoardCfg controlBoardCfg;
///
/// Reference to the control board component
///
IControlCom controlCom;
/// <summary>
/// Emergency stop signal state updated by RunDevice().
/// 'modelessDlg' is notified about the changes and uses this information to change its visibility.
/// </summary>
//UiBridge.EmergencyStopEventArgs.State emergencyStopState;
///
/// Public read only wrappers for Elde software component fields
///
/// rvNr1 = 1 .. nrRegulValves (one based)
/// wmNr0 = 0 .. nrWaterMeters-1 (zero based)
/// tmpNr0 = 0 .. nrTempMeters-1 (zero based)
/// prsNr0 = 0 .. nrPressureMeters-1 (zero based)
///
public StatusP StatusP { get { return controlCom.StatusP; } }
public int EtPulsesK { get { return controlCom.EtPulsesK; } }
public int EtPulses2 { get { return controlCom.EtPulses2; } } /// DEWA_300: pulses from I12
public int EtPulses3 { get { return controlCom.EtPulses3; } } /// DEWA_300: pulses from I13
public int WMeterReference(int wmNr0) { return controlCom.WMeterReference(wmNr0); }
public uint RegulValveDAC(int rvNr0) { return controlCom.RegulValveDAC(rvNr0); }
public float Pressure(int prsNr0) { return controlCom.Pressure(prsNr0); }
public float Temperature(int tmpNr0) { return controlCom.Temperature(tmpNr0); }
public RegulValveState RegulValveState(int rvNr1) { return (RegulValveState)controlCom.RegulValveState(rvNr1); }
public UInt128 RRoute { get { return controlCom.RRoute; } }
public uint DivTime(int id) { return controlCom.DivTime(id); }
public uint FmState { get { return controlCom.FmState; } }
public uint BeginState(int wmNr0) { return controlCom.BeginState(wmNr0); }
public double RefFrequency { get { return controlCom.ReferenceFreq; } } /// In [Hz] 0..2500, nom.=2000
public double ReferenceFreqs(int i) { return controlCom.ReferenceFreqs(i); }
public double RefFlow { get { return controlCom.ReferenceFlow; } }
public float RValvePosition(int rvNr1) { return controlCom.RValvePosition(rvNr1); }
public float DivSamples(int time, int divIx0) { return controlCom.DivSamples(time, divIx0); } /// Time unit is 2 ms
public int ScopeSamples(int i, int j, int k) { return controlCom.ScopeSamples(i, j, k); }
public ulong DigitalInputs { get { return controlCom.DigitalInputs; } }
public float AnalogInput(int adcNr0) { return controlCom.AnalogInput(adcNr0); }
public uint AnalogInputRaw(int adcNr0, int bank) { return controlCom.AnalogInputRaw(adcNr0, bank); } /// adcNr0: 0=RV1, 1=RV2,... bank: 0=RV, 1=Temp
public float ReferenceVolume { get { return controlCom.TotalRefVolume; } }
public float VyslExt(int wmNr0, int what) { return controlCom.VyslExt(wmNr0, what); }
public uint[] CyclePar { get { return controlCom.CyclePar; } set { controlCom.CyclePar = value; } }
public uint[] WMeterCont { get { return controlCom.WMeterCont; } }
public bool ManualUIAllowed { get { return controlCom.ManualUIAllowed; } set { controlCom.ManualUIAllowed = value; } }
public float ValveOpenCloseTime { get { return controlCom.ValveOpenCloseTime; } }
public int FlowmeterId { get { return (int)(controlCom.StatusP & Legacy.StatusP.RefFlowMeterMask); } }
/// <summary> Extracted from the StatusP in RunDeviceBefore </summary>
public bool EmergencyStop { get { return emergencyStop; } }
bool emergencyStop;
bool previousEmergencyStop;
///
/// IControlBoard interface
///
public int RefPulses { get { return controlCom.EtPulses(0); } }
public double TestTime { get { return (double)controlCom.TTime; } }
public int RefPulsesWM(int wmNr1) { return (wmNr1 > 0 && wmNr1 <= Config.Data.WMsCount) ? controlCom.EtPulses(wmNr1) : 0; }
public int PulsesWM(int wmNr1) { return (wmNr1 > 0 && wmNr1 <= Config.Data.WMsCount) ? unwrappedWMPulses[wmNr1] : 0; }
public double TestTimeWM(int wmNr1) { return (wmNr1 > 0 && wmNr1 <= Config.Data.WMsCount) ? (double)controlCom.ImpulseTime(wmNr1) : 0; }
public void DiverterToTank(int flowMtrNr)
{
cbCommandQueue.Enqueue(new SendCommandArgs(Command.Start, flowMtrNr, int.MaxValue, int.MaxValue, TestMethods.Diverter | TestMethods.Synchro, StopDevs.None));
}
///
public void DiverterToSink(int flowMtrNr)
{
cbCommandQueue.Enqueue(new SendCommandArgs(Command.Stop, 0, 0, 0, TestMethods.Diverter,
StopDevs.Diverter | StopDevs.GatePulse | StopDevs.Reference | StopDevs.RegValveRegulation));
}
///
public void ReadDiverterTransition(int flowMtrNr)
{
cbCommandQueue.Enqueue(new SendCommandArgs(Command.ReadDivTransition, flowMtrNr, 0, 0, TestMethods.Diverter, 0));
}
///
/// Initialization data updated by constructors of children components
/// and sent to 'controlCom2panel' by SendCalibData() method.
///
#if DEWA_300 || ROMA_200
public float[,] TempCalibData = new float[16, 5];
#else
public float[,] TempCalibData = new float[8, 5];
#endif
public uint[] DiverterEdge; /// Created and initialized in this.Initialize()
public byte MeretProtocol = 0;
// Array length is the reference flowmeters count plus one
#if DN100 || FUZHOU_150 || FUZHOU_300 || IZRAEL_200 || SENTEC || CEVAK_200
public uint[,] RegValveCalib = new uint[8,2] {{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500}};
public byte[] MeretRS485Address = new byte[4];
public float[] EtCalib = new float[6] { 1, 1, 1, 1, 1, 1 };
#elif PUCHONG_200 || GENESIS || BERLIN || GELSENWASSER || PETERSBURG_200 || RUM_MOB || SLM_150
public uint[,] RegValveCalib = new uint[16, 2] { {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500},
{100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500} };
public byte[] MeretRS485Address = new byte[4];
public float[] EtCalib = new float[7] { 1, 1, 1, 1, 1, 1, 1 };
#elif DEWA_300
public uint[,] RegValveCalib = new uint[16, 2] { {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500},
{100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500} };
public byte[] MeretRS485Address = new byte[4];
public float[] EtCalib = new float[8] { 1, 1, 1, 1, 1, 1, 1, 1 };
#elif ROMA_200
public uint[,] RegValveCalib = new uint[16, 2] { {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500},
{100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500} };
public byte[] MeretRS485Address = new byte[5];
public float[] EtCalib = new float[8] { 1, 1, 1, 1, 1, 1, 1, 1 };
#elif MUNICH || TORINO_50 || BADGER_MALA_TRAT || BADGER_STREDNA_TRAT || TORUN_50 || CEVAK_40 || TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL || MURES_40 || FUZHOU_50 || SLM_50 || PETERSBURG_50 || KEMPNO_50 || BAHRAIN_50 || KRAKOW_50 || JUZNA_AFRIKA_50 || IZRAEL_25 || ZAMBIA || ZODINO || FEWA_50 || FILIPINY_50 || FUZHOU_100 || ALZIR_25
public uint[,] RegValveCalib = new uint[8,2] {{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500}};
#if IZRAEL_50
public byte[] MeretRS485Address = new byte[6];
#else
public byte[] MeretRS485Address = new byte[4];
#endif
public float[] EtCalib = new float[5] { 1, 1, 1, 1, 1 };
#elif IZRAEL_50 || SLM_END
public uint[,] RegValveCalib = new uint[8,2] {{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500}};
public byte[] MeretRS485Address = new byte[7]; /// Modbus addresses of Pr1, Pr2, Pr3, Pr4, Pr5, Pr6, T9 (Izrael) or Pr1, Pr2, Pr3, Pr4, T9, T10 (SLM END)
public float[] EtCalib = new float[5] { 1, 1, 1, 1, 1 };
#elif WARSAW_END
public uint[,] RegValveCalib = new uint[8,2] {{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500}};
public byte[] MeretRS485Address = new byte[4];
public float[] EtCalib = new float[5] { 1, 1, 1, 1, 1 };
#elif MALTA_WSD25
public uint[,] RegValveCalib = new uint[8,2] {{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500}};
public byte[] MeretRS485Address = new byte[12];
public float[] EtCalib = new float[9] { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
#elif BADGER_VELKA_TRAT
public uint[,] RegValveCalib = new uint[8,2] {{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500}};
public byte[] MeretRS485Address = new byte[4];
public float[] EtCalib = new float[8] { 1, 1, 1, 1, 1, 1, 1, 1 };
#else
/// New benches => no initialization buffers at all
public uint[,] RegValveCalib = new uint[0,0];
public byte[] MeretRS485Address = new byte[0];
public float[] EtCalib = new float[0];
#endif
public uint[] BalanceRange = new uint[2];
Queue<SendCommandArgs> cbCommandQueue;
/// <summary>
/// Route: 128-bit word representing the current state of all valves and pumps
/// </summary>
public UInt128 Route { get { return benchModelRoute; } }
UInt128 benchModelRoute;
UInt128 valvesToInvert; /// Route = valesToInvert ^ RequiredRouteWithoutInvertedVlaves
readonly UInt128 routeMask; /// This mask masks out virtual valves, routeMask is set in the constructor
public OutputPath Devices
{
set { devices = value; }
get { return devices; }
}
OutputPath devices;
int[] filters;
float[] FMFreq;
int regConst;
int shortImp;
private int[] unwrappedWMPulses; /// Initialized to zeros
///
private void UnwrapPulses()
{
for (int i = 1; i <= Config.Data.WMsCount; i++)
{
UInt16 lowerWord = controlCom.WMeterPulses(i);
int uncorrected = (int)(((uint)unwrappedWMPulses[i] & 0xFFFF0000) | lowerWord);
if (Math.Abs(uncorrected - unwrappedWMPulses[i]) <= Int16.MaxValue)
{
unwrappedWMPulses[i] = uncorrected;
}
else if (Math.Abs(uncorrected + 65536 - unwrappedWMPulses[i]) <= Int16.MaxValue)
{
unwrappedWMPulses[i] = uncorrected + 65536;
}
else if (Math.Abs(uncorrected - 65536 - unwrappedWMPulses[i]) <= Int16.MaxValue)
{
unwrappedWMPulses[i] = uncorrected - 65536;
}
}
}
///
public void ClearProcessValues()
{
for (int i = 1; i <= Config.Data.WMsCount; i++)
{
unwrappedWMPulses[i] = 0;
}
UnwrapPulses();
}
/// <summary>
/// Set values to be applied during a test
/// </summary>
/// <param name="filters">Filters for meter pulses</param>
/// <param name="pid">PID coefficient for flow control</param>
/// <param name="shortPulses">Short pulses mode (0 = off)</param>
public void SetFiltersPidShortPulses(int[] filters, float pid, int shortPulses)
{
this.filters = filters;
this.regConst = (int)pid;
this.shortImp = shortPulses;
}
/// <summary>
/// Sets the power of the selected pump
/// </summary>
/// <param name="index">Pump index 0 .. 5, invalid pump index sets all pumps to 0%</param>
/// <param name="power">Power (0.0f .. 100.0f)</param>
public void SetFMFreq(int index, double power)
{
bool pumpPowerChanged = false;
#if DN100 || MUNICH || FUZHOU_150
if ((FMFreq == null) || (FMFreq.Length != 2))
{
FMFreq = new float[2];
pumpPowerChanged = true; /// Forces sending a command using Command.None
}
#elif SLM_END || WARSAW_END
if ((FMFreq == null) || (FMFreq.Length != 4))
{
FMFreq = new float[4];
pumpPowerChanged = true; /// Forces sending a command using Command.None
}
#else /// all newer benches
if ((FMFreq == null) || (FMFreq.Length != 6))
{
FMFreq = new float[6];
pumpPowerChanged = true; /// Forces sending a command using Command.None
}
#endif
if (index >= 0 && index < FMFreq.Length)
{
if (FMFreq[index] != power)
{
FMFreq[index] = (float)power;
pumpPowerChanged = true; /// Forces sending a command using Command.None
string s = string.Format("FMFreq=[{0}{1}{2}{3}{4}{5}]", FMFreq[0].ToString(),
(FMFreq.Length > 1) ? ("," + FMFreq[1].ToString()) : "",
(FMFreq.Length > 2) ? ("," + FMFreq[2].ToString()) : "",
(FMFreq.Length > 3) ? ("," + FMFreq[3].ToString()) : "",
(FMFreq.Length > 4) ? ("," + FMFreq[4].ToString()) : "",
(FMFreq.Length > 5) ? ("," + FMFreq[5].ToString()) : "");
log.Warn(s);
}
}
else
{
log.ErrorFormat("Wrong FM pump: index = {0}, power = {1}", index, power);
}
}
public void UpdateWeights()
{
/// Mettler-Toledo scales
//for (int i = 0; i < MettlerToledo.Standard.BalanceDev.BalancesCount; i++)
//{
// controlCom.SetWeight(i, MettlerToledo.Standard.BalanceDev.Masses[i]);
//}
///// Mettler-Toledo-multi scales (Badger Brno, ...)
//for (int i = 0; i < MettlerToledo.Multi.BalanceDev.BalancesCount; i++)
//{
// controlCom.SetWeight(i, MettlerToledo.Multi.BalanceDev.Masses[i]);
//}
///// Tanks (CEVAK, ...)
//int firstTankIx = Math.Max(MettlerToledo.Standard.BalanceDev.BalancesCount, MettlerToledo.Multi.BalanceDev.BalancesCount);
//for (int i = 0; i < Various.TankWithLevelMsrmnt.Tank.TanksCount; i++)
//{
// controlCom.SetWeight(firstTankIx + i, Various.TankWithLevelMsrmnt.Tank.Tanks[i].Volume);
//}
}
/// <summary>
/// Display value in ELDE component, update UI
/// </summary>
/// <param name="sParam">String parameter</param>
/// <param name="iParam">Integer parameter</param>
/// <param name="value">Value to be displayed</param>
public void UpdateUI(string sParam, int iParam, double value)
{
if (sParam == "ReservoirTemp")
{
controlCom.SetReservoirTemp(iParam, (float)value);
return;
}
}
public CBoard()
{
}
/// <summary>
/// Constructor
/// </summary>
public CBoard(Generic.IComponentCfg cfg)
: base(cfg)
{
controlBoardCfg = cfg as ControlBoardCfg;
/// Buffers used in UnwrapPulses() and PulsesWM(wmNr1)
unwrappedWMPulses = new int[Config.Data.WMsCount + 1];
cbCommandQueue = new Queue<SendCommandArgs>();
lastSentFilters = new uint[FiltersCount];
#if DN100 || MUNICH || FUZHOU_150
FMFreq = new float[2] { 0, 0 }; /// Nr. of pumps: Fuzhou150=2, Fuzhou300=6, newer=6
#elif SLM_END || WARSAW_END
FMFreq = new float[4] { 0, 0, 0, 0 };
#else /// all newer benches
FMFreq = new float[6] { 0, 0, 0, 0, 0, 0 };
#endif
emergencyStop = false;
previousEmergencyStop = false;
routeMask = 0;
for (int i = 0; i < 128; i++)
{
if (i < controlBoardCfg.VirtualValvesRangeLo || i > controlBoardCfg.VirtualValvesRangeHi)
{
routeMask = routeMask | ((UInt128)1 << i);
}
}
log.Debug(this.ToString());
}
/// <summary>
/// Specific pre-initialization for control board only
/// </summary>
/// <param name="eldeComponent"></param>
public void SpecifyInvertedValves(UInt128 valvesToInvert)
{
this.valvesToInvert = valvesToInvert;
this.benchModelRoute = valvesToInvert;
if (controlBoardCfg.DebugLevel == DebugMode.Simulate)
{
controlCom = new ControlComSim();
}
else
{
// controlCom = new ControlComWrap(eldeComponent);
/// Default number of scales (and BalanceRange length) is 2.
/// If there are more scales, BalanceRange length is larger.
// int scalesCnt = Math.Max(2, tankCapacities.Length);
// BalanceRange = new uint[scalesCnt];
// for (int i = 0; i < scalesCnt; i++)
// {
// BalanceRange[i] = (uint)((i < tankCapacities.Length) ? tankCapacities[i] : 0);
// }
}
}
/// <summary>Initialize this device</summary>
public override void Initialize()
{
//int divertersCount = Rig.Uni.Diverter.Diverter.DivertersCount;
//DiverterEdge = new uint[divertersCount];
//for (int i = 0; i < divertersCount; i++)
//{
// DiverterEdge[i] = (uint)Rig.Uni.Diverter.Diverter.Diverters[i].StartThreshold;
// controlCom.SetDivLimit(i, (uint)Rig.Uni.Diverter.Diverter.Diverters[i].ThresholdLo,
// (uint)Rig.Uni.Diverter.Diverter.Diverters[i].ThresholdHi);
//}
controlCom.SendCalibData(RegValveCalib,
MeretRS485Address,
controlBoardCfg.ComPortNr,
TempCalibData,
EtCalib,
DiverterEdge,
BalanceRange,
MeretProtocol);
log.FatalFormat("Successfully initialized device {0}", ToString());
}
/// <summary>
/// Run this device
/// </summary>
public void RunDeviceBefore()
{
if (DebugLevel == DebugMode.Simulate) return;
controlCom.RunDeviceBefore();
UnwrapPulses();
}
///
/// Used in RunDeviceAfter() when sending commands
///
UInt128 lastSentRoute;
uint[] lastSentFilters;
float[] lastSentFMFreq;
int lastsentRegConst;
int lastSentShortImp;
/// <summary>
/// Run this device
/// </summary>
public void RunDeviceAfter()
{
if (DebugLevel == DebugMode.Simulate) return;
previousEmergencyStop = emergencyStop;
emergencyStop = (controlCom.StatusP & StatusP.EmgcyStopActive) != 0;
///
if (emergencyStop)
{
/// Modify the queue in case of an emergency stop
cbCommandQueue.Clear();
cbCommandQueue.Enqueue(new SendCommandArgs(Command.Stop, 0, 0, 0, 0, StopDevs.All));
}
///
if (emergencyStop && !previousEmergencyStop)
{
/// Stop the cycle - Press 'STOP' button in the BenchControlPanel
TBF.UiBridge.Bridge.Ui2Bench(TBF.UiBridge.UI2BenchCmd.Stop);
Program.MainWnd.Invoke(new ShowEmergencyStopFormDlgt(ShowEmergencyStopForm));
}
else if (!emergencyStop && previousEmergencyStop)
{
//UiBridge.Bridge.OnEmergencyStopChanged(this, UiBridge.EmergencyStopEventArgs.State.CloseForm);
}
UpdateWeights();
/// Prepare uintFilters array and evaluate changes
uint[] uintFilters = new uint[FiltersCount];
uintFilters[0] = (filters != null && filters.Length > 0) ? (uint)filters[0] : 0;
bool filtersAreDifferent = (uintFilters[0] != lastSentFilters[0]);
for (int i = 1; i < FiltersCount; i++)
{
uintFilters[i] = (filters != null && filters.Length > i) ? (uint)filters[i] : uintFilters[i - 1];
filtersAreDifferent |= (uintFilters[i] != lastSentFilters[i]);
}
/// Evaluate FMFreq changes
bool fmFreqsAreDifferent = false;
if ((FMFreq == null) || (lastSentFMFreq == null) || (FMFreq.Length != lastSentFMFreq.Length))
{
fmFreqsAreDifferent = true;
}
else
{
for (int i = 0; i < FMFreq.Length; i++)
{
if (FMFreq[i] != lastSentFMFreq[i])
{
fmFreqsAreDifferent = true;
break;
}
}
}
if (cbCommandQueue.Count > 0)
{
///
/// There is a command in the queue
///
controlCom.SendCommand(cbCommandQueue.Dequeue(), (benchModelRoute & routeMask), uintFilters, FMFreq, regConst, shortImp);
lastSentRoute = (benchModelRoute & routeMask);
lastsentRegConst = regConst;
lastSentShortImp = shortImp;
/// Deep copy of arrays lastSentFilters and lastSentFMFreq
if ((lastSentFilters == null) || (lastSentFilters.Length != uintFilters.Length)) lastSentFilters = new uint[(uintFilters == null) ? 0 : uintFilters.Length];
for (int i = 0; i < lastSentFilters.Length; i++) lastSentFilters[i] = uintFilters[i];
if ((lastSentFMFreq == null) || (lastSentFMFreq.Length != FMFreq.Length)) lastSentFMFreq = new float[(FMFreq == null) ? 0 : FMFreq.Length];
for (int i = 0; i < lastSentFMFreq.Length; i++) lastSentFMFreq[i] = FMFreq[i];
}
else if (((benchModelRoute & routeMask) != lastSentRoute) ||
filtersAreDifferent ||
fmFreqsAreDifferent ||
(lastsentRegConst != regConst) ||
(lastSentShortImp != shortImp))
{
///
/// Command queue is mepty, but 'route', pump frequency, PID coef., filters or shortImp have changed
///
controlCom.SendCommand(new SendCommandArgs(Command.None, 0, 0, 0, 0, 0), (benchModelRoute & routeMask), uintFilters, FMFreq, regConst, shortImp);
lastSentRoute = (benchModelRoute & routeMask);
lastsentRegConst = regConst;
lastSentShortImp = shortImp;
/// Deep copy of arrays lastSentFilters and lastSentFMFreq
if ((lastSentFilters == null) || (lastSentFilters.Length != uintFilters.Length)) lastSentFilters = new uint[(uintFilters == null) ? 0 : uintFilters.Length];
for (int i = 0; i < lastSentFilters.Length; i++) lastSentFilters[i] = uintFilters[i];
if ((lastSentFMFreq == null) || (lastSentFMFreq.Length != FMFreq.Length)) lastSentFMFreq = new float[(FMFreq == null) ? 0 : FMFreq.Length];
for (int i = 0; i < lastSentFMFreq.Length; i++) lastSentFMFreq[i] = FMFreq[i];
}
controlCom.RunDeviceAfter();
}
/// <summary>Stop this device</summary>
public void StopDevice() { }
public void StopDevice2() { }
delegate void ShowEmergencyStopFormDlgt();
///
void ShowEmergencyStopForm()
{
//(new TBF.UI.Shared.EmergencyStopForm()).Show();
}
/// <summary>
/// Sends a command to the control board.
/// </summary>
/// <param name="cmd">See ControlBoard.Command enum</param>
/// <param name="refFlowmtrNr">Number of the etalon/reference (1..5)</param>
/// <param name="route">State of valves, 128-bit word</param>
/// <param name="totalRefPulses">kolko impulzov ma trvat skuska</param>
/// <param name="testMethods">See ControlBoard.TestMethods enum</param>
/// <param name="filterConstant">0 = No filtering (0..255)</param>
/// <param name="regConst">Coefficient used to control reg. valves (1..100)</param>
/// <param name="shortImp">0 = default value, 1 = spec. processing of very short pulses</param>
/// <param name="stopDevs">What to stop</param>
public void SendCommand(Command cmd, int refFlowmtrNr, int totalRefPulses, int massRefPulses,
TestMethods testMethods, StopDevs stopDevs)
{
cbCommandQueue.Enqueue(new SendCommandArgs(cmd, refFlowmtrNr, totalRefPulses, massRefPulses, testMethods, stopDevs));
}
/// <summary>
/// Set valves to new positions.
/// </summary>
/// <param name="valvesToOpen">'ulong' with bits of valves to open set to '1'</param>
/// <param name="valvesToClose">'ulong' with bits of valves to close set to '1'</param>
/// <returns>'ulong' with bits of valves that have changed set to '1'</returns>
public UInt128 SetValves(UInt128 valvesToOpen, UInt128 valvesToClose, IList<TBF.Rig.BuiltIn.ValveEx.Valve> extendedValves)
{
UInt128 oldRoute = benchModelRoute;
benchModelRoute = (((benchModelRoute ^ valvesToInvert) | valvesToOpen) & (~valvesToClose)) ^ valvesToInvert;
foreach (var extV in extendedValves) extV.UpdateRoute(ref benchModelRoute);
log.DebugFormat("SetValves(x,x), new route = {0}", Utils.RouteToStr(benchModelRoute));
return oldRoute ^ benchModelRoute;
}
/// <summary>
/// Set Route to value returned by RRoute. Take virtual valves into account.
/// </summary>
/// <returns>'ulong' with bits of valves that have changed set to '1'</returns>
public UInt128 SyncRoute()
{
UInt128 oldRoute = benchModelRoute;
benchModelRoute = (RRoute & routeMask) | (benchModelRoute & (~routeMask));
log.DebugFormat("SyncRoute(), new route = {0}", Utils.RouteToStr(benchModelRoute));
return oldRoute ^ benchModelRoute;
}
/// <summary>
/// Regulation valves control.
/// </summary>
/// <param name="valveNo">Regulation valve nr. (1..5)</param>
/// <param name="valveMode">Valve regulation mode, see the enum</param>
/// <param name="valveValue">Target position or target frequency or pulse duration</param>
/// <param name="stableTime">Stabilization time when setting the flow: 0=200ms, step 50ms, max. 1.5 sec.</param>
public void ValveMove(int valveNo, RegulValveMode valveMode, double[] valveValue, int stableTime)
{
controlCom.ValveMove(valveNo, valveMode, valveValue, stableTime);
}
/// <summary>
/// Open one valve and/or close one valve.
/// Events: ValvesSet
/// </summary>
/// <param name="valveOpen">Valve to be opened</param>
/// <param name="valveClose">Valve to be closed</param>
/// <returns>Created operation</returns>
public IOperation SetValvesOp(IValve valveOpen, IValve valveClose)
{
return new BuiltIn.SetValvesOp(this, valveOpen, valveClose);
}
/// <summary>
/// Open and/or close multiple valves.
/// Events: ValvesSet
/// </summary>
/// <param name="valvesOpen">A list of valves to be opened</param>
/// <param name="valvesClose">A list of valves to be closed</param>
/// <returns>Created operation</returns>
public IOperation SetValvesOp(IList<IValve> valvesOpen, IList<IValve> valvesClose)
{
return new BuiltIn.SetValvesOp(this, valvesOpen, valvesClose);
}
/// <summary>
/// Open start/stop valve.
/// Events: ValvesSet, ValvesBusy, Error
/// </summary>
/// <returns>Created operation</returns>
public IOperation OpenStartValveOp()
{
return new BuiltIn.SetValvesOp(this, true, devices);
}
/// <summary>
/// Close start/stop valve.
/// Events: ValvesSet, ValvesBusy, Error
/// </summary>
/// <returns>Created operation</returns>
public IOperation CloseStartValveOp()
{
return new BuiltIn.SetValvesOp(this, false, devices);
}
public IOperation SetFlowOp(double reqrdFlowLo, double reqrdFlowHi, TBF.Boxes.DoubleBox measuredFlow, int timeout)
{
if (Devices.RegValve == null || Devices.FlowMeter == null) return null;
return Devices.RegValve.SetFlowOp(Devices.FlowMeter, reqrdFlowLo, reqrdFlowHi, measuredFlow, timeout);
}
/// <summary>
/// Start a standing start-stop test
/// </summary>
/// <returns>Operation running a test</returns>
public IOperation StandingStartStopTestOp(Test test, double qFrom, double qTo, int pulsesCount)
{
return StartTestOp(test, false, false, true, qFrom, qTo, pulsesCount, 0);
}
/// <summary>
/// Start a flying start-stop test
/// </summary>
/// <returns>Operation running a test</returns>
public IOperation FlyingStartStopTestOp(Test test, double qFrom, double qTo, int pulsesCount)
{
return StartTestOp(test, true, false, false, qFrom, qTo, pulsesCount, 0);
}
/// <summary>
/// Start a flying start-stop test with diverter
/// </summary>
/// <returns>Operation running a test</returns>
public IOperation FlyingStartStopTestWithDivOp(Test test, double qFrom, double qTo, int pulsesCount, int massPulsesCount, bool readDivTransition)
{
return StartTestOp(test, true, true, false, qFrom, qTo, pulsesCount, massPulsesCount);
}
/// <summary>
/// Start a test
/// </summary>
/// <returns>Operation running a test</returns>
public IOperation StartTestOp(Test test, bool isSyncMethod, bool isDivUsed, bool isStartStop, double qFrom, double qTo, int pulsesCount, int massPulsesCount)
{
if (controlBoardCfg.DebugLevel == DebugMode.Simulate)
{
return new Operations.ReturnGivenEventOp(Event.TestInProgress);
}
/// Get total number of pulses
int totalPulses = Convert.ToInt32(Math.Round(test.Volume / devices.FlowMeter.LtrPerPulse));
/// Get method class string
string methodClass;
if (!StateMachine.TestMethod2Class.TryGetValue(test.Name, out methodClass)) return null;
if (methodClass.Contains("TestMethods.Adjustment."))
{
return new StartMeasurementOp(this, devices, TestMethods.Synchro, test.Qfrom, test.Qto, totalPulses);
}
if (methodClass.Contains("TestMethods.CombinedWithDetection."))
{
return new StartMeasurementOp(this, devices, (TestMethods.Diverter | TestMethods.Synchro), test.Qfrom, test.Qto, totalPulses);
}
if (methodClass == "TestMethods.DiverterTest")
{
return new StartMeasurementOp(this, devices, (TestMethods.Diverter | TestMethods.Synchro), test.Qfrom, test.Qto, totalPulses);
}
if (methodClass == "TestMethods.Dummy")
{
}
if (methodClass == "TestMethods.Endurance")
{
return new StartMeasurementOp(this, devices, TestMethods.Synchro, test.Qfrom, test.Qto, totalPulses);
}
if (methodClass.Contains("TestMethods.FixedStart."))
{
return new StartMeasurementOp(this, devices, TestMethods.Synchro, test.Qfrom, test.Qto, 2 * totalPulses, 10);
}
if (methodClass.Contains("TestMethods.FixedStartAdvanced."))
{
return new StartMeasurementOp(this, devices, TestMethods.Synchro, test.Qfrom, test.Qto, 2 * totalPulses, 10);
}
if (methodClass.Contains("TestMethods.FixedStartDefferedEval."))
{
return new StartMeasurementOp(this, devices, TestMethods.Synchro, test.Qfrom, test.Qto, 2 * totalPulses, 10);
}
if (methodClass.Contains("TestMethods.FixedStartMassCollDeferredEval."))
{
return new StartMeasurementOp(this, devices, (TestMethods.Diverter | TestMethods.Synchro), test.Qfrom, test.Qto, 2 * totalPulses, 10);
}
if (methodClass.Contains("TestMethods.FixedStartMassCollection."))
{
return new StartMeasurementOp(this, devices, (TestMethods.Diverter | TestMethods.FixedStart), test.Qfrom, test.Qto, 2 * totalPulses, 10);
}
if (methodClass.Contains("TestMethods.FixedStartTankCollection."))
{
return new StartMeasurementOp(this, devices, (TestMethods.Diverter | TestMethods.Synchro), test.Qfrom, test.Qto, (totalPulses * 5 / 4), 10);
}
if (methodClass.Contains("TestMethods.FlyingStart."))
{
return new StartMeasurementOp(this, devices, TestMethods.Synchro, test.Qfrom, test.Qto, totalPulses);
}
if (methodClass.Contains("TestMethods.FlyingStartFirstRepetWithMassColl."))
{
return new StartMeasurementOp(this, devices, TestMethods.Synchro, test.Qfrom, test.Qto, totalPulses);
}
if (methodClass.Contains("TestMethods.FlyingStartMassCollComparative."))
{
return new StartMeasurementOp(this, devices, (TestMethods.Diverter | TestMethods.Synchro), test.Qfrom, test.Qto, totalPulses);
}
if (methodClass.Contains("TestMethods.FlyingStartMassCollection."))
{
return new StartMeasurementOp(this, devices, (TestMethods.Diverter | TestMethods.Synchro), test.Qfrom, test.Qto, totalPulses);
}
if (methodClass.Contains("TestMethods.FlyingStartMassCollProlonged."))
{
return new StartMeasurementOp(this, devices, (TestMethods.Diverter | TestMethods.Synchro), test.Qfrom, test.Qto, totalPulses, massPulsesCount);
}
if (methodClass.Contains("TestMethods.FlyingStartTankCollection."))
{
return new StartMeasurementOp(this, devices, (TestMethods.Diverter | TestMethods.Synchro), test.Qfrom, test.Qto, totalPulses);
}
if (methodClass == "TestMethods.PulsesTest")
{
return new StartMeasurementOp(this, devices, TestMethods.Synchro, test.Qfrom, test.Qto, totalPulses);
}
if (methodClass == "TestMethods.PulsesTestManual")
{
return new StartMeasurementOp(this, devices, TestMethods.Synchro, test.Qfrom, test.Qto, totalPulses);
}
return null;
}
/// <summary>
/// Starts the measurement.
/// Events: MeasurementStarted
/// </summary>
/// <param name="flowMeter">Flow meter</param>
/// <param name="readers">An array of register readers</param>
/// <param name="refPulses">Number of reference pulses to complete the test</param>
/// <returns>Created operation</returns>
public IOperation StartProlongedMeasurementOp(OutputPath outputPath,
double requiredFlowLo, double requiredFlowHi,
int totalRefPulses, int massRefPulses, int delayBeforeFlowRegulation = 0)
{
if (controlBoardCfg.DebugLevel == DebugMode.Simulate)
{
return new Operations.ReturnGivenEventOp(Event.TestInProgress);
}
else
{
return new StartMeasurementOp(this, outputPath, TestMethods.Diverter | TestMethods.Synchro | TestMethods.MassAndContinue,
requiredFlowLo, requiredFlowHi, totalRefPulses, massRefPulses, delayBeforeFlowRegulation);
}
}
/// <summary>
/// Read diverter samples from the control board and calculated the transition time.
/// Events: Event.None
/// </summary>
/// <param name="div">Diverter</param>
/// <param name="runsCountWhenSendingCmd">State machine ticks from test start/end when diverter read command is issued (obsolete)</param>
/// <param name="runsCountWhenReadingDiv">State machine ticks from test start/end when diverter samples are read</param>
/// <param name="transitionTimeSec">FloatBox for the resulting transition time in s</param>
/// <param name="plotter">Statistics for plotting diverter transitions</param>
/// <param name="batchNr">Batch number</param>
/// <param name="testName">Test name (without repetitions)</param>
/// <param name="repetition">Repetition number</param>
/// <returns>Created operation</returns>
public IOperation ReadDiverterTransitionOp(bool isStart, Sequences.Statistics plotter, int batchNr, string testName, int repetition)
{
if (controlBoardCfg.DebugLevel == DebugMode.Simulate) return new Operations.ReturnGivenEventOp(Event.None);
return new ReadDiverterTransitionOp(this, devices.Diverter, 1, 3, isStart, plotter, batchNr, testName, repetition);
}
/// <summary>
/// Queries th econtrol board whether the measurement was completed.
/// Events: MeasurementCompleted or None
/// </summary>
/// <returns>Created operation</returns>
public IOperation QueryMeasurementEndOp()
{
return new QueryMeasurementEndOp(this);
}
/// <summary>
/// Stop controls board flow regulation operation
/// Events: FlowRegulationStopped
/// </summary>
/// <returns>Created operation</returns>
public IOperation StopFlowRegulationOp()
{
return new StopFlowRegulationOp(this);
}
/// <summary>
/// Stop the previous control board operation (diverter, gate, etc.)
/// Events: PreviousStopped
/// </summary>
/// <returns>Created operation</returns>
public IOperation StopPreviousOp()
{
return new StopPreviousOp(this);
}
/// <summary>
/// Sends commands to the control board.
/// Events: Event.None, Event.CommandCompleted
/// </summary>
/// <param name="commandOnStartOp">Command sent to CB when this operation starts</param>
/// <param name="commandOnStopOp">Command sent to CB when this operation stops</param>
/// <param name="testMethod">Test method parameter</param>
/// <returns>Created operation</returns>
public IOperation ExecuteCommandOp(Command commandOnStartOp, Command commandOnStopOp, TestMethods testMethod)
{
return new ExecuteCommandOp(this, commandOnStartOp, commandOnStopOp, testMethod);
}
}
}
@@ -1,389 +0,0 @@
///
/// Copyright (c) 2013-2019 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.Text;
using Dirichlet.Numerics;
using log4net;
namespace TBF.Rig.ControlBoard.Legacy
{
public class ControlComSim : IControlCom
{
private static readonly ILog log = LogManager.GetLogger(typeof(ControlComSim));
public override string ToString() { return string.Format("ControlComSim"); }
StatusP statusP;
public StatusP StatusP { get { return statusP; } }
double referenceFreq = 650.0;
public double ReferenceFreq { get { return referenceFreq; } }
public double ReferenceFreqs(int i) { return 0; }
int[] etPulses = new int[Config.Data.WMsCount + 1];
public int EtPulses(int wmNr1)
{
return etPulses[wmNr1];
}
public int EtPulsesK { get { return 1; } }
public int EtPulses2 { get { return 0; } }
public int EtPulses3 { get { return 0; } }
double[] errFactor = new double[Config.Data.WMsCount + 1]; /// Internal
double[] wMeterPulsesF = new double[Config.Data.WMsCount + 1]; /// Internal
UInt16[] wMeterPulses = new UInt16[Config.Data.WMsCount + 1]; /// Rounded from wMeterPulsesF
public UInt16 WMeterPulses(int wmNr1)
{
return wMeterPulses[wmNr1];
}
int[] wMeterReference = new int[Config.Data.WMsCount + 1];
public int WMeterReference(int wmNr1)
{
return wMeterReference[wmNr1];
}
public uint RegulValveDAC(int rvNr0) { return 0; }
public float Pressure(int prsNr0) { return 0; }
public float Temperature(int tmpNr0) { return (float)(20 + tmpNr0); }
public RegulValveState RegulValveState(int rvNr1) { return 0; }
public UInt128 RRoute { get { return simRoute; } }
public uint DivTime(int id) { return 0; }
public void SetDivLimit(int divNo, uint limLoPct, uint limHiPct) { }
float tTime = 1;
public float TTime { get { return tTime; } }
public float ImpulseTime(int wmNr1) { return tTime; }
public uint FmState { get { return 0; } }
public uint BeginState(int wmNr0) { return 0; }
double referenceFlow;
public double ReferenceFlow { get { return referenceFlow; } }
public float RValvePosition(int rvNr1) { return 0; }
public float DivSamples(int ms, int divIx0) { return 0; }
public int ScopeSamples(int i, int j, int k) { return 0; }
public ulong DigitalInputs { get { return 0; } }
public float AnalogInput(int adcNr0) { return 0; }
public uint AnalogInputRaw(int adcNr0, int bank) { return 0; } /// bank0=RV, bank1=Temp
public float TotalRefVolume { get { return 0; } }
public float VyslExt(int wmNr0, int what) { return 0; }
public void SetWeight(int pos, double mass) { return; } /// not available in sim. mode
public uint[] CyclePar { get { return cyclePar; } set { cyclePar = value; } } /// dummy
public uint[] WMeterCont { get { return wMeterCont; } } /// dummy
public float ValveOpenCloseTime { get { return 0.001f; } }
///
public bool ManualUIAllowed
{
get { return manualUIAllowed; }
set { manualUIAllowed = value; }
}
bool manualUIAllowed = true;
public void SetReservoirTemp(int nr, float temp) { }
///
/// Private initialization data updated by contructors of children components
/// and sent to 'controlCom2panel' by SendCalibData() method.
///
uint[,] regValveCalib;
byte[] meretRS485Address;
float[,] tempCalibData;
float[] etCalib;
uint[] diverterEdge;
uint[] balanceRange;
byte meretProtocol;
uint[] cyclePar;
uint[] wMeterCont;
///
/// Private values set by SendCommand()
///
Command cmd;
int refFlowmtrNr;
UInt128 simRoute;
int totalRefPulses;
int massRefPulses;
TestMethods testMethods;
uint[] filterConstants;
float[] FMFreq;
int regConst;
int shortImp;
StopDevs stopDevs;
///
/// Private values set by ValveMove()
///
int regulValveNo;
RegulValveMode regulValveMode;
double[] regulValveValue;
Random rand;
/// <summary>
/// Constructor
/// </summary>
public ControlComSim()
{
rand = new Random();
cyclePar = new uint[163];
wMeterCont = new uint[3] { 1, 2, 3 };
}
/// <summary>
/// Sends calibration and configuration data to the control board.
/// </summary>
/// <param name="rvCalib">Regulating valves calib.coefs, ix1 = valve nr. (1..5), ix2 = coef.nr. (0..1), values typ. c0 = 0, c1 = 0.2</param>
/// <param name="meretA">Meret address, index = 0..1, value typ. 99 and 100</param>
/// <param name="usedCom">COM port number of the control board (typ. 1)</param>
/// <param name="tempCalib">Temp.calc.coefs, ix1 = temp.sens.nr. (0..7 ???), ix2 = coef.nr</param>
/// <param name="etCalib">Etalon nominal values</param>
/// <param name="divEdge">Percentages for switching of diverters, ix = diverter nr.(0,1), typ.value 50 (%)</param>
public void SendCalibData(uint[,] rvCalib, byte[] meretA, int usedCom, float[,] tempCalib, float[] etCalib, uint[] divEdge, uint[] balanceRange, byte meretProtocol)
{
log.Info("SendCalibData(...)");
this.regValveCalib = rvCalib;
this.meretRS485Address = meretA;
this.tempCalibData = tempCalib;
this.etCalib = etCalib;
this.diverterEdge = divEdge;
this.balanceRange = balanceRange;
this.meretProtocol = meretProtocol;
}
/// <summary>
/// Sends a command to the control board.
/// </summary>
/// <param name="cmd">See ControlBoard.Command enum</param>
/// <param name="refFlowmtrNr">Number of the etalon/reference (1..5)</param>
/// <param name="route">State of valves, 128-bit word</param>
/// <param name="refPulses">kolko impulzov ma trvat skuska</param>
/// <param name="testMethods">See ControlBoard.TestMethods enum</param>
/// <param name="filterConstant">0 = No filtering (0..255)</param>
/// <param name="fmFreq">Freq.inverter control (not applicable in DT100, Munich)</param>
/// <param name="regConst">Coefficient used to control reg. valves (1..100)</param>
/// <param name="shortImp">0 = default value, 1 = spec. processing of very short pulses</param>
/// <param name="stopDevs">What to stop</param>
public void SendCommand(SendCommandArgs sendCommandArgs, UInt128 route, uint[] filterConstants, float[] fmFreq, int regConst, int shortImp)
{
log.InfoFormat("SendCommand(Cmd={0},Ref#={1},Route={2} {3} {4} {5},TotalPls={6},MassPls={7},TstM={8},filt={9},FM=[{10}{11}{12}{13}{14}{15}],Reg={16},ShrtImp={17},Stop={18})",
sendCommandArgs.Cmd, sendCommandArgs.RefFlowmtrNr, /// 0, 1
((route >> 48) & 0xFFFF).ToString("X4"), /// 2
((route >> 32) & 0xFFFF).ToString("X4"), /// 3
((route >> 16) & 0xFFFF).ToString("X4"), /// 4
(route & 0xFFFF).ToString("X4"), /// 5
totalRefPulses, massRefPulses, testMethods, filterConstants, /// 6, 7, 8, 9
fmFreq[0].ToString(), /// 10
(fmFreq.Length > 1) ? ("," + fmFreq[1].ToString()) : "", /// 11
(fmFreq.Length > 2) ? ("," + fmFreq[2].ToString()) : "", /// 12
(fmFreq.Length > 3) ? ("," + fmFreq[3].ToString()) : "", /// 13
(fmFreq.Length > 4) ? ("," + fmFreq[4].ToString()) : "", /// 14
(fmFreq.Length > 5) ? ("," + fmFreq[5].ToString()) : "", /// 15
regConst, shortImp, stopDevs); /// 16, 17, 18
///
/// Simulation
///
Command lastCmd = this.cmd;
this.cmd = sendCommandArgs.Cmd;
this.refFlowmtrNr = sendCommandArgs.RefFlowmtrNr;
#if FUZHOU_300
///
/// The following code deals with the situation that all FM controlled pums share bit #39.
/// In settings the bits of pumps should be sent as follows: P1=50, P2=51, P3=52, P4=53, P5=54 and P7=55
/// (in FUZHOU_300 the FM pump bit should be set set to value FMIndex+50).
///
bool bit39 = (route & 0x00FC000000000000) != 0; /// true if any of bits 50 through 55 is set
route = route & 0xFF03FFFFFFFFFFFF;
if (bit39) route = route | 0x0000008000000000;
log.DebugFormat("SendCommand route = {0}", Utils.RouteToStr(route));
#endif
TestBenchSim.SimRoute = this.simRoute = route;
this.totalRefPulses = sendCommandArgs.TotalRefPulses;
this.massRefPulses = sendCommandArgs.MassRefPulses;
this.testMethods = sendCommandArgs.TestMethods;
this.stopDevs = sendCommandArgs.StopDevs;
this.filterConstants = filterConstants;
this.FMFreq = fmFreq;
this.regConst = regConst;
this.shortImp = shortImp;
#pragma warning disable
statusP = (StatusP)(((ulong)statusP & (ulong)0xFFFFFFFFFFFFFFF8L) | (ulong)refFlowmtrNr);
#pragma warning restore
if (cmd == Command.Start && lastCmd != Command.Start )
{
statusP |= StatusP.TestInProgress;
///
/// Clear all counters
///
if (etPulses != null) { for (int i = 0; i < etPulses.Length; i++) etPulses[i] = 0; }
if (wMeterPulses != null) { for (int i = 0; i < wMeterPulses.Length; i++) wMeterPulses[i] = 0; }
if (wMeterPulsesF != null) { for (int i = 0; i < wMeterPulsesF.Length; i++) wMeterPulsesF[i] = 0; }
if (wMeterReference != null) { for (int i = 0; i < wMeterReference.Length; i++) wMeterReference[i] = 0; }
if (errFactor != null)
{
for (int i = 0; i < errFactor.Length; i++) errFactor[i] = ((float)rand.Next(100) + 950.0f) / 1000.0f;
}
tTime = 0;
}
else if (cmd == Command.Stop)
{
statusP = 0;
//statusP &= ~StatusP.Running;
}
}
/// <summary>
/// Control of regulating valves.
/// </summary>
/// <param name="regulValveNo">Regulating valve nr. (1..5)</param>
/// <param name="regulValveMode">???</param>
/// <param name="regulValveValue">???</param>
/// <param name="stableTime">Stabilization time when setting the flow: 0=200ms, step 50ms, max. 1.5 sec.</param>
public void ValveMove(int regulValveNo, RegulValveMode regulValveMode, double[] regulValveValue, int stableTime)
{
log.InfoFormat("ValveMove({0}, {1}, [{2},{3}], {4})", regulValveNo, regulValveMode, regulValveValue[0], regulValveValue[1], stableTime);
this.regulValveNo = regulValveNo;
this.regulValveMode = regulValveMode;
this.regulValveValue = regulValveValue;
}
public void RunDeviceBefore()
{
log.DebugFormat("RunDeviceBefore() ... regV#={0}, flowM#{1}, statusP={2}", regulValveNo, refFlowmtrNr, statusP.ToString("X"));
TestBenchSim.RunDevice(regulValveNo, refFlowmtrNr, statusP);
log.DebugFormat("refFreq={0}", referenceFreq);
tTime += 1.0f;
float Qnom = (regulValveNo > 0) ? etCalib[regulValveNo] : 0;
switch (cmd)
{
case Command.None:
break;
case Command.Start:
if ((testMethods & TestMethods.Diverter) == TestMethods.Diverter)
{
TestBenchSim.SetSimDiverter(true);
}
break;
case Command.Stop:
if ((testMethods & TestMethods.Diverter) == TestMethods.Diverter)
{
TestBenchSim.SetSimDiverter(false);
}
break;
}
switch (regulValveMode)
{
case RegulValveMode.TargetFrequency:
double targetFlow = ((regulValveValue[0] + regulValveValue[1]) / 2.0) * (Qnom / 2000.0);
TestBenchSim.UpdateSimFlow(targetFlow);
//if (referenceFreq < valveValue[0]) referenceFreq += ((float)rand.Next(20) + 10.0f) / 2.0f;
//else if (referenceFreq > valveValue[1]) referenceFreq -= ((float)rand.Next(20) + 10.0f) / 2.0f;
//else referenceFreq += ((float)rand.Next(10) - 5.0f) / 2.0f;
referenceFreq = TestBenchSim.GetSimFlow() * 2000.0 / Qnom;
if (referenceFreq < 0) referenceFreq = 0;
if (referenceFreq > 2500) referenceFreq = 2500;
break;
default:
break;
}
referenceFlow = referenceFreq / 2000.0;
bool stopTest = false;
if (cmd == Command.Start)
{
double pwFactor = 1.0;
/// Increment reference flow meters
for (int i = 0; i <= Config.Data.WMsCount; i++)
{
etPulses[i] += (int)referenceFreq;
if (etPulses[i] > totalRefPulses)
{
pwFactor = 1.0 - (etPulses[i] - totalRefPulses) / referenceFreq;
etPulses[i] = totalRefPulses;
stopTest = true;
}
}
/// Increment water meters
double flowLtrPerSec = TestBenchSim.GetSimFlow() / 1800.0;
for (int i = 1; i <= Config.Data.WMsCount; i++)
{
float wmPulsesPerLiter = 0;
if ((Rig.Sequences.ProcessData.RegisterReaders[i - 1] != null) &&
(Rig.Sequences.ProcessData.BatchRslts.Batch.WaterMeters.Count >= i) &&
(Rig.Sequences.ProcessData.BatchRslts.Batch.WaterMeters[i - 1] != null))
{
wmPulsesPerLiter = (float)Rig.Sequences.ProcessData.RegisterReaders[i-1].PulsesPerLtr;
}
wMeterPulsesF[i] += errFactor[i] * pwFactor * ((float)rand.Next(100) + 450.0f) * wmPulsesPerLiter * flowLtrPerSec;
wMeterPulses[i] = (UInt16)wMeterPulsesF[i];
}
if (etPulses[0] > totalRefPulses)
{
statusP |= StatusP.TestCompleted;
statusP &= ~StatusP.TestInProgress;
}
}
if (stopTest)
{
TestBenchSim.SetSimDiverter(false);
statusP = (statusP | StatusP.TestCompleted);
statusP = (statusP & ~StatusP.TestInProgress);
}
}
StatusP lastStatusP;
UInt128 lastRoute;
public void RunDeviceAfter()
{
StatusP bufferedStatusP = StatusP;
if (lastStatusP != bufferedStatusP)
{
string statusPStr = ((ulong)bufferedStatusP).ToString("x16");
log.InfoFormat("RunDeviceAfter() StatusP = {0}", statusPStr);
Program.MainWnd.UpdateStatusP(statusPStr);
lastStatusP = bufferedStatusP;
}
UInt128 bufferedRoute = simRoute;
if (lastRoute != bufferedRoute)
{
string routeStr = bufferedRoute.ToString("x16");
log.InfoFormat("RunDeviceAfter() Route = {0}", routeStr);
Program.MainWnd.UpdateRoute(routeStr);
lastRoute = bufferedRoute;
}
}
}
}
@@ -1,104 +0,0 @@
///
/// Copyright (c) 2016 Sensus Metering Systems
///
using System;
using log4net;
namespace TBF.Rig.ControlBoard.Legacy
{
public class ExecuteCommandOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(ExecuteCommandOp));
public override string ToString() { return string.Format("ExecuteCommandOp( command={0}, testMethod={1} )", commandOnStartOp, testMethod); }
/// Set by the constructor
readonly CBoard controlBoard;
readonly Command commandOnStartOp;
readonly Command commandOnStopOp;
readonly TestMethods testMethod;
///
/// Internal states of this operation
///
enum OpState
{
StartingCommand,
CommandStarted,
OpCompleted,
}
OpState opState;
/// <summary>
/// Starts the measurement.
/// Events: MeasurementStarted
/// </summary>
/// <param name="controlBoard">Control board component reference</param>
/// <param name="outputPath">Specifies used components</param>
/// <param name="testMethod">Test method</param>
/// <param name="refPulses">Test duration in number of reference flowmeter pulses</param>
/// <param name="filterConstant">Specifies filter for watermeter pulses</param>
public ExecuteCommandOp(CBoard controlBoard, Command commandOnStartOp, Command commandOnStopOp, TestMethods testMethod)
{
if (controlBoard == null) throw new ArgumentNullException("controlBoardDev");
this.controlBoard = controlBoard;
this.commandOnStartOp = commandOnStartOp;
this.commandOnStopOp = commandOnStopOp;
this.testMethod = testMethod;
log.Debug(this.ToString());
}
/// <summary>Start this operation</summary>
public void Start()
{
controlBoard.SyncRoute();
controlBoard.SendCommand(commandOnStartOp, 0, 0, 0, testMethod, StopDevs.None);
opState = OpState.StartingCommand;
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.FlowInDone or Event.FlowOutDone
/// </returns>
public Event Run()
{
if (opState == OpState.StartingCommand)
{
StatusP statusP = controlBoard.StatusP;
log.DebugFormat("statusP = {0} {1} {2} {3}",
(((ulong)statusP >> 48) & 0xFFFF).ToString("X4"),
(((ulong)statusP >> 32) & 0xFFFF).ToString("X4"),
(((ulong)statusP >> 16) & 0xFFFF).ToString("X4"),
((ulong)statusP & 0xFFFF).ToString("X4"));
log.Info("Run() - StartingCommand");
opState = OpState.CommandStarted;
return Event.None;
}
else if (opState == OpState.CommandStarted)
{
log.InfoFormat("Run() - CommandStarted");
opState = OpState.OpCompleted;
return Event.None;
}
else if (opState == OpState.OpCompleted)
{
return Event.CommandCompleted;
}
return Event.None;
}
/// <summary>Stop this operation</summary>
public void Stop()
{
if (commandOnStopOp != Command.None)
{
controlBoard.SyncRoute();
controlBoard.SendCommand(commandOnStopOp, 0, 0, 0, testMethod, StopDevs.None);
}
}
}
}
-35
View File
@@ -1,35 +0,0 @@
///
/// Copyright (c) 2013-2021 Sensus Slovensko a.s.
///
using System.Collections.Generic;
using TBF.Rig.Generic;
namespace TBF.Rig.ControlBoard.Legacy
{
public class Factory : IComponentFactory
{
public string ClassName { get { return GetType().Namespace.Substring(8); } }
public override string ToString() { return ClassName; }
/// <summary>Max. number of components of this class in the system</summary>
public int MaxCount { get { return 1; } }
public IComponent DummyComponent() { return new CBoard(); }
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new CBoard(cfg); }
public IComponentCfg DefaultConfig() { return new ControlBoardCfg(this); }
public IComponentCfgCtrl CreateCfgCtrl() { return new ControlBoardCfgCtrl(); }
public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList<Generic.IComponent> components)
{
return new CBoard((ControlBoardCfg)config);
}
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
{
return ComponentCfgBase.CreateFromDbEntity(ControlBoardCfg.Serializer, component, this);
}
}
}
@@ -1,84 +0,0 @@
///
/// Copyright (c) 2013-2019 Sensus Slovensko a.s.
///
using System;
using Dirichlet.Numerics;
namespace TBF.Rig.ControlBoard.Legacy
{
interface IControlCom
{
StatusP StatusP { get; }
int EtPulses(int wmNr1);
int EtPulsesK { get; }
int EtPulses2 { get; }
int EtPulses3 { get; }
UInt16 WMeterPulses(int wmNr1);
int WMeterReference(int wmNr0);
uint RegulValveDAC(int rvNr0);
float Pressure(int prsNr0);
float Temperature(int tmpNr0);
RegulValveState RegulValveState(int rvNr1);
UInt128 RRoute { get; }
uint DivTime(int id); /// 50% id=0, 10% id=1, 90% id=2
float TTime { get; }
float ImpulseTime(int WMNr1);
uint FmState { get; }
uint BeginState(int wmNr0);
double ReferenceFreq { get; }
double ReferenceFreqs(int i); /// Frequences for doble/tripple flowmeter
double ReferenceFlow { get; }
float RValvePosition(int rvNr1);
float DivSamples(int time, int divIx0); /// time unit is 2 ms
int ScopeSamples(int i, int j, int k);
ulong DigitalInputs { get; }
float AnalogInput(int adcNr0);
uint AnalogInputRaw(int adcNr0, int bank);
float TotalRefVolume { get; }
float VyslExt(int wmNr0, int what);
void SetWeight(int pos, double mass);
uint[] CyclePar { get; set; }
uint[] WMeterCont { get; }
bool ManualUIAllowed { get; set; }
float ValveOpenCloseTime { get; }
void SetDivLimit(int divNr, uint limLoPct, uint limHiPct);
void SetReservoirTemp(int nr, float temp);
/// <summary>
/// Sends calibration and configuration data to the control board.
/// </summary>
/// <param name="rvCalib">Regulating valves calib.coefs, ix1 = valve nr. (1..5), ix2 = coef.nr. (0..1), values typ. c0 = 0, c1 = 0.2</param>
/// <param name="meretA">Meret address, index = 0..1, value typ. 99 and 100</param>
/// <param name="usedCom">COM port number of the control board (typ. 1)</param>
/// <param name="tempCalib">Temp.calc.coefs, ix1 = temp.sens.nr. (0..7 ???), ix2 = coef.nr</param>
/// <param name="etCalib">Etalon nominal values</param>
/// <param name="divEdge">Percentages for switching of diverters, ix = diverter nr.(0,1), typ.value 50 (%)</param>
/// <param name="balanceRange">TODO</param>
/// <param name="meretProtocol">TODO</param>
void SendCalibData(uint[,] rvCalib, byte[] meretA, int usedCom, float[,] tempCalib, float[] etCalib, uint[] divEdge, uint[] balanceRange, byte meretProtocol);
/// <summary>
/// Updates a command that is regularly sent to the control board by SendCommand.
/// </summary>
/// <param name="sendCommandArgs">Arguments, see SendCommandArgs class</param>
/// <param name="route">State of valves, 128-bit word</param>
/// <param name="filterConstants">Array with length=8 of filter costants (0..255, 0 = no filtering)</param>
/// <param name="fmFreq">Freq.inverter control (not applicable in DT100, Munich)</param>
/// <param name="regConst">PID coefficient for flow control</param>
/// <param name="shortImp">0 = default value, 1 = spec. processing of very short pulses</param>
void SendCommand(SendCommandArgs sendCommandArgs, UInt128 route, uint[] filterConstants, float[] fmFreq, int regConst, int shortImp);
/// <summary>
/// Control of regulating valves.
/// </summary>
/// <param name="valveNo">Regulating valve nr. (1..5)</param>
/// <param name="valveMode">???</param>
/// <param name="valveValue">???</param>
/// <param name="stableTime">Stabilization time when setting the flow: 0=200ms, step 50ms, max. 1.5 sec.</param>
void ValveMove(int valveNo, RegulValveMode valveMode, double[] valveValue, int stableTime);
void RunDeviceBefore();
void RunDeviceAfter();
}
}
@@ -1,59 +0,0 @@
///
/// Copyright (c) 2013-2020 Sensus Slovensko a.s.
///
using System;
using log4net;
namespace TBF.Rig.ControlBoard.Legacy
{
public class QueryMeasurementEndOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(QueryMeasurementEndOp));
public override string ToString() { return string.Format("QueryMeasurementEndOp()"); }
/// Set by the constructor
readonly CBoard controlBoard;
bool done;
/// <summary>
/// Events: MeasurementCompleted
/// </summary>
/// <param name="eventDone">Event to be returned by Run() when completed OK</param>
public QueryMeasurementEndOp(CBoard controlBoardDev)
{
if (controlBoardDev == null) throw new ArgumentNullException("controlBoardDev");
this.controlBoard = controlBoardDev;
done = false;
log.Debug(this.ToString());
}
/// <summary> Start this operation </summary>
public void Start()
{
done = false;
}
/// <summary> Run this operation </summary>
/// <returns>
/// Event.FlowInDone or Event.FlowOutDone
/// </returns>
public Event Run()
{
if (done) return Event.TestCompleted;
if (0 != (controlBoard.StatusP & StatusP.TestCompleted))
{
done = true;
return Event.TestCompleted;
}
return Event.None;
}
/// <summary> Stop this operation </summary>
public void Stop()
{
}
}
}
@@ -1,200 +0,0 @@
///
/// Copyright (c) 2017 Sensus Metering Systems
///
using System;
using log4net;
using TBF.Boxes;
namespace TBF.Rig.ControlBoard.Legacy
{
public class ReadDiverterTransitionOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(ReadDiverterTransitionOp));
public override string ToString()
{
return string.Format("ReadDiverterTransitionOp(.,{0},{1},{2},...)", div.Name, runsCountWhenSendingCmd, runsCountWhenReadingDiv);
}
const int SamplesCount = 240; /// Should be less then or equal to 256
float[] samples;
/// Set by the constructor
readonly CBoard controlBoard;
readonly GenericDevices.IDiverter div;
readonly bool toTank;
readonly int runsCountWhenSendingCmd;
readonly int runsCountWhenReadingDiv;
readonly Sequences.Statistics plotter;
readonly int batchNr;
readonly string testName;
readonly int repetition;
int counter;
/// <summary>
/// Starts the measurement.
/// Events: MeasurementStarted
/// </summary>
/// <param name="controlBoard">Control board component reference</param>
/// <param name="outputPath">Specifies used components</param>
/// <param name="method">Test method</param>
/// <param name="refPulses">Test duration in number of reference flowmeter pulses</param>
/// <param name="filterConstant">Specifies filter for watermeter pulses</param>
public ReadDiverterTransitionOp(CBoard controlBoard, GenericDevices.IDiverter div, int runsCountWhenSendingCmd, int runsCountWhenReadingDiv, bool toTank,
Sequences.Statistics plotter, int batchNr, string testName, int repetition)
{
if (controlBoard == null) throw new ArgumentNullException("controlBoardDev");
if (div == null) throw new ArgumentNullException("div");
if (runsCountWhenSendingCmd < 0) throw new ArgumentNullException("runsCountWhenSendingCmd");
if (runsCountWhenReadingDiv <= runsCountWhenSendingCmd) throw new ArgumentNullException("runsCountWhenReadingDiv");
this.controlBoard = controlBoard;
this.div = div;
this.runsCountWhenSendingCmd = runsCountWhenSendingCmd;
this.runsCountWhenReadingDiv = runsCountWhenReadingDiv;
this.toTank = toTank;
this.plotter = plotter;
this.batchNr = batchNr;
this.testName = testName;
this.repetition = repetition;
samples = new float[SamplesCount];
log.Debug(this.ToString());
}
/// <summary>Start this operation</summary>
public void Start()
{
counter = 0;
if (runsCountWhenSendingCmd == 0 && div.DiverterNr > 0)
{
SendCommand();
log.DebugFormat("Start() ... Sending a command to read diverter {0}", div.Name);
}
if (plotter != null)
{
plotter.Start(batchNr, testName, repetition);
log.DebugFormat("Start() ... plotter.Start({0}, {1}, {2})", batchNr, testName, repetition);
}
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.FlowInDone or Event.FlowOutDone
/// </returns>
public Event Run()
{
counter++;
if (counter == runsCountWhenSendingCmd && div.DiverterNr > 0)
{
SendCommand();
log.DebugFormat("Run() ... Sending a command to read diverter {0}", div.Name);
}
else if (counter == runsCountWhenReadingDiv && div.DiverterNr > 0)
{
if (plotter == null)
{
ReadDiverterTransitionTimes();
log.DebugFormat("Run() ... Reading diverter {0} transition times: {1}s", div.Name, (toTank ? div.SwitchTimeStart : div.SwitchTimeEnd).Val);
}
else
{
log.DebugFormat("Run() ... Reading diverter {0} samples", div.Name);
for (int i = 0; i < SamplesCount; i++)
{
float oneSample = controlBoard.DivSamples(i, div.DiverterNr - 1);
samples[i] = oneSample;
plotter.Update(oneSample);
}
plotter.Stop();
log.DebugFormat("Run() ... Calculating diverter {0} transition times: {1}s", div.Name, (toTank ? div.SwitchTimeStart : div.SwitchTimeEnd).Val);
CalculateDiverterTransitionTimes();
}
}
return Event.None;
}
/// <summary>Stop this operation</summary>
public void Stop()
{
log.DebugFormat("Stop()");
}
void SendCommand()
{
controlBoard.SyncRoute();
controlBoard.SendCommand(Command.ReadDivTransition, 0, 0, 0, 0, StopDevs.None);
}
/// <summary>
/// Diverter transition time is read from the control board
/// </summary>
/// <returns>true (always)</returns>
bool ReadDiverterTransitionTimes()
{
(toTank ? div.SwitchTimeStart : div.SwitchTimeEnd).Val = (float)controlBoard.DivTime(2) - (float)controlBoard.DivTime(1);
return true;
}
/// <summary>
/// Diverter transition time is calculated from ADC samples and threshold levels
/// </summary>
/// <returns>true when transition time calculated OK</returns>
bool CalculateDiverterTransitionTimes()
{
bool startedRising = false;
bool startedFalling = false;
bool stopped = false;
int transitionStartIdx = 0;
int transitionEndIdx = 0;
float level = samples[0];
for (int i = 1; i < SamplesCount; i++)
{
if (!startedRising && !startedFalling)
{
if (level <= div.ThresholdLo && samples[i] > div.ThresholdLo)
{
transitionStartIdx = i;
startedRising = true;
}
else if (level >= div.ThresholdHi && samples[i] < div.ThresholdHi)
{
transitionStartIdx = i;
startedFalling = true;
}
}
else if (startedRising && !stopped && level < div.ThresholdHi && samples[i] >= div.ThresholdHi)
{
transitionEndIdx = i;
stopped = true;
break;
}
else if (startedFalling && !stopped && level > div.ThresholdLo && samples[i] <= div.ThresholdLo)
{
transitionEndIdx = i;
stopped = true;
break;
}
}
if ((startedRising || startedFalling) && stopped)
{
(toTank ? div.SwitchTimeStart : div.SwitchTimeEnd).Val = 0.002f * (float)(transitionEndIdx - transitionStartIdx); /// 2 ms per sample
return true;
}
else
{
return false;
}
}
}
}
-70
View File
@@ -1,70 +0,0 @@
///
/// Copyright (c) 2017 Sensus Slovensko a.s.
///
using System;
using log4net;
using TBF.Boxes;
namespace TBF.Rig.ControlBoard.Legacy
{
public class ReadFlowOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(ReadFlowOp));
public override string ToString() { return string.Format("ReadFlowOp({0},.,.,{1})", flowMeter.Idx1, eventDone); }
/// Set by the constructor
readonly GenericDevices.IFlowMeter flowMeter;
readonly CBoard controlBoard;
readonly DoubleBox flowBox;
readonly Event eventDone;
/// <summary>
/// Events: FlowInDone, FlowOutDone or Error
/// </summary>
/// <param name="flowMeter">Flow meter reference</param>
/// <param name="flowBox">Reference to the measured flow variable, value is in bar</param>
/// <param name="eventDone">Event to be returned by Run() when completed OK</param>
public ReadFlowOp(GenericDevices.IFlowMeter flowMeter, CBoard controlBoard, ref DoubleBox flowBox, Event eventDone)
{
if (flowMeter == null || controlBoard == null) throw new ArgumentNullException();
this.flowMeter = flowMeter;
this.controlBoard = controlBoard;
this.eventDone = eventDone;
this.flowBox = flowBox;
log.Debug(this.ToString());
}
public ReadFlowOp(GenericDevices.IFlowMeter flowMeter, CBoard controlBoard, ref DoubleBox flowBox)
: this(flowMeter, controlBoard, ref flowBox, Event.FlowMeasurementDone)
{
}
/// <summary>Start this operation</summary>
public void Start()
{
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.FlowInDone or Event.FlowOutDone
/// </returns>
public Event Run()
{
if ((int)(controlBoard.StatusP & StatusP.RefFlowMeterMask) == flowMeter.Idx1)
{
flowBox.Val = flowMeter.ReadFlow();
return eventDone;
}
else
{
return Event.Error;
}
}
/// <summary>Stop this operation</summary>
public void Stop()
{
}
}
}
@@ -1,33 +0,0 @@
///
/// Copyright (c) 2019 Sensus Slovensko a.s.
///
using System;
using Dirichlet.Numerics;
namespace TBF.Rig.ControlBoard.Legacy
{
public class SendCommandArgs
{
public Command Cmd;
public int RefFlowmtrNr;
public int TotalRefPulses;
public int MassRefPulses;
public TestMethods TestMethods;
public StopDevs StopDevs;
public SendCommandArgs()
{
}
public SendCommandArgs(Command cmd, int refFlowmtrNr, int totalRefPulses, int massRefPulses,
TestMethods testMethods, StopDevs stopDevs)
{
Cmd = cmd;
RefFlowmtrNr = refFlowmtrNr;
TotalRefPulses = totalRefPulses;
MassRefPulses = massRefPulses;
TestMethods = testMethods;
StopDevs = stopDevs;
}
}
}
@@ -1,223 +0,0 @@
///
/// Copyright (c) 2013-2020 Sensus Slovensko a.s.
///
using System;
using log4net;
using TBF.Rig.GenericDevices;
namespace TBF.Rig.ControlBoard.Legacy
{
public class StartMeasurementOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(StartMeasurementOp));
public override string ToString() { return string.Format("StartMeasurementOp(ref={0},pulses={1})", flowMeterNr, totalRefPulses); }
/// Set by the constructor
readonly CBoard controlBoard;
readonly IRegValve regulValve;
readonly int regulValveNr;
readonly int regulValveStableTime;
readonly int flowMeterNr;
readonly double nominalFlow;
readonly double maximalFlow;
readonly double reqFlowLo;
readonly double reqFlowHi;
readonly int totalRefPulses; /// Number of reference pulses for a complete test
readonly int massRefPulses; /// Number of reference pulses for mass collection
readonly int delayBeforeFlowRegulation; /// Delay before flow control starts in seconds
readonly TestMethods testMethod;
readonly int diverterNr;
///
/// Internal states of this operation
///
enum OpState
{
StartingTest,
ResendCommand,
WaitingBeforeValveMove,
StartingFlowRegulation,
OpCompleted,
}
OpState opState;
int delayStartTime; /// StateMachine.Time snapshot when delay before flow regulation starts
/// <summary>
/// Starts the measurement.
/// Events: MeasurementStarted
/// </summary>
/// <param name="controlBoard">Control board component reference</param>
/// <param name="outputPath">Specifies used components</param>
/// <param name="method">Test method</param>
/// <param name="totalRefPulses">Test duration in number of reference flowmeter pulses</param>
/// <param name="filterConstant">Specifies filter for watermeter pulses</param>
public StartMeasurementOp(CBoard controlBoard, OutputPath outputPath, TestMethods method,
double requiredFlowLo, double requiredFlowHi, int refPulses, int delayBeforeFlowRegulation = 0)
: this(controlBoard, outputPath, method, requiredFlowLo, requiredFlowHi, refPulses, refPulses, delayBeforeFlowRegulation)
{
}
/// <summary>
/// Starts the measurement.
/// Events: MeasurementStarted
/// </summary>
/// <param name="controlBoard">Control board component reference</param>
/// <param name="outputPath">Specifies used components</param>
/// <param name="method">Test method</param>
/// <param name="refPulses">Test duration in number of reference flowmeter pulses</param>
/// <param name="filterConstant">Specifies filter for watermeter pulses</param>
public StartMeasurementOp(CBoard controlBoard, OutputPath outputPath, TestMethods method,
double requiredFlowLo, double requiredFlowHi, int totalRefPulses, int massRefPulses, int delayBeforeFlowRegulation = 0)
{
if (controlBoard == null) throw new ArgumentNullException("controlBoardDev");
this.controlBoard = controlBoard;
if (outputPath.FlowMeter == null) throw new ArgumentNullException("Flow meter is missing");
flowMeterNr = outputPath.FlowMeter.Idx1;
this.regulValve = outputPath.RegValve;
regulValveNr = 0;
regulValveStableTime = 0;
if (outputPath.Diverter is TBF.Rig.Uni.Diverter.Diverter)
{
diverterNr = (outputPath.Diverter as TBF.Rig.Uni.Diverter.Diverter).DiverterNr;
}
nominalFlow = outputPath.FlowMeter.NominalFlow;
maximalFlow = 1.25 * nominalFlow;
this.testMethod = method;
this.reqFlowLo = requiredFlowLo;
this.reqFlowHi = requiredFlowHi;
this.totalRefPulses = totalRefPulses;
this.massRefPulses = massRefPulses;
this.delayBeforeFlowRegulation = delayBeforeFlowRegulation;
log.Debug(this.ToString());
}
void SendStartCommand()
{
controlBoard.SyncRoute();
#if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL || BADGER_VELKA_TRAT || SLM_50
int flowMeterIdxAndDiv = flowMeterNr + 16 * diverterNr;
#elif BADGER_STREDNA_TRAT
int flowMeterIdxAndDiv = flowMeterNr + 8 * (diverterNr - 1);
#elif FILIPINY_50
int flowMeterIdxAndDiv = flowMeterNr + ((flowMeterNr == 3) ? (4 * (diverterNr - 1)) : 0);
#elif GELSENWASSER
int flowMeterIdxAndDiv = flowMeterNr + ((diverterNr == 2) ? 16 : 0);
#else
int flowMeterIdxAndDiv = flowMeterNr;
#endif
log.InfoFormat("Start() : SendCommand(Cmd.Start, {0}, route, {1}, {1}, {2}, Stop.None)",
flowMeterIdxAndDiv, totalRefPulses, testMethod);
controlBoard.SendCommand(Command.Start, flowMeterIdxAndDiv, totalRefPulses, massRefPulses, testMethod, StopDevs.None);
}
/// <summary>Start this operation</summary>
public void Start()
{
SendStartCommand();
opState = OpState.StartingTest;
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.FlowInDone or Event.FlowOutDone
/// </returns>
public Event Run()
{
if (opState == OpState.StartingTest)
{
StatusP statusP = controlBoard.StatusP;
log.DebugFormat("statusP = {0} {1} {2} {3}",
(((ulong)statusP >> 48) & 0xFFFF).ToString("X4"),
(((ulong)statusP >> 32) & 0xFFFF).ToString("X4"),
(((ulong)statusP >> 16) & 0xFFFF).ToString("X4"),
((ulong)statusP & 0xFFFF).ToString("X4"));
if ((statusP & StatusP.TestInProgress) != 0)
{
log.Info("Test started");
if (delayBeforeFlowRegulation > 0)
{
delayStartTime = StateMachine.Time;
opState = OpState.WaitingBeforeValveMove;
}
else
{
opState = OpState.StartingFlowRegulation;
}
}
else
{
//opState = OpState.ResendCommand;
}
return Event.None;
}
else if (opState == OpState.ResendCommand)
{
SendStartCommand();
opState = OpState.StartingTest;
return Event.None;
}
else if (opState == OpState.WaitingBeforeValveMove)
{
if (StateMachine.Time - delayStartTime >= delayBeforeFlowRegulation)
{
opState = OpState.StartingFlowRegulation;
}
return Event.None;
}
else if (opState == OpState.StartingFlowRegulation)
{
///
/// Done once, issues an appropriate ValveMove(...) command
///
if ((reqFlowLo >= reqFlowHi) || (reqFlowLo > maximalFlow) || (reqFlowHi <= 0))
{
return Event.OpArgumentError;
}
log.InfoFormat("Run(): rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3}",
regulValveNr, flowMeterNr, reqFlowLo, reqFlowHi);
double freqLo = 2000.0 * reqFlowLo / nominalFlow;
double freqHi = 2000.0 * reqFlowHi / nominalFlow;
if (regulValve.IsCoax)
{
controlBoard.ValveMove(regulValveNr, RegulValveMode.TargetFrequency,
new double[2] { (freqLo + freqHi) / 2, (freqLo + freqHi) / 2 },
regulValveStableTime);
}
else
{
controlBoard.ValveMove(regulValveNr, RegulValveMode.TargetFrequency,
new double[2] { freqLo, freqHi },
regulValveStableTime);
}
opState = OpState.OpCompleted;
return Event.None;
}
else if (opState == OpState.OpCompleted)
{
return Event.TestInProgress;
}
return Event.None;
}
/// <summary>Stop this operation</summary>
public void Stop()
{
}
}
}
@@ -1,62 +0,0 @@
///
/// Copyright (c) 2019 Sensus Slovensko a.s.
///
using System;
using log4net;
namespace TBF.Rig.ControlBoard.Legacy
{
class StopFlowRegulationOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(StopFlowRegulationOp));
public override string ToString() { return string.Format("StopFlowRegulationOp(.)"); }
/// Set by the constructor
readonly CBoard controlBoard;
readonly int flowMeterNr;
/// <summary>
/// Stop the previous control board operation (diverter, gate, etc.)
/// Events: None or PreviousStopped
/// </summary>
/// <param name="controlBoardDev">Control board component reference</param>
public StopFlowRegulationOp(CBoard controlBoardDev)
{
if (controlBoardDev == null) throw new ArgumentNullException("controlBoardDev");
this.controlBoard = controlBoardDev;
if (controlBoardDev.Devices.FlowMeter == null) throw new ArgumentNullException("Flow meter is missing");
flowMeterNr = controlBoardDev.Devices.FlowMeter.Idx1;
log.Debug(this.ToString());
}
void SendStopFlowRegulationCommand()
{
controlBoard.SyncRoute();
controlBoard.SendCommand(Command.Stop, flowMeterNr, 0, 0, 0, StopDevs.RegValveRegulation);
}
/// <summary>Start this operation</summary>
public void Start()
{
SendStopFlowRegulationCommand();
}
/// <summary>Run this operation</summary>
/// <returns>Event.FlowRegulationStopped</returns>
public Event Run()
{
return Event.FlowRegulationStopped;
}
/// <summary>Stop this operation</summary>
public void Stop()
{
}
}
}
@@ -1,107 +0,0 @@
///
/// Copyright (c) 2013-2015 Sensus Metering Systems
///
using System;
using log4net;
namespace TBF.Rig.ControlBoard.Legacy
{
public class StopPreviousOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(StopPreviousOp));
public override string ToString() { return string.Format("StopPreviousOp(.)"); }
/// Set by the constructor
readonly CBoard controlBoard;
///
/// Internal states of this operation
///
enum OpState
{
Idle = 0,
CheckIfStopped,
ResendCommand,
Stopped,
}
OpState opState;
/// <summary>
/// Stop the previous control board operation (diverter, gate, etc.)
/// Events: None or PreviousStopped
/// </summary>
/// <param name="controlBoardDev">Control board component reference</param>
public StopPreviousOp(CBoard controlBoardDev)
{
if (controlBoardDev == null) throw new ArgumentNullException("controlBoardDev");
this.controlBoard = controlBoardDev;
log.Debug(this.ToString());
}
void SendStopCommand()
{
controlBoard.SyncRoute();
controlBoard.SendCommand(Command.Stop, 0, 0, 0, TestMethods.Diverter,
StopDevs.Diverter | StopDevs.GatePulse | StopDevs.Reference | StopDevs.RegValveRegulation);
}
/// <summary>Start this operation</summary>
public void Start()
{
SendStopCommand();
opState = OpState.CheckIfStopped;
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.None or Event.PreviousStopped
/// </returns>
public Event Run()
{
if (opState == OpState.CheckIfStopped)
{
if ((controlBoard.StatusP & (StatusP.TestCompleted | StatusP.TestInProgress)) == 0)
{
opState = OpState.Stopped;
return Event.PreviousStopped;
}
else
{
opState = OpState.ResendCommand;
return Event.None;
}
}
else if (opState == OpState.ResendCommand)
{
if ((controlBoard.StatusP & (StatusP.TestCompleted | StatusP.TestInProgress)) == 0)
{
opState = OpState.Stopped;
return Event.PreviousStopped;
}
else
{
SendStopCommand();
opState = OpState.CheckIfStopped;
return Event.None;
}
}
else if (opState == OpState.Stopped)
{
return Event.PreviousStopped;
}
return Event.None;
}
/// <summary>Stop this operation</summary>
public void Stop()
{
opState = OpState.Idle;
}
}
}
-774
View File
@@ -1,774 +0,0 @@
///
/// Copyright (c) 2013-2020 Sensus Slovensko a.s.
///
using System;
using Dirichlet.Numerics;
using log4net;
namespace TBF.Rig.ControlBoard.Legacy
{
/// <summary>
/// Test bench model inherited by all classes for the simulation of devices.
/// Define DN100, MUNICH or nothing.
/// </summary>
public static class TestBenchSim
{
private static readonly ILog log = LogManager.GetLogger(typeof(TestBenchSim));
///
/// Incremented in RunDevice() depending on diverters and valves
///
public static double Mass1sim; /// Volume in [ltr] or mass in [kg] in the tank1 on the balance1, filled by the diverter1
public static double Mass2sim; /// Volume in [ltr] or mass in [kg] in the tank2 on the balance2, filled by the diverter2
///
/// Set by regulation valves
///
public static double Flow1sim; /// flow in [m3/h] through RV1
public static double Flow2sim; /// flow in [m3/h] through RV2
public static double Flow3sim; /// flow in [m3/h] through RV3
public static double Flow4sim; /// flow in [m3/h] through RV4
public static double Flow5sim; /// flow in [m3/h] through RV5
public static double Flow6sim; /// flow in [m3/h] through RV5
///
/// Valves and diverters
///
public static UInt128 SimRoute;
public static bool Div1sim;
public static bool Div2sim;
public static bool Div3sim;
static int regulValveNo; /// 0=undefined, 1..5
static int refFlowmtrNo; /// 0=undefined, 1..4
public static void Initialize()
{
Mass1sim = 0; /// Initialize tanks
Mass2sim = 0;
Flow1sim = 0; /// Initialize regulation valves
Flow2sim = 0;
Flow3sim = 0;
Flow4sim = 0;
Flow5sim = 0;
Flow6sim = 0;
SimRoute = 0; /// Initialize other valves
Div1sim = false;
Div2sim = false;
Div3sim = false;
}
#if DN100
/// Paths modulating the flows
const ulong K5 = (1L << 0);
const ulong K7 = (1L << 1);
const ulong K10 = (1L << 2);
const ulong K13 = (1L << 3);
const ulong K16 = (1L << 4);
const ulong K2 = (1L << 5);
const ulong EmptyValve1 = (1L << 17);
const ulong EmptyValve2 = (1L << 18);
const ulong Vl5 = (1L << 21);
const ulong Path1 = K2 | K5 | K7;
const ulong Path2 = K2 | K5 | K10;
const ulong Path3 = K2 | K5 | K13;
const ulong Path4 = K2 | K5 | K16;
const ulong Path5 = K2 | K5 | Vl5;
#elif MUNICH
const ulong VL11 = (1L << 0);
const ulong VL13 = (1L << 1);
const ulong VL21 = (1L << 2);
const ulong VL23 = (1L << 3);
const ulong VZ1 = (1L << 4);
const ulong VP2 = (1L << 5);
const ulong VP4 = (1L << 6);
const ulong VP5 = (1L << 7);
const ulong VP6 = (1L << 8);
const ulong VL12 = (1L << 9);
const ulong VL22 = (1L << 10);
const ulong VI11 = (1L << 11);
const ulong VI12 = (1L << 12);
const ulong VI13 = (1L << 13);
const ulong VI21 = (1L << 14);
const ulong VI22 = (1L << 15);
const ulong VI2P = (1L << 16);
const ulong VI31 = (1L << 17);
const ulong VI32 = (1L << 18);
const ulong VI3P = (1L << 19);
const ulong VI41 = (1L << 20);
const ulong VI42 = (1L << 21);
const ulong VI43 = (1L << 22);
const ulong VI4P = (1L << 23);
const ulong VB1 = (1L << 24);
const ulong VB1a = (1L << 25);
const ulong VB2 = (1L << 26);
const ulong VB2a = (1L << 27);
const ulong VM1 = (1L << 28);
const ulong VM2 = (1L << 29);
const ulong VM3 = (1L << 30);
const ulong VM4 = ((ulong)1 << 31);
const ulong Pump1 = ((ulong)1 << 32);
const ulong Block = ((ulong)1 << 33);
const ulong VZ8 = ((ulong)1 << 37);
const ulong EmptyValve1 = VB1 | VB1a;
const ulong EmptyValve2 = VB2 | VB2a;
const ulong Path1 = VZ1 | VL12 | VI11 | VI13;
const ulong Path2 = VZ1 | VL11 | VL12 | VI21 | VI22 | VI13;
const ulong Path3 = VZ1 | VL11 | VL12 | VI31 | VI32;
const ulong Path4 = VZ1 | VL11 | VL12 | VI41 | VI42;
const ulong Path5 = VZ1 | VL11 | VL12 | VI41 | VI43;
#elif FUZHOU_150
const ulong VL11 = (1L << 2);
const ulong VL13 = (1L << 3);
const ulong VL4 = (1L << 4);
const ulong VZ6 = (1L << 5);
const ulong VZ7 = (1L << 6);
const ulong VP5 = (1L << 7);
const ulong VP6 = (1L << 8);
const ulong VL12 = (1L << 9);
const ulong VZ14 = (1L << 10);
const ulong VI11 = (1L << 11);
const ulong VI12 = (1L << 12);
const ulong VI13 = (1L << 13);
const ulong VI21 = (1L << 14);
const ulong VI22 = (1L << 15);
const ulong VI2p = (1L << 16);
const ulong VI31 = (1L << 17);
const ulong VI32 = (1L << 18);
const ulong VI3p = (1L << 19);
const ulong VI41 = (1L << 20);
const ulong VI42 = (1L << 21);
const ulong VI43 = (1L << 22);
const ulong VI4p = (1L << 23);
const ulong VB1 = (1L << 24);
const ulong VB1a = (1L << 25);
const ulong VB2 = (1L << 26);
const ulong VB2a = (1L << 27);
const ulong VM1 = (1L << 28);
const ulong VM2 = (1L << 29);
const ulong VM3 = (1L << 20);
const ulong Pump1 = ((ulong)1 << 32);
const ulong Pump4 = ((ulong)1 << 33);
const ulong Pump2 = ((ulong)1 << 37);
const ulong Pump3 = ((ulong)1 << 38);
const ulong Pump5 = ((ulong)1 << 39);
const ulong EmptyValve1 = VB1 | VB1a;
const ulong EmptyValve2 = VB2 | VB2a;
const ulong Path1 = VL12 | VI11 | VI13;
const ulong Path2 = VL12 | VI21 | VI22 | VI13;
const ulong Path3 = VL12 | VI31 | VI32;
const ulong Path4 = VL12 | VI41 | VI42;
const ulong Path5 = VL12 | VI41 | VI43;
#elif FUZHOU_300
const ulong VL11 = (1L << 2);
const ulong VL13 = (1L << 3);
const ulong VL4 = (1L << 4);
const ulong VZ6 = (1L << 5);
const ulong VZ7 = (1L << 6);
const ulong VP5 = (1L << 7);
const ulong VP6 = (1L << 8);
const ulong VL12 = (1L << 9);
const ulong VZ14 = (1L << 10);
const ulong VI11 = (1L << 11);
const ulong VI12 = (1L << 12);
const ulong VI13 = (1L << 13);
const ulong VI21 = (1L << 14);
const ulong VI22 = (1L << 15);
const ulong VI2p = (1L << 16);
const ulong VI31 = (1L << 17);
const ulong VI32 = (1L << 18);
const ulong VI3p = (1L << 19);
const ulong VI41 = (1L << 20);
const ulong VI42 = (1L << 21);
const ulong VI43 = (1L << 22);
const ulong VI4p = (1L << 23);
const ulong VB1 = (1L << 24);
const ulong VB1a = (1L << 25);
const ulong VB2 = (1L << 26);
const ulong VB2a = (1L << 27);
const ulong VM1 = (1L << 28);
const ulong VM2 = (1L << 29);
const ulong VM3 = (1L << 20);
const ulong Pump1 = ((ulong)1 << 32);
const ulong Pump4 = ((ulong)1 << 33);
const ulong Pump2 = ((ulong)1 << 37);
const ulong Pump3 = ((ulong)1 << 38);
const ulong Pump5 = ((ulong)1 << 39);
const ulong EmptyValve1 = VB1 | VB1a;
const ulong EmptyValve2 = VB2 | VB2a;
const ulong Path1 = VL12 | VI11 | VI13;
const ulong Path2 = VL12 | VI21 | VI22 | VI13;
const ulong Path3 = VL12 | VI31 | VI32;
const ulong Path4 = VL12 | VI41 | VI42;
const ulong Path5 = VL12 | VI41 | VI43;
#elif IZRAEL_200 || PUCHONG_200 || GENESIS || BERLIN || GELSENWASSER
const ulong VM11 = (1L << 4);
const ulong VM12 = (1L << 5);
const ulong VM21 = (1L << 6);
const ulong VM22 = (1L << 7);
const ulong VZ14 = (1L << 8);
const ulong VZ13 = (1L << 9);
const ulong VL11 = (1L << 10);
const ulong VL13 = (1L << 11);
const ulong VL4 = (1L << 12);
const ulong VZ6 = (1L << 13);
const ulong VZ7 = (1L << 14);
const ulong VP5 = (1L << 15);
const ulong VP6 = (1L << 16);
const ulong VL12 = (1L << 17);
const ulong VL51 = (1L << 18);
const ulong VL53 = (1L << 19);
const ulong VI11 = (1L << 20);
const ulong VI12 = (1L << 21);
const ulong VI13 = (1L << 22);
const ulong VV1 = (1L << 23);
const ulong VI21 = (1L << 25);
const ulong VI22 = (1L << 26);
const ulong VI2p = (1L << 27);
const ulong VI31 = (1L << 28);
const ulong VI32 = (1L << 29);
const ulong VI3p = (1L << 30);
const ulong VI41 = (1L << 31);
const ulong VI42 = (1L << 32);
const ulong VI4p = (1L << 33);
const ulong VI43 = (1L << 37);
const ulong VM1 = (1L << 50);
const ulong VM2 = (1L << 51);
const ulong VM3 = (1L << 52);
const ulong VB1 = (1L << 41);
const ulong VB1a = (1L << 42);
const ulong VB2 = (1L << 43);
const ulong VB2a = (1L << 44);
const ulong Pump1 = (1L << 48);
const ulong Pump4 = (1L << 49);
const ulong Pump2 = (1L << 38);
const ulong Pump3 = (1L << 39);
const ulong Pump5 = (1L << 40);
const ulong EmptyValve1 = VB1 | VB1a;
const ulong EmptyValve2 = VB2 | VB2a;
const ulong Path1 = VL12 | VI11 | VI13;
const ulong Path2 = VL12 | VI21 | VI22 | VI13;
const ulong Path3 = VL12 | VI31 | VI32;
const ulong Path4 = VL12 | VI41 | VI42;
const ulong Path5 = VL12 | VI41 | VI43;
#elif BADGER_MALA_TRAT || BADGER_STREDNA_TRAT || BADGER_VELKA_TRAT
const ulong VZ34 = (1L << 0);
const ulong VZ35 = (1L << 1);
const ulong VZ39 = (1L << 2);
const ulong VZ37 = (1L << 3);
const ulong VZ38 = (1L << 4);
const ulong VL31 = (1L << 5);
const ulong VV1 = (1L << 6);
const ulong VS33 = (1L << 7);
const ulong VS31 = (1L << 8);
const ulong VS32 = (1L << 9);
const ulong VV2 = (1L << 10);
const ulong VL32 = (1L << 11);
const ulong VI31 = (1L << 12);
const ulong VI32 = (1L << 13);
const ulong VI33 = (1L << 14);
const ulong VI34 = (1L << 15);
const ulong DIV1 = (1L << 16);
const ulong DIV2 = (1L << 17);
const ulong VB1 = (1L << 18);
const ulong VB1a = (1L << 19);
const ulong VB2 = (1L << 20);
const ulong VB2a = (1L << 21);
const ulong P1 = (1L << 22);
const ulong P2 = (1L << 23);
const ulong EmptyValve1 = VB1 | VB1a;
const ulong EmptyValve2 = VB2 | VB2a;
const ulong Path1 = VI31;
const ulong Path2 = VI32;
const ulong Path3 = VI33;
const ulong Path4 = VI34;
const ulong Path5 = 0;
#elif CEVAK_40 || MURES_40 || FUZHOU_50 || SLM_50 || MALTA_WSD25
const ulong VL11 = (1L << 0);
const ulong VL13 = (1L << 1);
const ulong VL18 = (1L << 2);
const ulong VZ12 = (1L << 3);
const ulong VL15 = (1L << 4);
const ulong VL21 = (1L << 5);
const ulong VL23 = (1L << 6);
const ulong VL28 = (1L << 7);
const ulong VZ5 = (1L << 8);
const ulong VI1 = (1L << 9);
const ulong VI2 = (1L << 10);
const ulong VI3 = (1L << 11);
const ulong VZ9 = (1L << 12);
const ulong VBa = (1L << 13);
const ulong VB = (1L << 14);
const ulong DIV1 = (1L << 15);
const ulong P1 = (1L << 16);
const ulong P2 = (1L << 17);
const ulong VL9 = (1L << 18);
const ulong VV1 = (1L << 19);
const ulong VV2 = (1L << 20);
const ulong VZ6 = (1L << 21);
const ulong VV3 = (1L << 22);
const ulong Gate = (1L << 23);
const ulong EmptyValve1 = VB | VBa;
const ulong EmptyValve2 = 0x0000FFFFFFFFFFFF;
const ulong Path1 = VI1;
const ulong Path2 = VI2;
const ulong Path3 = VI3;
const ulong Path4 = 0;
const ulong Path5 = 0;
#elif TORINO_50
const ulong nic1 = (1L << 0);
const ulong nic2 = (1L << 1);
const ulong VL11 = (1L << 2);
const ulong VL13 = (1L << 3);
const ulong VL18 = (1L << 4);
const ulong VZ13 = (1L << 5);
const ulong VL15 = (1L << 6);
const ulong VZ10 = (1L << 7);
const ulong VZ6 = (1L << 8);
const ulong VV1 = (1L << 9);
const ulong VV4 = (1L << 10);
const ulong VL12 = (1L << 11);
const ulong VI1 = (1L << 12);
const ulong VI2 = (1L << 13);
const ulong VI3 = (1L << 14);
const ulong VI4 = (1L << 15);
const ulong VB1 = (1L << 16);
const ulong VB1a = (1L << 17);
const ulong VB2 = (1L << 18);
const ulong VB2a = (1L << 19);
const ulong DIV1 = (1L << 20);
const ulong DIV2 = (1L << 21);
const ulong P1 = (1L << 22);
const ulong P3 = (1L << 23);
const ulong P2 = (1L << 24);
const ulong EmptyValve1 = VB1 | VB1a;
const ulong EmptyValve2 = VB2 | VB2a;
const ulong Path1 = VI1;
const ulong Path2 = VI2;
const ulong Path3 = VI3;
const ulong Path4 = VI4;
const ulong Path5 = 0;
#elif TORUN_50 || TURA_IPERL || TURA_IPERL_NEW
const ulong VL11 = (1L << 0);
const ulong VL13 = (1L << 1);
const ulong VL15 = (1L << 2);
const ulong VL21 = (1L << 3);
const ulong VL23 = (1L << 4);
const ulong VL18 = (1L << 5);
const ulong VL28 = (1L << 6);
const ulong VZ5 = (1L << 7);
const ulong VZ6 = (1L << 8);
const ulong DIV1 = (1L << 9);
const ulong DIV2 = (1L << 10);
const ulong P1 = (1L << 11);
const ulong P2 = (1L << 12);
const ulong P3 = (1L << 13);
const ulong DIV3 = (1L << 14);
const ulong rez1 = (1L << 15);
const ulong nic1 = (1L << 16);
const ulong nic2 = (1L << 17);
const ulong VI1 = (1L << 18);
const ulong VI2 = (1L << 19);
const ulong VI3 = (1L << 20);
const ulong VI4 = (1L << 21);
const ulong VI5 = (1L << 22);
const ulong VB1 = (1L << 23);
const ulong VV12 = (1L << 24);
const ulong VV22 = (1L << 25);
const ulong VI6 = (1L << 26);
const ulong VV3 = (1L << 27);
const ulong VB2 = (1L << 28);
const ulong EmptyValve1 = VB1;
const ulong EmptyValve2 = VB2;
const ulong Path1 = VI1;
const ulong Path2 = VI2;
const ulong Path3 = VI3;
const ulong Path4 = VI4;
const ulong Path5 = VI5;
const ulong Path6 = VI6;
#elif TURA_SPECIAL
const ulong VL11 = (1L << 0);
const ulong VL13 = (1L << 1);
const ulong VL15 = (1L << 2);
const ulong VL21 = (1L << 3);
const ulong VL23 = (1L << 4);
const ulong VL18 = (1L << 5);
const ulong VL28 = (1L << 6);
const ulong VZ5 = (1L << 7);
const ulong VZ6 = (1L << 8);
const ulong DIV1 = (1L << 9);
const ulong DIV2 = (1L << 10);
const ulong P1 = (1L << 11);
const ulong P2 = (1L << 12);
const ulong P3 = (1L << 13);
const ulong DIV3 = (1L << 14);
const ulong rez1 = (1L << 15);
const ulong nic1 = (1L << 16);
const ulong nic2 = (1L << 17);
const ulong VI1 = (1L << 18);
const ulong VI2 = (1L << 19);
const ulong VI3 = (1L << 20);
const ulong VI4 = (1L << 21);
const ulong VI5 = (1L << 22);
const ulong VB1 = (1L << 23);
const ulong VV12 = (1L << 24);
const ulong VV22 = (1L << 25);
const ulong VI6 = (1L << 26);
const ulong VV3 = (1L << 27);
const ulong VB2 = (1L << 28);
const ulong EmptyValve1 = VB1;
const ulong EmptyValve2 = VB2;
const ulong Path1 = VI1;
const ulong Path2 = VI2;
const ulong Path3 = VI3;
const ulong Path4 = VI4;
const ulong Path5 = VI5;
const ulong Path6 = VI6;
#else
/// Paths modulating the flows
const ulong V1 = (1L << 1);
const ulong V2 = (1L << 2);
const ulong V3 = (1L << 3);
const ulong V3b = (1L << 4);
const ulong V4 = (1L << 5);
const ulong V4b = (1L << 6);
const ulong V5 = (1L << 7);
const ulong V5b = (1L << 8);
const ulong EmptyValve1 = (1L << 9); // =Ve1
const ulong EmptyValve2 = (1L << 10); // =Ve2
const ulong Path1 = V1 | V3 | V3b | V4 | V4b;
const ulong Path2 = V2 | V3 | V3b | V5 | V5b;
const ulong Path3 = 0;
const ulong Path4 = 0;
const ulong Path5 = 0;
#endif
/// <summary>Run this device</summary>
public static void RunDevice(int regulValveNo, int refFlowmtrNo, StatusP statusP)
{
TestBenchSim.regulValveNo = regulValveNo;
TestBenchSim.refFlowmtrNo = refFlowmtrNo;
double time = 1.0;
#if DN100
if (Div1sim && (SimRoute & Path1) == Path1) Mass1sim += DiffKg(Flow1sim, time);
if (Div1sim && (SimRoute & Path2) == Path2) Mass1sim += DiffKg(Flow2sim, time);
if (Div2sim && (SimRoute & Path3) == Path3) Mass2sim += DiffKg(Flow3sim, time);
if (Div2sim && (SimRoute & Path4) == Path4) Mass2sim += DiffKg(Flow4sim, time);
if (Div1sim && (SimRoute & Path5) == Path5) Mass1sim += DiffKg(Flow5sim, time);
#elif MUNICH || FUZHOU_150 || FUZHOU_300 || IZRAEL_200 || PUCHONG_200 || GENESIS || BERLIN || GELSENWASSER
if (Div1sim && (SimRoute & Path1) == Path1)
{
double diff = DiffKg(Flow1sim, time);
Mass1sim += diff;
log.WarnFormat("Path1: Div1, Mass1+={0}kg, flow={1}m3/h, Mass1={2}kg", diff, Flow1sim, Mass1sim);
}
if (Div1sim && (SimRoute & Path2) == Path2)
{
double diff = DiffKg(Flow2sim, time);
Mass1sim += diff;
log.WarnFormat("Path2: Div1, Mass1 += {0}kg, flow={1}m3/h, Mass1={2}kg", diff, Flow1sim, Mass1sim);
}
if (Div2sim && (SimRoute & Path3) == Path3)
{
double diff = DiffKg(Flow3sim, time);
Mass2sim += diff;
log.WarnFormat("Path3: Div2, Mass2 += {0}kg, flow={1}m3/h, Mass2={2}kg", diff, Flow1sim, Mass2sim);
}
if (Div3sim && (SimRoute & Path4) == Path4)
{
double diff = DiffKg(Flow4sim, time);
Mass2sim += diff;
log.WarnFormat("Path4: Div3, Mass2 += {0}kg, flow={1}m3/h, Mass2={2}kg", diff, Flow1sim, Mass2sim);
}
if (Div3sim && (SimRoute & Path5) == Path5)
{
double diff = DiffKg(Flow5sim, time);
Mass2sim += diff;
log.WarnFormat("Path5: Div3, Mass2 += {0}kg, flow={1}m3/h, Mass2={2}kg", diff, Flow1sim, Mass2sim);
}
#elif BADGER_MALA_TRAT || BADGER_STREDNA_TRAT || BADGER_VELKA_TRAT || TORINO_50 /// Path1,2 do WT1, Path3,4 do WT2
if (Div1sim && (SimRoute & Path1) == Path1) Mass1sim += DiffKg(Flow1sim, time);
if (Div1sim && (SimRoute & Path2) == Path2) Mass1sim += DiffKg(Flow2sim, time);
if (Div2sim && (SimRoute & Path3) == Path3) Mass2sim += DiffKg(Flow3sim, time);
if (Div2sim && (SimRoute & Path4) == Path4) Mass2sim += DiffKg(Flow4sim, time);
#elif CEVAK_40 || MURES_40 || FUZHOU_50 || SLM_50 || MALTA_WSD25 /// Path1,2,3 do WT1
if (Div1sim && (SimRoute & Path1) == Path1) Mass1sim += DiffKg(Flow1sim, time);
if (Div1sim && (SimRoute & Path2) == Path2) Mass1sim += DiffKg(Flow2sim, time);
if (Div1sim && (SimRoute & Path3) == Path3) Mass1sim += DiffKg(Flow3sim, time);
#elif TORUN_50 || TURA_IPERL || TURA_IPERL_NEW /// Path1,2,3,4,5 do WT1, Path6 do WT2
if (Div1sim && (SimRoute & Path1) == Path1) Mass1sim += DiffKg(Flow1sim, time);
if (Div1sim && (SimRoute & Path2) == Path2) Mass1sim += DiffKg(Flow2sim, time);
if (Div1sim && (SimRoute & Path3) == Path3) Mass1sim += DiffKg(Flow3sim, time);
if (Div2sim && (SimRoute & Path4) == Path4) Mass1sim += DiffKg(Flow4sim, time);
if (Div2sim && (SimRoute & Path5) == Path5) Mass1sim += DiffKg(Flow5sim, time);
if (Div3sim && (SimRoute & Path6) == Path6) Mass2sim += DiffKg(Flow4sim, time);
#elif TURA_SPECIAL
if (Div1sim && (SimRoute & Path1) == Path1) Mass1sim += DiffKg(Flow1sim, time);
if (Div1sim && (SimRoute & Path2) == Path2) Mass1sim += DiffKg(Flow2sim, time);
if (Div1sim && (SimRoute & Path3) == Path3) Mass1sim += DiffKg(Flow3sim, time);
if (Div2sim && (SimRoute & Path4) == Path4) Mass1sim += DiffKg(Flow4sim, time);
if (Div2sim && (SimRoute & Path5) == Path5) Mass1sim += DiffKg(Flow5sim, time);
if (Div3sim && (SimRoute & Path6) == Path6) Mass2sim += DiffKg(Flow4sim, time);
#else
if (Div1sim && (SimRoute & Path1) == Path1) Mass1sim += DiffKg(Flow1sim, time);
if (Div2sim && (SimRoute & Path2) == Path2) Mass2sim += DiffKg(Flow2sim, time);
#endif
if ((SimRoute & EmptyValve1) == EmptyValve1) Mass1sim -= DiffKg(100.0, time);
if (Mass1sim < 0) Mass1sim = 0;
if ((SimRoute & EmptyValve2) == EmptyValve2) Mass2sim -= DiffKg(10.0, time);
if (Mass2sim < 0) Mass2sim = 0;
}
/// <summary>
/// Calculate the mass change from the flow and the time period
/// </summary>
/// <param name="flowM3H">Flow in [m3/h]</param>
/// <param name="timeSec">Time period in [s]</param>
/// <returns>Mass change in [kg]</returns>
static double DiffKg(double flowM3H, double timeSec)
{
return timeSec * flowM3H / 3.6;
}
/// <summary>
/// Get the simulated mass. Use the balance range to distinguish the balances.
/// </summary>
/// <param name="balanceNr">0-based balance number</param>
/// <returns>Simulated mass reading [kg]</returns>
public static double GetSimMass(int balanceNr)
{
if (balanceNr == 0) return Mass1sim;
else if (balanceNr == 1) return Mass2sim;
else return 0;
}
/// <summary>
/// Set the simulated diverter. Use the nominal flow to distinguish the path.
/// </summary>
/// <param name="toTank">Diverter state: true = to the tank</param>
/// <param name="nominalFlow">Nominal flow of the path [m3/h]</param>
public static void SetSimDiverter(bool toTank)
{
#if DN100
switch (regulValveNo)
{
case 1:
case 2:
case 5:
Div1sim = toTank;
break;
case 3:
case 4:
Div2sim = toTank;
break;
default:
if (toTank) { throw (new Exception()); }
break;
}
#elif MUNICH || FUZHOU_150 || FUZHOU_300 || IZRAEL_200 || PUCHONG_200 || GENESIS || BERLIN || GELSENWASSER
switch (regulValveNo)
{
case 1:
case 2:
Div1sim = toTank;
break;
case 3:
Div2sim = toTank;
break;
case 4:
case 5:
Div3sim = toTank;
break;
default:
//if (toTank) { throw (new Exception()); }
break;
}
#elif BADGER_MALA_TRAT || BADGER_STREDNA_TRAT || TORINO_50
switch (regulValveNo)
{
case 1:
case 2:
Div1sim = toTank;
break;
case 3:
case 4:
Div2sim = toTank;
break;
default:
if (toTank) { throw (new Exception()); }
break;
}
#elif BADGER_VELKA_TRAT
switch (regulValveNo)
{
case 7:
case 2:
Div1sim = toTank;
break;
case 3:
Div2sim = toTank;
break;
default:
if (toTank) { throw (new Exception()); }
break;
}
#elif CEVAK_40 || MURES_40 || FUZHOU_50 || SLM_50 || MALTA_WSD25
switch (regulValveNo)
{
case 1:
case 2:
case 3:
Div1sim = toTank;
break;
default:
if (toTank) { /* throw (new Exception()); */ }
break;
}
#elif TORUN_50 || TURA_IPERL || TURA_IPERL_NEW
switch (regulValveNo)
{
case 1:
case 2:
case 3:
Div1sim = toTank;
break;
case 4:
case 5:
Div2sim = toTank;
break;
case 6:
Div3sim = toTank;
break;
default:
if (toTank) { throw (new Exception()); }
break;
}
#elif TURA_SPECIAL
switch (regulValveNo)
{
case 1:
case 2:
case 3:
Div1sim = toTank;
break;
case 4:
case 5:
Div2sim = toTank;
break;
case 6:
Div3sim = toTank;
break;
default:
if (toTank) { throw (new Exception()); }
break;
}
#else
switch (regulValveNo)
{
case 1: Div1sim = toTank; break;
case 2: Div2sim = toTank; break;
default:
if (toTank) { throw (new Exception()); }
break;
}
#endif
return;
}
/// <summary>
/// Get the simulated flow in [m3/h].
/// </summary>
/// <returns>Simulated flow [m3/h]</returns>
public static double GetSimFlow()
{
switch (refFlowmtrNo)
{
case 1: return ((SimRoute & Path1) == Path1) ? Flow1sim : 0;
case 2: return ((SimRoute & Path2) == Path2) ? Flow2sim : 0;
case 3: return ((SimRoute & Path3) == Path3) ? Flow3sim : 0;
case 4: return (((SimRoute & Path4) == Path4) ? Flow4sim : 0) +
(((SimRoute & Path5) == Path5) ? Flow5sim : 0);
default: return 0;
}
}
/// <summary>
/// Update simulated flow. Use the nominal flow to distinguish the path.
/// </summary>
/// <param name="targetFlow">Target flow [m3/h]</param>
/// <param name="nominalFlow">Nominal flow of the path [m3/h]</param>
public static void UpdateSimFlow(double targetFlow)
{
double A = 0.7; /// higher value -> slower regulation
double B = 1.0 - A;
switch (regulValveNo)
{
case 1: Flow1sim = A * Flow1sim + B * targetFlow; break;
case 2: Flow2sim = A * Flow2sim + B * targetFlow; break;
case 3: Flow3sim = A * Flow3sim + B * targetFlow; break;
case 4: Flow4sim = A * Flow4sim + B * targetFlow; break;
case 5: Flow5sim = A * Flow5sim + B * targetFlow; break;
case 6: Flow6sim = A * Flow6sim + B * targetFlow; break;
default: break;
}
}
}
}
+1 -1
View File
@@ -439,7 +439,7 @@ namespace TBF.Rig.ControlBoard.Papouch
/// Start a standing start-stop test
/// </summary>
/// <returns>Operation</returns>
public IOperation StandingStartStopTestOp(Test test, double qFrom, double qTo, int pulsesCount)
public IOperation StandingStartStopTestOp(Test test, double qFrom, double qTo, int pulsesCount, bool withDiverter)
{
currentTest = test;
return new Operations.ReturnGivenEventOp(Event.TestInProgress);
@@ -16,9 +16,11 @@ namespace TBF.Rig.ControlBoard.Uni
readonly UniCB uniCB;
readonly TBF.Rig.Uni.RegValve.RegValve regV;
readonly TBF.Rig.Uni.FlowMeter.FlowMeter flowMeter;
readonly TBF.Rig.Uni.Diverter.Diverter diverter;
readonly double qFrom;
readonly double qTo;
readonly int pulsesCount; /// Number of reference pulses for a complete test
readonly int pulsesCount; /// Number of reference pulses for a complete test
readonly bool withDiverter; /// Test with diverter (and scale)
/// <summary>
/// Operation for a Standing start-stop test (constructor)
@@ -34,7 +36,7 @@ namespace TBF.Rig.ControlBoard.Uni
/// <param name="qFrom">Flow lower limit</param>
/// <param name="qTo">Flow upper limit</param>
/// <param name="pulsesCount">Test duration - number of reference flow meter pulses</param>
public StandingStartStopTestOp(UniCB cb, OutputPath devices, double qFrom, double qTo, int pulsesCount)
public StandingStartStopTestOp(UniCB cb, OutputPath devices, double qFrom, double qTo, int pulsesCount, bool withDiverter)
{
this.uniCB = cb;
@@ -47,6 +49,13 @@ namespace TBF.Rig.ControlBoard.Uni
this.qFrom = qFrom;
this.qTo = qTo;
this.pulsesCount = pulsesCount;
this.withDiverter = withDiverter;
if (withDiverter)
{
diverter = devices.Diverter as TBF.Rig.Uni.Diverter.Diverter;
if (diverter == null) throw new ArgumentNullException("Invalid diverter");
}
log.Debug(this.ToString());
}
@@ -69,7 +78,8 @@ namespace TBF.Rig.ControlBoard.Uni
log.InfoFormat("Op.Start() RV#={0} Et#={1} Qfrom={2} Qto={3}", regV.Idx1, flowMeter.Idx1, qFrom, qTo);
/// Start the test (and the flow measurement)
uniCB.StartTest(false, flowMeter.Idx1, 0, 0, false, false, true, false, pulsesCount);
uniCB.StartTest(false, flowMeter.Idx1, (withDiverter ? diverter.DiverterNr : 0), 0,
false, withDiverter, true, false, pulsesCount);
opState = OpState.StartingTest;
}
+2 -2
View File
@@ -559,9 +559,9 @@ namespace TBF.Rig.ControlBoard.Uni
/// Start a standing start-stop test
/// </summary>
/// <returns>Operation running a test</returns>
public IOperation StandingStartStopTestOp(Test test, double qFrom, double qTo, int pulsesCount)
public IOperation StandingStartStopTestOp(Test test, double qFrom, double qTo, int pulsesCount, bool withDiverter)
{
return new StandingStartStopTestOp(this, devices, qFrom, qTo, pulsesCount);
return new StandingStartStopTestOp(this, devices, qFrom, qTo, pulsesCount, withDiverter);
}
/// <summary>