CombinedWithDetTestParams.OffsetPulsesFreq parameter introduced, use in Qfall detection, ver. 2.18.968

This commit is contained in:
Milan Hanajik 2018-07-17 09:15:43 +02:00
parent 1d8728c7ce
commit 9ba1b58d2e
3 changed files with 137 additions and 116 deletions

View File

@ -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()

View File

@ -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)

View File

@ -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")]