diff --git a/TestBenchFramework/BenchControl/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs b/TestBenchFramework/BenchControl/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs
index 8099b2cc5..dd827340c 100644
--- a/TestBenchFramework/BenchControl/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs
+++ b/TestBenchFramework/BenchControl/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs
@@ -1106,6 +1106,62 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
}
+ ///
+ /// Write the calculated 2Hz correction factor to the memory.
+ ///
+ /// Water meter object
+ /// String passed to caller
+ /// true on success
+ static CommErr Write2HzCorrection(WaterMeters.iPerl.WaterMeter wm, ref string resultStr)
+ {
+ if (wm.CommFailed) return CommErr.CommFailed;
+
+ /// Write Q2 corrections
+ double hz2CorrectionFactor = wm.Hz2CorrectionFactor();
+ if (hz2CorrectionFactor == 0)
+ {
+ resultStr = string.Format("2Hz factors = 0 (writing bypassed)");
+ return CommErr.None;
+ }
+
+ if (OpenPort(wm) != 0) return CommErr.OpenPort; /// Open RFID port
+
+ CommErr error = CommErr.Write;
+
+ Byte hz2CorrectionByte = (byte)((int)Math.Round(hz2CorrectionFactor) & 0x000000FF);
+ byte[] wrData = new byte[1] { hz2CorrectionByte };
+ ///
+ for (int j = 0; j < cfg.MaxCommRetries; j++)
+ {
+ if (0 == WriteRequestPort(wm, MessageID.MetrologyMemory, Hz2CorrFactorsAddr, 1, wrData, cfg.CommTimeout)) { error = CommErr.None; break; }
+ }
+
+ if (error == CommErr.None)
+ {
+ error = CommErr.Verify;
+
+ /// Read calibration
+ byte[] rdData = null;
+ for (int j = 0; j < cfg.MaxCommRetries; j++)
+ {
+ if ((0 == ReadRequestPort(wm, MessageID.MetrologyMemory, Hz2CorrFactorsAddr, 1, out rdData, cfg.CommTimeout)) &&
+ (rdData != null) && (rdData.Length == 2) && (rdData[0] == hz2CorrectionByte))
+ {
+ error = CommErr.None;
+ resultStr = string.Format("2Hz factor = {0}", (SByte)hz2CorrectionByte);
+ rfidDataLogger.Warn(wm.Name + ": " + resultStr);
+ wm.Current2HzCorrection = hz2CorrectionFactor;
+ break;
+ }
+ }
+ }
+
+ ClosePort(wm); /// Close RFID port
+
+ return error;
+ }
+
+
///
/// Called when communication with one watermeter is completed
///
diff --git a/TestBenchFramework/BenchControl/WaterMeters/iPerl/WaterMeter.cs b/TestBenchFramework/BenchControl/WaterMeters/iPerl/WaterMeter.cs
index ebafcdcc5..51d0b39ee 100644
--- a/TestBenchFramework/BenchControl/WaterMeters/iPerl/WaterMeter.cs
+++ b/TestBenchFramework/BenchControl/WaterMeters/iPerl/WaterMeter.cs
@@ -113,8 +113,9 @@ namespace TBF.BenchControl.WaterMeters.iPerl
public double Q2ErrorWOCorrection;
public bool Q2CorrectionDone;
- public double CurrentQ2Correction;
+ public double CurrentQ2Correction;
+ public double Current2HzCorrection;
/// Result of the last test used to calculate Q2 correction factors, etc
public Results.Entities.MeterTestRslt LastTestResult;
@@ -219,6 +220,55 @@ namespace TBF.BenchControl.WaterMeters.iPerl
return corrFactor;
}
+
+ ///
+ /// 2 Hz correction factor calculated from two Q3 tests - done at 2Hz and at 8Hz.
+ /// This factors should be used only for DN32 and DN40 meters.
+ ///
+ /// 2 Hz correction factor
+ public double Hz2CorrectionFactor()
+ {
+ Q2ErrorWOCorrection = LastTestResult.Error;
+
+ if (Math.Abs(LastTestResult.Error) <= 0.5)
+ {
+ Q2CorrectionDone = false;
+ return 0; /// No Q2 correction if error < +/-0.5 %
+ }
+
+ double A = 16.0 / ScalingFactor(); /// Raw units per ml: DN15=16, DN20=8, DN25=4, DN32=2, DN40=1
+ const double B = 8.0; /// Raw units per minute, 8
+ const double C = B * 60.0; /// Raw units per hour, 480
+ double D = C / A; /// ml correction per hour
+ double F = D / (NominalTestFlow * 10.0); /// Error corrected with 8 Raw Units per minute [%]
+ double G = F / B; /// Error corrected with 1 Raw Unit per minute [%]
+
+ double errLimitLo = LastTestResult.ErrLimLo() + LastTestResult.Uncertainty();
+ double errLimitHi = LastTestResult.ErrLimHi() - LastTestResult.Uncertainty();
+
+ if (LastTestResult.Error < errLimitLo) return 0; /// No Q2 correction if error too large -> WM failed
+ if (LastTestResult.Error > errLimitHi) return 0; /// No Q2 correction if error too large -> WM failed
+
+ double volumeMeterErrLimLo = LastTestResult.VolumeRef * (100.0 + errLimitLo) / 100.0;
+ double volumeMeterErrLimHi = LastTestResult.VolumeRef * (100.0 + errLimitHi) / 100.0;
+
+ double corrFactorHi = (-1) * (errLimitLo / G) * (LastTestResult.VolumeRef / volumeMeterErrLimLo); /// > 0
+ double corrFactorLo = (-1) * (errLimitHi / G) * (LastTestResult.VolumeRef / volumeMeterErrLimHi); /// < 0
+
+ double corrFactor = (-1) * (LastTestResult.Error / G) * (LastTestResult.VolumeRef / LastTestResult.VolumeMeter);
+ double origCalulatedCorrFactor = corrFactor;
+
+ log.WarnFormat("Q2 correction: {0}, corrFactor={4}, error={3}% [Lo={1}%, Hi={2}%]",
+ Name,
+ errLimitLo.ToString("F1"),
+ errLimitHi.ToString("F1"),
+ LastTestResult.Error.ToString("F2"),
+ corrFactor.ToString("F1"));
+
+ Q2CorrectionDone = true;
+ return corrFactor;
+ }
+
/// Name set by the test, to be used as a part of the opto-data log file name
public string TestName;