From 9ba1b58d2e5e736790694ecb1f2ac9ecc2caec2d Mon Sep 17 00:00:00 2001 From: Milan Hanajik Date: Tue, 17 Jul 2018 09:15:43 +0200 Subject: [PATCH] CombinedWithDetTestParams.OffsetPulsesFreq parameter introduced, use in Qfall detection, ver. 2.18.968 --- .../CombinedWithDetTestParams.cs | 33 +-- .../CombinedWithDetectionSeq.cs | 216 ++++++++++-------- TBF/Properties/AssemblyInfo.cs | 4 +- 3 files changed, 137 insertions(+), 116 deletions(-) diff --git a/TBF/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetTestParams.cs b/TBF/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetTestParams.cs index 6fb9865c8..6640806fd 100644 --- a/TBF/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetTestParams.cs +++ b/TBF/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetTestParams.cs @@ -1,5 +1,5 @@ /// -/// Copyright (c) 2013-2015 Sensus Metering Systems +/// Copyright (c) 2013-2018 Sensus Slovensko a.s. /// using System; using System.IO; @@ -21,7 +21,8 @@ namespace TBF.BenchControl.TestMethods.CombinedWithDetection public float RelativeQto; /// Tested flow high range related to the detected flow public float RateOfChange; /// Each step is calculated as (TargetQfrom - Qfrom) * RateOfChange, text form is displayed in % (*100) public float DetectionThreshold; /// Drop of frequency for the detection, text form is displayed in % (*100) - public bool SupressTrills; /// Main meter readings are ignored during test (suitable for small flows) + public float OffsetPulsesFreq; /// Offset frequency of pulses of the small WM for the detection in Hz + public bool SupressTrills; /// Main meter readings are ignored during test (suitable for small flows) public override void InitializeAll() { @@ -30,6 +31,7 @@ namespace TBF.BenchControl.TestMethods.CombinedWithDetection RelativeQto = -0.2f; RateOfChange = 0.05f; DetectionThreshold = 0.25f; + OffsetPulsesFreq = 1.0f; SupressTrills = false; } @@ -41,6 +43,7 @@ namespace TBF.BenchControl.TestMethods.CombinedWithDetection Strings.RelativeQto, Strings.RateOfChangePct, Strings.DetectionThresholdPct, + "Offset pulses freq.", Strings.SupressWMTrills, }; public override string ParamName(int i) { return paramNames[i]; } @@ -55,7 +58,8 @@ namespace TBF.BenchControl.TestMethods.CombinedWithDetection case 2: return RelativeQto.ToString(); case 3: return (100.0f * RateOfChange).ToString(); case 4: return (100.0f * DetectionThreshold).ToString(); - case 5: return (SupressTrills ? Strings.yes : Strings.no); + case 5: return OffsetPulsesFreq.ToString(); + case 6: return (SupressTrills ? Strings.yes : Strings.no); default: return string.Empty; } } @@ -64,13 +68,14 @@ namespace TBF.BenchControl.TestMethods.CombinedWithDetection { switch (i) { - case 0: TargetQ = Utils.ParseUFloat(strValue); return CfgUpdateFlags.None; - case 1: RelativeQfrom = Utils.ParseSFloat(strValue); return CfgUpdateFlags.None; - case 2: RelativeQto = Utils.ParseSFloat(strValue); return CfgUpdateFlags.None; - case 3: RateOfChange = Utils.ParseUFloat(strValue) / 100.0f; return CfgUpdateFlags.None; - case 4: DetectionThreshold = Utils.ParseUFloat(strValue) / 100.0f; return CfgUpdateFlags.None; - case 5: SupressTrills = strValue.Equals(Strings.yes); return CfgUpdateFlags.None; - default: return CfgUpdateFlags.None; + case 0: TargetQ = Utils.ParseUFloat(strValue); return CfgUpdateFlags.None; + case 1: RelativeQfrom = Utils.ParseSFloat(strValue); return CfgUpdateFlags.None; + case 2: RelativeQto = Utils.ParseSFloat(strValue); return CfgUpdateFlags.None; + case 3: RateOfChange = Utils.ParseUFloat(strValue) / 100.0f; return CfgUpdateFlags.None; + case 4: DetectionThreshold = Utils.ParseUFloat(strValue) / 100.0f; return CfgUpdateFlags.None; + case 5: OffsetPulsesFreq = Utils.ParseUFloat(strValue); return CfgUpdateFlags.None; + case 6: SupressTrills = strValue.Equals(Strings.yes); return CfgUpdateFlags.None; + default: return CfgUpdateFlags.None; } } @@ -84,13 +89,14 @@ namespace TBF.BenchControl.TestMethods.CombinedWithDetection case 0: case 3: case 4: - if (Utils.TryParseUFloat(strValue, out dummy)) return true; + case 5: + if (Utils.TryParseUFloat(strValue, out dummy)) return true; break; case 1: case 2: if (Utils.TryParseSFloat(strValue, out dummy)) return true; break; - case 5: + case 6: if (strValue.Equals(Strings.yes) || strValue.Equals(Strings.no)) return true; break; default: @@ -109,7 +115,8 @@ namespace TBF.BenchControl.TestMethods.CombinedWithDetection prms.RelativeQto = this.RelativeQto; prms.RateOfChange = this.RateOfChange; prms.DetectionThreshold = this.DetectionThreshold; - prms.SupressTrills = this.SupressTrills; + prms.OffsetPulsesFreq = this.OffsetPulsesFreq; + prms.SupressTrills = this.SupressTrills; } public IParamsProvider Clone() diff --git a/TBF/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetectionSeq.cs b/TBF/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetectionSeq.cs index 5cdf4e7eb..1dac53c27 100644 --- a/TBF/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetectionSeq.cs +++ b/TBF/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetectionSeq.cs @@ -91,7 +91,7 @@ namespace TBF.BenchControl.TestMethods.CombinedWithDetection int[] lastWMPulses = new int[2 * Config.Data.CompoundWMsCount]; //-------------------------------- - State.Create(string.Format("{0}({1}) : stopTest diverter gate etc", test.Method, test.Name)) + State.Create(string.Format("{0}({1}) : Stop diverter gate etc", test.Method, test.Name)) .AddOperation(checkUiOp) .AddOperation(cBrd.StopPreviousOp()) .EnterState(); @@ -131,9 +131,9 @@ namespace TBF.BenchControl.TestMethods.CombinedWithDetection goto stopTest; } } - + processDataLoggingOp = new TBF.BenchControl.Operations.ProcessDataLoggingOp(processDataLogger, this, false); - + /// Meters path is required for the following: readRegistersOp = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders); @@ -170,7 +170,7 @@ namespace TBF.BenchControl.TestMethods.CombinedWithDetection } } - // Empty the water tank + /// Empty the water tank switch (DrainTheTank(outPath.Scale.DrainValve, outPath.Scale)) { case Event.Error: goto error; @@ -218,7 +218,6 @@ namespace TBF.BenchControl.TestMethods.CombinedWithDetection foreach (var camera in cameras) measureOperations.Add(camera.MeasurementOp()); - //------------------------------------------------ Bridge.OnActivity(this, Strings.Switching_flow_detection); //------------------------------------------------ @@ -237,7 +236,7 @@ namespace TBF.BenchControl.TestMethods.CombinedWithDetection } while (!e.Contains(Event.ValvesSet)); - //-------------------------------- + State.Create(string.Format("{0}({1}) : Set the initial flow", test.Method, test.Name)) .AddOperation(checkUiOp) .AddOperations(measureOperations) @@ -257,7 +256,7 @@ namespace TBF.BenchControl.TestMethods.CombinedWithDetection } while (!e.Contains(Event.FlowReached)); - //-------------------------------- + switch (ReadRegistersTempPressAmbient(measureOperations, false)) { case Event.Error: goto error; @@ -269,7 +268,7 @@ namespace TBF.BenchControl.TestMethods.CombinedWithDetection //==================================== /// Allocate detection buffers - double[] flowsForDetection = new double[DetectionBufferSize]; + double[] flowsForDetection = new double[DetectionBufferSize]; /// in [m3/h] double[] pulseFreqsForDetection = new double[DetectionBufferSize]; /// Current values @@ -279,9 +278,9 @@ namespace TBF.BenchControl.TestMethods.CombinedWithDetection int lastTime = StateMachine.Time; /// Detection parameters - float rvPulse = (testParams.TargetQ > (test.Qfrom + test.Qto) / 2.0f) ? 0.05f : -0.05f; // rise or fall? + float rvPulse = (testParams.TargetQ > (test.Qfrom + test.Qto) / 2.0f) ? 0.05f : -0.05f; /// rise(+) or fall(-) rvPulse *= (100.0f * testParams.RateOfChange); - + bool detected = false; bool targetReached = false; double detectedFlow = 0; @@ -290,109 +289,124 @@ namespace TBF.BenchControl.TestMethods.CombinedWithDetection Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Config.Entities.Progress.SwitchingFlowDetection)); do - { - //-------------------------------- + { State.Create(string.Format("{0}({1}) : Change the RV position", test.Method, test.Name)) - .AddOperation(checkUiOp) - .AddOperations(measureOperations) - .AddOperation(outPath.RegulValve.ChangeRegulValvePositionOp(rvPulse)) - .EnterState(); - do - { - e = StateMachine.WaitRunDevsRunOps(); - Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Config.Entities.Progress.SwitchingFlowDetection)); + .AddOperation(checkUiOp) + .AddOperations(measureOperations) + .AddOperation(outPath.RegulValve.ChangeRegulValvePositionOp(rvPulse)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Config.Entities.Progress.SwitchingFlowDetection)); - if (TestAndLogUiCmdStop(test,e)) goto stopTest; - } + if (TestAndLogUiCmdStop(test, e)) goto stopTest; + } while (!e.Contains(Event.PositionReached)); - // Last pulses are kept to calculate differences - for (int i = 0; i < 2 * Config.Data.CompoundWMsCount; i++) lastWMPulses[i] = RegisterReaders[i].WMPulses; - - // Shift data in the detection buffers - for (int i = DetectionBufferSize - 2; i >= 0; i--) { - flowsForDetection[i+1] = flowsForDetection[i]; - pulseFreqsForDetection[i+1] = pulseFreqsForDetection[i]; + /// + /// Update FIFO buffers for the reference flow and the frequency of pulses + /// + + /// Last pulses are kept to calculate differences + for (int i = 0; i < 2 * Config.Data.CompoundWMsCount; i++) lastWMPulses[i] = RegisterReaders[i].WMPulses; + + /// Shift data in the detection buffers + for (int i = DetectionBufferSize - 2; i >= 0; i--) + { + flowsForDetection[i + 1] = flowsForDetection[i]; + pulseFreqsForDetection[i + 1] = pulseFreqsForDetection[i]; + } + + switch (ReadRegistersTempPressAmbient(measureOperations, false)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stopTest; + } + + int diff = RegisterReaders[(test.Part - 1) * 2 + 1].WMPulses - lastWMPulses[(test.Part - 1) * 2 + 1]; + flowsForDetection[0] = cBrd.ReferenceFreq * outPath.FlowMeter.NominalFlow / 2000.0; + pulseFreqsForDetection[0] = (double)diff / (double)(StateMachine.Time - lastTime); + lastTime = StateMachine.Time; } - switch (ReadRegistersTempPressAmbient(measureOperations, false)) - { - case Event.Error: goto error; - case Event.UiCmdStop: goto stopTest; - } + if ((StateMachine.Time - detectionStartTime > 15) && (flowsForDetection[0] > 0) && (flowsForDetection[DetectionBufferSize - 1] > 0)) + { + /// + /// Evaluate ref. flow and WM pulses frequency data in FIFO buffers. + /// Updpate 'detected' and 'targetReached' flags. + /// + double[] flowBefore = new double[DetectionKernelSize]; + double[] flowAfter = new double[DetectionKernelSize]; + double[] freqBefore = new double[DetectionKernelSize]; + double[] freqAfter = new double[DetectionKernelSize]; + for (int i = 0; i < DetectionKernelSize; i++) + { + flowBefore[i] = flowsForDetection[DetectionBufferSize - DetectionKernelSize + i]; /// The oldest DetectionKernelSize samples + freqBefore[i] = pulseFreqsForDetection[DetectionBufferSize - DetectionKernelSize + i]; - int time = StateMachine.Time; - int diff = RegisterReaders[(test.Part - 1) * 2 + 1].WMPulses - lastWMPulses[(test.Part - 1) * 2 + 1]; - flowsForDetection[0] = cBrd.ReferenceFreq * outPath.FlowMeter.NominalFlow / 2000.0f; - pulseFreqsForDetection[0] = (float)diff / (float)(time - lastTime); - lastTime = StateMachine.Time; + flowAfter[i] = flowsForDetection[i]; /// The newest DetectionKernelSize samples + freqAfter[i] = pulseFreqsForDetection[i]; + } - if (StateMachine.Time - detectionStartTime > 15) - { - if ((flowsForDetection[0] > 0) && (flowsForDetection[DetectionBufferSize - 1] > 0)) - { - double[] flowBefore = new double[DetectionKernelSize]; - double[] flowAfter = new double[DetectionKernelSize]; - double[] freqBefore = new double[DetectionKernelSize]; - double[] freqAfter = new double[DetectionKernelSize]; - for (int i = 0; i < DetectionKernelSize; i++) - { - flowBefore[i] = flowsForDetection[DetectionBufferSize - DetectionKernelSize + i]; - freqBefore[i] = pulseFreqsForDetection[DetectionBufferSize - DetectionKernelSize + i]; - flowAfter[i] = flowsForDetection[i]; - freqAfter[i] = pulseFreqsForDetection[i]; - } - Array.Sort(flowBefore); - Array.Sort(flowAfter); - Array.Sort(freqBefore); - Array.Sort(freqAfter); - flowBefore[0] = 0; - flowAfter[0] = 0; - //freqBefore[0] = 0; - //freqAfter[0] = 0; - flowBefore[DetectionKernelSize - 1] = 0; - flowAfter[DetectionKernelSize - 1] = 0; - //freqBefore[DetectionKernelSize - 1] = 0; - //freqAfter[DetectionKernelSize - 1] = 0; - double aveFlowBefore = 0; - double aveFlowAfter = 0; - double aveFreqBefore = 0; - double aveFreqAfter = 0; - foreach (var f in flowBefore) aveFlowBefore += f; - foreach (var f in flowAfter) aveFlowAfter += f; - foreach (var f in freqBefore) aveFreqBefore += f; - foreach (var f in freqAfter) aveFreqAfter += f; - aveFlowBefore /= (double)(DetectionKernelSize - 2); - aveFlowAfter /= (double)(DetectionKernelSize - 2); - aveFreqBefore /= (double)(DetectionKernelSize); - aveFreqAfter /= (double)(DetectionKernelSize); + /// Skip the smallest and the largest flow + Array.Sort(flowBefore); + Array.Sort(flowAfter); + flowBefore[0] = 0; + flowAfter[0] = 0; + flowBefore[DetectionKernelSize - 1] = 0; + flowAfter[DetectionKernelSize - 1] = 0; + /// + double aveFlowBefore = 0; + double aveFlowAfter = 0; + foreach (var f in flowBefore) aveFlowBefore += f; + foreach (var f in flowAfter) aveFlowAfter += f; + aveFlowBefore /= (double)(DetectionKernelSize - 2); + aveFlowAfter /= (double)(DetectionKernelSize - 2); - UiBridge.Bridge.OnLog(this, string.Format("time={0}, flow{1}, aveFlowB={2}, aveFlowA={3}, pulseFreq={4}, aveFreqB={5}, aveFreqA={6}\r\n", - time - startTime, - flowsForDetection[0].ToString("F2"), - aveFlowBefore.ToString("F2"), - aveFlowAfter.ToString("F2"), - pulseFreqsForDetection[0].ToString("F2"), - aveFreqBefore.ToString("F2"), - aveFreqAfter.ToString("F2"))); + /// Do NOT skip the smallest and the largest flow + //Array.Sort(freqBefore); + //Array.Sort(freqAfter); + //freqBefore[0] = 0; + //freqAfter[0] = 0; + //freqBefore[DetectionKernelSize - 1] = 0; + //freqAfter[DetectionKernelSize - 1] = 0; + /// + double aveFreqBefore = 0; + double aveFreqAfter = 0; + foreach (var f in freqBefore) aveFreqBefore += f; + foreach (var f in freqAfter) aveFreqAfter += f; + aveFreqBefore /= (double)DetectionKernelSize; + aveFreqAfter /= (double)DetectionKernelSize; - //detectedFlow = (aveFlowBefore + aveFlowAfter) / 2.0f; - detectedFlow = aveFlowBefore; + UiBridge.Bridge.OnLog(this, string.Format("time={0}, flow{1}, aveFlowB={2}, aveFlowA={3}, pulseFreq={4}, aveFreqB={5}, aveFreqA={6}\r\n", + StateMachine.Time - startTime, + flowsForDetection[0].ToString("F2"), + aveFlowBefore.ToString("F2"), + aveFlowAfter.ToString("F2"), + pulseFreqsForDetection[0].ToString("F2"), + aveFreqBefore.ToString("F2"), + aveFreqAfter.ToString("F2"))); - if (rvPulse > 0) - { - detected = (aveFreqAfter < aveFreqBefore * (1.0f - testParams.DetectionThreshold)); - targetReached = ((aveFlowAfter + aveFlowBefore) / 2.0f) > testParams.TargetQ; - } - else - { - detected = (aveFreqAfter > aveFreqBefore * (1.0f + testParams.DetectionThreshold)); - targetReached = ((aveFlowAfter + aveFlowBefore) / 2.0f) < testParams.TargetQ; - } - } - } - } + //detectedFlow = (aveFlowBefore + aveFlowAfter) / 2.0f; + detectedFlow = aveFlowBefore; + + if (rvPulse > 0) + { + /// rise + detected = (aveFreqAfter < aveFreqBefore * (1.0f - testParams.DetectionThreshold)); + targetReached = ((aveFlowAfter + aveFlowBefore) / 2.0f) > testParams.TargetQ; + } + else + { + /// fall + detected = (aveFreqAfter > (aveFreqBefore + testParams.OffsetPulsesFreq) * (1.0f + testParams.DetectionThreshold)); + targetReached = ((aveFlowAfter + aveFlowBefore) / 2.0f) < testParams.TargetQ; + } + } + + } while (!detected && !targetReached); if (rvPulse > 0) diff --git a/TBF/Properties/AssemblyInfo.cs b/TBF/Properties/AssemblyInfo.cs index 0f8055e1a..2d3f001e3 100644 --- a/TBF/Properties/AssemblyInfo.cs +++ b/TBF/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("2.18.967.0")] -[assembly: AssemblyFileVersion("2.18.967.0")] +[assembly: AssemblyVersion("2.18.968.0")] +[assembly: AssemblyFileVersion("2.18.968.0")]