From fdb1e112dc359b7e17123cb60665a4912b089dd5 Mon Sep 17 00:00:00 2001 From: Milan Hanajik Date: Mon, 26 Apr 2021 08:48:52 +0200 Subject: [PATCH] (1) Dummy.Flowmeter displays flow measured by a scale, (2) OoR values are orange. --- SchematicDrawing/SchematicDrawingCtrl.cs | 20 +++- TBF/Rig/Dummy/FlowMeter/FlowMeter.cs | 22 +++-- TBF/Rig/Dummy/FlowMeter/FlowMeterCfg.cs | 21 ++++- TBF/Rig/Dummy/FlowMeter/ReadFlowOp.cs | 9 +- TBF/Rig/Sequences/ProcessData.cs | 16 +++- TBF/Rig/Sequences/Statistics.cs | 92 ++++++++++++++++--- .../FixedStartMassCollAdvancedSeq.cs | 15 ++- TBF/UI/MainWnd.cs | 4 +- 8 files changed, 161 insertions(+), 38 deletions(-) diff --git a/SchematicDrawing/SchematicDrawingCtrl.cs b/SchematicDrawing/SchematicDrawingCtrl.cs index 5e57ff3e8..2d36bc318 100644 --- a/SchematicDrawing/SchematicDrawingCtrl.cs +++ b/SchematicDrawing/SchematicDrawingCtrl.cs @@ -320,6 +320,8 @@ namespace SchematicDrawing Font measuredValueFont; Brush measuredValueBrush; Brush measuredValueBackColor; + Brush measuredValueOoRBackColor; + Brush measuredValueErrorBackColor; /// Font setpointFont; Brush setpointBrush; @@ -449,6 +451,8 @@ namespace SchematicDrawing measuredValueFont = new Font("Arial", 10, FontStyle.Regular); measuredValueBrush = Brushes.Black; measuredValueBackColor = new SolidBrush(Color.LightGreen); + measuredValueOoRBackColor = new SolidBrush(Color.Orange); + measuredValueErrorBackColor = new SolidBrush(Color.Red); /// Font for drawing setpoints setpointFont = new Font("Arial", 10, FontStyle.Regular); @@ -650,7 +654,6 @@ namespace SchematicDrawing bool msrmntAvailable = msrmntAvailableFlags[msrdValIx]; double msrdVal = Config.Units.ConvertTo(itm.MsrdUnit, measuredValues[msrdValIx]); string altString = altStrings[msrdValIx]; - msrdValIx++; if ((msrmntAvailable || EditMode) && !Utils.IsHidden(item)) { @@ -666,12 +669,21 @@ namespace SchematicDrawing e.Graphics.FillRectangle(brushWater, r.X + 2, r.Y + r.Height - 2 - level, r.Width - 4, level); } - /// Draw text + /// Draw rectangle for a measured value SizeF size = e.Graphics.MeasureString(strVal, measuredValueFont); Rectangle rect = new Rectangle(itm.X + itm.MsrdX, itm.Y + itm.MsrdY, (int)Math.Round(size.Width) + 4, (int)Math.Round(size.Height) + 2); ItemElementRectangles.Add(new ItemElementRect(item, Element.MeasuredVal, rect)); - e.Graphics.FillRectangle(measuredValueBackColor, rect); + if (measuredValues[msrdValIx] >= itm.MsrdValLimLo && measuredValues[msrdValIx] <= itm.MsrdValLimHi) + { + e.Graphics.FillRectangle(measuredValueBackColor, rect); + } + else + { + e.Graphics.FillRectangle(measuredValueOoRBackColor, rect); + } e.Graphics.DrawRectangle(thinBlackPen, rect); + + /// Draw the measured value e.Graphics.DrawString(strVal, measuredValueFont, measuredValueBrush, rect.X + 2, rect.Y + 2); if (EditMode && (item == selectedItem) && (selectedElement == Element.MeasuredVal)) @@ -681,6 +693,8 @@ namespace SchematicDrawing } } } + + msrdValIx++; } } } diff --git a/TBF/Rig/Dummy/FlowMeter/FlowMeter.cs b/TBF/Rig/Dummy/FlowMeter/FlowMeter.cs index 22fcaee42..63c6ff418 100644 --- a/TBF/Rig/Dummy/FlowMeter/FlowMeter.cs +++ b/TBF/Rig/Dummy/FlowMeter/FlowMeter.cs @@ -1,15 +1,16 @@ /// -/// Copyright (c) 2017 Sensus Metering Systems +/// Copyright (c) 2017-2021 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; using log4net; using SchematicDrawing; using TBF.Boxes; +using TBF.Rig.Sequences; namespace TBF.Rig.Dummy.FlowMeter { - public class FlowMeter : ComponentBase, GenericDevices.IFlowMeter, IDrawingItCmpnt + public class FlowMeter : ComponentBase, GenericDevices.IFlowMeter, IDrawingItCmpntWithMeasuredVal { private static readonly ILog log = LogManager.GetLogger(typeof(FlowMeter)); public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); } @@ -27,9 +28,16 @@ namespace TBF.Rig.Dummy.FlowMeter public int Idx1 { get { return 1; } } - public bool MsrmntAvailable { get { return true; } } - public double MeasuredVal { get { return 1.234; } } - public string AltString { get { return "dummy"; } } + public bool MsrmntAvailable { get { return ProcessData.Devices != null && ProcessData.Devices.FlowMeter == this && ReadFlow() > 0; } } + public string AltString { get { return string.Empty; } } + public double MeasuredVal + { + get { return (ProcessData.Devices != null && ProcessData.Devices.FlowMeter == this) ? ReadFlow() : 0; } + set { } + } + + public double MsrdValLimLo { get { return flowMeterCfg.MsrdValLimLo; } set { flowMeterCfg.MsrdValLimLo = value; } } + public double MsrdValLimHi { get { return flowMeterCfg.MsrdValLimHi; } set { flowMeterCfg.MsrdValLimHi = value; } } public FlowMeter() { } @@ -44,8 +52,8 @@ namespace TBF.Rig.Dummy.FlowMeter public override void Initialize() { } - public double ReadFlow() { return 1.23; } - public double ReadFrequency() { return 1.23 * 2000.0 / (double)NominalFlow; } + public double ReadFlow() { return ProcessData.FlowFromMassIncrease; } + public double ReadFrequency() { return ProcessData.FlowFromMassIncrease * 2000.0 / (double)NominalFlow; } /// /// Events: FlowDone, Error diff --git a/TBF/Rig/Dummy/FlowMeter/FlowMeterCfg.cs b/TBF/Rig/Dummy/FlowMeter/FlowMeterCfg.cs index b4004b9ea..d4353e5f0 100644 --- a/TBF/Rig/Dummy/FlowMeter/FlowMeterCfg.cs +++ b/TBF/Rig/Dummy/FlowMeter/FlowMeterCfg.cs @@ -1,5 +1,5 @@ /// -/// Copyright (c) 2017 Sensus Metering Systems +/// Copyright (c) 2017-2021 Sensus Slovensko a.s. /// using System.Collections.Generic; using System.Xml.Serialization; @@ -8,7 +8,7 @@ using TBF.Rig.Generic; namespace TBF.Rig.Dummy.FlowMeter { - public class FlowMeterCfg : ComponentCfgBase, IComponentCfg, IDrawingItem + public class FlowMeterCfg : ComponentCfgBase, IComponentCfg, IDrawingItemWithMeasuredVal { public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(FlowMeterCfg) })[0]; public override XmlSerializer GetSerializer() { return Serializer; } @@ -30,8 +30,21 @@ namespace TBF.Rig.Dummy.FlowMeter public int LblY { get; set; } public Orient LblOrient { get; set; } + public int MsrdX { get; set; } + public int MsrdY { get; set; } + public Orient MsrdOrient { get; set; } + public string MsrdFormat { get; set; } + public Config.Unit MsrdUnit { get; set; } + [XmlIgnore] public IList GNodes { get; set; } + [XmlIgnore] + public double MsrdValLimLo { get { return msrdValLimLo; } set { msrdValLimLo = value; } } + [XmlIgnore] + public double MsrdValLimHi { get { return msrdValLimHi; } set { msrdValLimHi = value; } } + + double msrdValLimLo; + double msrdValLimHi; /// Private parameterless constructor invoked by all other (public) constructors FlowMeterCfg() @@ -44,14 +57,14 @@ namespace TBF.Rig.Dummy.FlowMeter { Shape = Shape.FlowM; Sz = Sz.M; + MsrdFormat = "{0:F4}"; + MsrdUnit = Config.Unit.m3ph; Name = name; Factory = factory; NominalFlow = 1.0f; } - - public string ToString(int i) { return string.Format("{0} {1}[{2},{3}] NominalFlow={4}", Name, Shape, X, Y, NominalFlow); diff --git a/TBF/Rig/Dummy/FlowMeter/ReadFlowOp.cs b/TBF/Rig/Dummy/FlowMeter/ReadFlowOp.cs index ac66ddc99..16ca4091d 100644 --- a/TBF/Rig/Dummy/FlowMeter/ReadFlowOp.cs +++ b/TBF/Rig/Dummy/FlowMeter/ReadFlowOp.cs @@ -1,5 +1,5 @@ /// -/// Copyright (c) 2017 Sensus Metering Systems +/// Copyright (c) 2017-2021 Sensus Slovensko a.s. /// using System; using log4net; @@ -41,7 +41,8 @@ namespace TBF.Rig.Dummy.FlowMeter /// Start this operation public void Start() { - } + if (flowBox != null) flowBox.Val = flowMeter.ReadFlow(); + } /// Run this operation /// @@ -54,8 +55,6 @@ namespace TBF.Rig.Dummy.FlowMeter } /// Stop this operation - public void Stop() - { - } + public void Stop() { } } } diff --git a/TBF/Rig/Sequences/ProcessData.cs b/TBF/Rig/Sequences/ProcessData.cs index 0f3891bca..8f48a96cf 100644 --- a/TBF/Rig/Sequences/ProcessData.cs +++ b/TBF/Rig/Sequences/ProcessData.cs @@ -29,6 +29,7 @@ namespace TBF.Rig.Sequences ///------------------------------------------------------------ protected static Rig.BenchPath benchPath; protected static Rig.OutputPath outPath; + public static Rig.OutputPath Devices { get { return outPath; } } public static readonly IList ComponentsWithMeasuredVal; @@ -215,8 +216,10 @@ namespace TBF.Rig.Sequences public static DoubleBox RefFrequency = new DoubleBox() { Name = "RefFreq", Format = "F2" }; public static DoubleBox RefFlow = new DoubleBox() { Name = "RefFlow", Format = "F2" }; /// [m3/h] + public static DoubleBox Mass = new DoubleBox() { Name = "Mass", Format = "F3" }; /// [kg] public static DoubleBox StartMass = new DoubleBox() { Name = "Start Mass", Format = "F3" }; /// [kg] public static DoubleBox EndMass = new DoubleBox() { Name = "End Mass", Format = "F3" }; /// [kg] + public static double FlowFromMassIncrease; public static DateTime TestStartTime; public static DateTime TestEndTime; @@ -240,6 +243,7 @@ namespace TBF.Rig.Sequences RefPulses = 0; RefFrequency.Clear(); RefFlow.Clear(); + Mass.Clear(); StartMass.Clear(); EndMass.Clear(); } @@ -296,6 +300,7 @@ namespace TBF.Rig.Sequences public static Statistics PressDeltaStat = new Statistics(3, 4, true); public static Statistics ConductStat = new Statistics(0, 4, true, new Plotter("Conductivity")); public static Statistics RefFlowStat = new Statistics(5, 7, true, new Plotter("Flow")); + public static Statistics MassStat = new Statistics(0, 7, false, new Plotter("Mass")); public static Statistics TempRefHiStat = new Statistics(); public static Statistics TempRefLoStat = new Statistics(); @@ -327,8 +332,9 @@ namespace TBF.Rig.Sequences PressDeltaStat.Start(batchNr, testName, repetition, skippedSamplesCount); ConductStat.Start (batchNr, testName, repetition, skippedSamplesCount); RefFlowStat.Start (batchNr, testName, repetition, skippedSamplesCount); - - TempRefHiStat.Start (batchNr, testName, repetition); + MassStat.Start (batchNr, testName, repetition, skippedSamplesCount); + + TempRefHiStat.Start(batchNr, testName, repetition); TempRefLoStat.Start (batchNr, testName, repetition); Energy.Start (batchNr, testName, repetition); VolumeForEnergy.Start(batchNr, testName, repetition); @@ -353,6 +359,10 @@ namespace TBF.Rig.Sequences ConductStat.Update(Conductivity); RefFlowStat.Update(RefFlow); + double massIncreasePerSec; + MassStat.Update(Mass, out massIncreasePerSec); + FlowFromMassIncrease = 3600 * massIncreasePerSec / Config.Formulas.DistilledWaterDensityFromTemp(TempDiv.Val); + if (BatchRslts.Batch.HeatMeter) { TempRefHiStat.Update((TempRefHi1.Val + TempRefHi2.Val) / 2); @@ -377,6 +387,8 @@ namespace TBF.Rig.Sequences PressDeltaStat.Stop(); ConductStat.Stop(); RefFlowStat.Stop(); + MassStat.Stop(); + FlowFromMassIncrease = 0; TempRefHiStat.Stop(); TempRefLoStat.Stop(); diff --git a/TBF/Rig/Sequences/Statistics.cs b/TBF/Rig/Sequences/Statistics.cs index b9d00b1b9..6aec03f6b 100644 --- a/TBF/Rig/Sequences/Statistics.cs +++ b/TBF/Rig/Sequences/Statistics.cs @@ -13,7 +13,8 @@ namespace TBF.Rig.Sequences bool recordingInProgress; double[] fifo; double[] sorted; - double first; + double[] timeStamps; + double first; double last; double min; double max; @@ -46,6 +47,7 @@ namespace TBF.Rig.Sequences { fifo = new double[FilterSize]; sorted = new double[FilterSize]; + timeStamps = new double[FilterSize]; } recordingInProgress = false; @@ -117,6 +119,15 @@ namespace TBF.Rig.Sequences Update(box.Val); } + /// + /// Updates statistics + /// + /// New boxed value + public void Update(TBF.Boxes.DoubleBox box, out double increasePerSecond) + { + Update(box.Val, out increasePerSecond); + } + /// /// Updates statistics /// @@ -126,6 +137,15 @@ namespace TBF.Rig.Sequences Update(box.Val); } + /// + /// Updates statistics + /// + /// New boxed value + public void Update(TBF.Boxes.FloatBox box, out double increasePerSecond) + { + Update(box.Val, out increasePerSecond); + } + /// /// All samples are passed to this function /// @@ -136,22 +156,45 @@ namespace TBF.Rig.Sequences { if (totalCount >= skippedSamplesCount) { - Process(value); + double dummy; + Process(value, out dummy, false); } totalCount++; } } + /// + /// All samples are passed to this function + /// + /// New value + public void Update(double value, out double increasePerSecond) + { + increasePerSecond = 0; + + if (recordingInProgress) + { + if (totalCount >= skippedSamplesCount) + { + Process(value, out increasePerSecond, true); + if (FilterSize > 1) + { + + } + } + totalCount++; + } + } + /// /// Only samples after first 'SkippedSamplesCount' samples are passed to this function. /// Any filtering is done inside this function. /// /// New value - void Process(double value) + void Process(double value, out double increasePerSecond, bool calculateIncrease = false) { double filteredValue; - if (ApplyFilter(value, out filteredValue)) + if (ApplyFilter(value, out filteredValue, out increasePerSecond, calculateIncrease)) { sum += filteredValue; if (count == 0) first = filteredValue; @@ -172,31 +215,43 @@ namespace TBF.Rig.Sequences /// Input value /// Output filtered value /// true when 'fileterdValue' is valid - bool ApplyFilter(double value, out double filteredValue) + bool ApplyFilter(double value, out double filteredValue, out double increasePerSecond, bool calculateIncrease = false) { + increasePerSecond = 0; + if (FilterSize == 0) { /// No filter => Pass the input value to the output filteredValue = value; return true; - } - + } /// Shift values in FIFO buffer, calculate the sum - double sum1 = 0; - for (int i = FilterSize - 1; i > 0; i--) + double sumX = 0; + double sumY = 0; + double sumXX = 0; + double sumXY = 0; + for (int i = FilterSize - 1; i > 0; i--) { fifo[i] = fifo[i - 1]; - sum1 += fifo[i]; + timeStamps[i] = timeStamps[i - 1]; + /// + sumX += timeStamps[i]; + sumY += fifo[i]; + sumXX += timeStamps[i] * timeStamps[i]; + sumXY += timeStamps[i] * fifo[i]; } /// Insert the current value into FIFO, add it to the sum fifo[0] = value; - sum1 += value; - + timeStamps[0] = Convert.ToDouble(StateMachine.Time); + /// + sumX += timeStamps[0]; + sumY += fifo[0]; + sumXX += timeStamps[0] * timeStamps[0]; + sumXY += timeStamps[0] * fifo[0]; fifoCount++; - if (fifoCount < FilterSize) { /// FIFO not filled yet => Pass the input value to the output @@ -220,9 +275,18 @@ namespace TBF.Rig.Sequences } else { - filteredValue = sum1 / FilterSize; + filteredValue = sumY / FilterSize; } + if (calculateIncrease) + { + double D = FilterSize * sumXX - sumX * sumX; + if (D != 0) + { + increasePerSecond = (FilterSize * sumXY - sumX * sumY) / D; + } + } + return true; } } diff --git a/TBF/Rig/TestMethods/FixedStartMassCollAdvanced/FixedStartMassCollAdvancedSeq.cs b/TBF/Rig/TestMethods/FixedStartMassCollAdvanced/FixedStartMassCollAdvancedSeq.cs index 489bbb0af..0f6fb510d 100644 --- a/TBF/Rig/TestMethods/FixedStartMassCollAdvanced/FixedStartMassCollAdvancedSeq.cs +++ b/TBF/Rig/TestMethods/FixedStartMassCollAdvanced/FixedStartMassCollAdvancedSeq.cs @@ -1,5 +1,5 @@ /// -/// Copyright (c) 2020 Sensus Slovensko a.s. +/// Copyright (c) 2020-2021 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; @@ -101,6 +101,12 @@ namespace TBF.Rig.TestMethods.FixedStartMassCollAdvanced new List { Event.ConfigurationError }; } } + else if (outPath.FlowMeter is TBF.Rig.Dummy.FlowMeter.FlowMeter) + { + var flowm = outPath.FlowMeter as TBF.Rig.Dummy.FlowMeter.FlowMeter; + flowm.MsrdValLimLo = test.Qfrom; + flowm.MsrdValLimHi = test.Qto; + } IList e; /// Events from currently running operations int tMass1 = 0; @@ -1059,6 +1065,13 @@ namespace TBF.Rig.TestMethods.FixedStartMassCollAdvanced while (!e.Contains(Event.PreviousStopped)); } + if (outPath.FlowMeter is TBF.Rig.Dummy.FlowMeter.FlowMeter) + { + var flowm = outPath.FlowMeter as TBF.Rig.Dummy.FlowMeter.FlowMeter; + flowm.MsrdValLimLo = 0; + flowm.MsrdValLimHi = flowm.NominalFlow; + } + return new List { retVal }; } } diff --git a/TBF/UI/MainWnd.cs b/TBF/UI/MainWnd.cs index 0752218fa..f794a937a 100644 --- a/TBF/UI/MainWnd.cs +++ b/TBF/UI/MainWnd.cs @@ -338,9 +338,9 @@ namespace TBF.UI string[] edgesLcfg = null; string[] edgesXLcfg = null; /// - foreach (var c in cmptnEntities) + foreach (var component in Rig.StateMachine.Components) { - TBF.Rig.Generic.IComponentCfg cmpCfg = TBF.Rig.TbfComponents.CmpntCfgFromCmpntEntity(c); + TBF.Rig.Generic.IComponentCfg cmpCfg = component.Cfg; if (cmpCfg is IDrawingItem) { /// Component is an item to be drawn in the schematic drawing and added to the list box