From 33963ec8cfb5c266f477f65c8adf5e4423e1841b Mon Sep 17 00:00:00 2001 From: Milan Hanajik Date: Wed, 19 Aug 2015 13:04:47 +0200 Subject: [PATCH] Version 1.5.84. Reading registers, scales, temperature, pressure, ... during test done in one state in the sequence. Many changes in TestMethods.iPerlCommunication and WaterMeters.iPerl.WaterMeter. iPerl measurement with opto-data works OK. Logging in State changed, ... --- .../Operations/ReadMoreRegistersOp.cs | 50 +++ .../BenchControl/Sequences/SequenceBase.cs | 16 +- TestBenchFramework/BenchControl/State.cs | 22 +- .../TestMethods/Adjustment/AdjustmentSeq.cs | 5 +- .../CombinedMeters/CombinedMetersSeq.cs | 5 +- .../CombinedWithDetectionSeq.cs | 3 +- .../FixedStartCombinedMetersSeq.cs | 3 +- .../FixedStartMassCollectionSeq.cs | 5 +- .../TestMethods/FlyingStart/FlyingStartSeq.cs | 5 +- .../FlyingStartCollectionMethodSeq.cs | 96 +++-- .../ReferenceFlowmeterCalibrationSeq.cs | 7 +- .../iPerlCommunicationForm.cs | 256 ++++++++----- .../iPerlCommunicationSeq.cs | 7 +- .../BenchControl/WaterMeters/iPerl/Enums.cs | 1 + .../WaterMeters/iPerl/OptoTelegramRaw.cs | 48 ++- .../WaterMeters/iPerl/WaterMeter.cs | 347 ++++++++++++++---- TestBenchFramework/LocalSettings.cs | 4 + TestBenchFramework/Properties/AssemblyInfo.cs | 4 +- 18 files changed, 635 insertions(+), 249 deletions(-) diff --git a/TestBenchFramework/BenchControl/Operations/ReadMoreRegistersOp.cs b/TestBenchFramework/BenchControl/Operations/ReadMoreRegistersOp.cs index dbb933700..bc672816d 100644 --- a/TestBenchFramework/BenchControl/Operations/ReadMoreRegistersOp.cs +++ b/TestBenchFramework/BenchControl/Operations/ReadMoreRegistersOp.cs @@ -17,8 +17,10 @@ namespace TBF.BenchControl.Operations int readersCount; int[] iPulses; int[] iRefPulses; + double[] dTimes; IntBox[] pulses; IntBox[] refPulses; + DoubleBox[] times; IOperation[] readRegOps; /// @@ -90,6 +92,54 @@ namespace TBF.BenchControl.Operations log.Debug(this.ToString()); } + /// + /// Events: eventDone (default=Event.ReadRegisterDone) or Event.Error + /// + /// Register reader reference + /// Reference to the water meter register state in pulses + public ReadMoreRegistersOp(GenericDevices.IRegisterReader[] readers, ref int[] iPulses, ref double[] dTimes, ref int[] iRefPulses) + : this(readers, ref iPulses) + { + if (readers == null) throw new ArgumentNullException("readers"); + + readersCount = readers.Length; + + if (iPulses == null || iPulses.Length != readersCount || + dTimes == null || dTimes.Length != readersCount || + iRefPulses == null || iRefPulses.Length != readersCount) + { + throw new ArgumentException("iPulses or iRefPulses"); + } + this.iPulses = iPulses; + this.dTimes = dTimes; + this.iRefPulses = iRefPulses; + + pulses = new IntBox[Program.WMsCount]; + times = new DoubleBox[Program.WMsCount]; + refPulses = new IntBox[Program.WMsCount]; + + readRegOps = new IOperation[readersCount]; + for (int i = 0; i < readersCount; i++) + { + pulses[i] = new IntBox(iPulses[i]); + times[i] = new DoubleBox(dTimes[i]); + refPulses[i] = new IntBox(iRefPulses[i]); + + if (readers[i] != null) + { + if (readers[i] is WaterMeters.iPerl.WaterMeter) + { + readRegOps[i] = (readers[i] as WaterMeters.iPerl.WaterMeter).ReadRegisterOp(ref pulses[i], ref times[i], ref refPulses[i]); + } + else + { + readRegOps[i] = readers[i].ReadRegisterOp(ref pulses[i], ref refPulses[i]); + } + } + } + log.Debug(this.ToString()); + } + /// Start this operation public void Start() { diff --git a/TestBenchFramework/BenchControl/Sequences/SequenceBase.cs b/TestBenchFramework/BenchControl/Sequences/SequenceBase.cs index 0d3c8e384..730a9f901 100644 --- a/TestBenchFramework/BenchControl/Sequences/SequenceBase.cs +++ b/TestBenchFramework/BenchControl/Sequences/SequenceBase.cs @@ -199,17 +199,16 @@ namespace TBF.BenchControl.Sequences protected float ltrPerRefPulse; - protected IOperation readRegisters1; - protected IOperation readRegisters2; + protected IOperation readRegistersOp; protected IOperation queryEnd1; protected IOperation queryEnd2; protected IOperation checkUiOp; protected IOperation processDataLoggingOp; - protected bool ticTac = false; protected int[] WMPulses = new int[Program.WMsCount]; protected int[] WMRefPulses = new int[Program.WMsCount]; + protected double[] WMTimes = new double[Program.WMsCount]; protected static FloatBox[] WMVolumes; protected static FloatBox[] WMErrors; @@ -720,11 +719,11 @@ namespace TBF.BenchControl.Sequences protected Event ReadRegistersTempPressAmbient(IList measureOperations, bool realTest) { IList e; - ticTac = !ticTac; + State.Create("Read water meters") .AddOperation(checkUiOp) .AddOperations(measureOperations) - .AddOperation(ticTac ? readRegisters1 : readRegisters2) + .AddOperation(readRegistersOp) .AddOperation(benchPath.TempIn.ReadTempOp(ref tempIn)) .AddOperation(benchPath.TempOut.ReadTempOp(ref tempOut)) .AddOperation(outPath.TempDiv.ReadTempOp(ref tempDiv)) @@ -733,9 +732,10 @@ namespace TBF.BenchControl.Sequences .AddOperation(realTest ? outPath.Balance.ReadMassOp(ref mass) : null) .AddOperation(StateMachine.ControlBoard.UpdateTankWeightOp()) .AddOperation((StateMachine.Ambient != null) - ? StateMachine.Ambient.ReadAmbientOp(airTemperature, airPressure, airHumidity) - : null) - .AddOperation(realTest ? (ticTac ? queryEnd1 : queryEnd2) : null) + ? StateMachine.Ambient.ReadAmbientOp(airTemperature, airPressure, airHumidity) + : null) + //.AddOperation(realTest ? (ticTac ? queryEnd1 : queryEnd2) : null) + .AddOperation(realTest ? queryEnd1 : null) .AddOperation(realTest ? processDataLoggingOp : null) .EnterState(); do diff --git a/TestBenchFramework/BenchControl/State.cs b/TestBenchFramework/BenchControl/State.cs index eea20e6c4..446d4fa82 100644 --- a/TestBenchFramework/BenchControl/State.cs +++ b/TestBenchFramework/BenchControl/State.cs @@ -20,10 +20,7 @@ namespace TBF.BenchControl /// Current state (static) - public static State CurrentState - { - get { return currentState; } - } + public static State CurrentState { get { return currentState; } } static State currentState; @@ -35,10 +32,7 @@ namespace TBF.BenchControl /// State with an empty list of operations /// Useful when entering the first state and leaving the last one - public static State Empty - { - get { return new State("empty"); } - } + public static State Empty { get { return new State("empty"); } } /// /// Static constructor that initializes CurrentState @@ -199,13 +193,9 @@ namespace TBF.BenchControl Event evnt = operation.Run(); if (evnt != Event.None) { - log.InfoFormat("Operation {0} returned {1}", operation, evnt); + log.DebugFormat("Operation {0} returned {1}", operation, evnt); events.Add(evnt); } - else - { - log.DebugFormat("Operation {0} returned {1}", operation, evnt); - } } LastEvents = events; @@ -219,7 +209,7 @@ namespace TBF.BenchControl { foreach (IOperation operation in currentState.Operations) { - log.DebugFormat("stopping {0}", operation); + log.InfoFormat("stopping {0}", operation); operation.Stop(); } } @@ -236,7 +226,7 @@ namespace TBF.BenchControl { if (!newState.Operations.Contains(operation)) { - log.DebugFormat("stopping {0}", operation); + log.InfoFormat("stopping {0}", operation); operation.Stop(); } } @@ -248,7 +238,7 @@ namespace TBF.BenchControl { if (!previousState.Operations.Contains(operation)) { - log.DebugFormat("starting {0}", operation); + log.InfoFormat("starting {0}", operation); operation.Start(); } } diff --git a/TestBenchFramework/BenchControl/TestMethods/Adjustment/AdjustmentSeq.cs b/TestBenchFramework/BenchControl/TestMethods/Adjustment/AdjustmentSeq.cs index a4f36aed4..423401fdd 100644 --- a/TestBenchFramework/BenchControl/TestMethods/Adjustment/AdjustmentSeq.cs +++ b/TestBenchFramework/BenchControl/TestMethods/Adjustment/AdjustmentSeq.cs @@ -180,9 +180,8 @@ namespace TBF.BenchControl.TestMethods.Adjustment while (!e.Contains(Event.MeasurementStarted)); /// Measurement loop - preparation - readRegisters1 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); - readRegisters2 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); - queryEnd1 = cBrd.QueryMeasurementEndOp(); + readRegistersOp = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); + queryEnd1 = cBrd.QueryMeasurementEndOp(); queryEnd2 = cBrd.QueryMeasurementEndOp(); bool firstTime = true; /// To reset sums for averaging diff --git a/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/CombinedMetersSeq.cs b/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/CombinedMetersSeq.cs index 343d61877..65f7df1f4 100644 --- a/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/CombinedMetersSeq.cs +++ b/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/CombinedMetersSeq.cs @@ -243,8 +243,7 @@ namespace TBF.BenchControl.TestMethods.CombinedMeters while (!e.Contains(Event.MeasurementStarted)); /// Measurement loop - preparation - readRegisters1 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); - readRegisters2 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); + readRegistersOp = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); queryEnd1 = cBrd.QueryMeasurementEndOp(); queryEnd2 = cBrd.QueryMeasurementEndOp(); @@ -323,7 +322,7 @@ namespace TBF.BenchControl.TestMethods.CombinedMeters .AddOperation(outPath.TempDiv.ReadTempOp(ref tempDiv)) .AddOperation(benchPath.PressIn.ReadPressureOp(ref pressIn)) .AddOperation(benchPath.PressOut.ReadPressureOp(ref pressOut)) - .AddOperation(readRegisters1) + .AddOperation(readRegistersOp) .AddOperation((StateMachine.Ambient != null) ? StateMachine.Ambient.ReadAmbientOp(airTemperature, airPressure, airHumidity) : null) .AddOperation(outPath.Balance.ReadMassOp(ref mass)) diff --git a/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetectionSeq.cs b/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetectionSeq.cs index 181244b95..2b022e548 100644 --- a/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetectionSeq.cs +++ b/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetectionSeq.cs @@ -61,8 +61,7 @@ namespace TBF.BenchControl.TestMethods.CombinedWithDetection processDataLoggingOp = new TBF.BenchControl.Operations.ProcessDataLoggingOp(processDataLogger, this); /// Meters path is required for the following: - readRegisters1 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); - readRegisters2 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); + readRegistersOp = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); int repetitionNr = 1; /// First test: repetitionNr=1 diff --git a/TestBenchFramework/BenchControl/TestMethods/FixedStartCombinedMeters/FixedStartCombinedMetersSeq.cs b/TestBenchFramework/BenchControl/TestMethods/FixedStartCombinedMeters/FixedStartCombinedMetersSeq.cs index 5e069c78c..2517a8cc5 100644 --- a/TestBenchFramework/BenchControl/TestMethods/FixedStartCombinedMeters/FixedStartCombinedMetersSeq.cs +++ b/TestBenchFramework/BenchControl/TestMethods/FixedStartCombinedMeters/FixedStartCombinedMetersSeq.cs @@ -311,8 +311,7 @@ namespace TBF.BenchControl.TestMethods.FixedStartCombinedMeters /// Measurement loop - preparation - readRegisters1 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); - readRegisters2 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); + readRegistersOp = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); queryEnd1 = cBrd.QueryMeasurementEndOp(); queryEnd2 = cBrd.QueryMeasurementEndOp(); diff --git a/TestBenchFramework/BenchControl/TestMethods/FixedStartMassCollection/FixedStartMassCollectionSeq.cs b/TestBenchFramework/BenchControl/TestMethods/FixedStartMassCollection/FixedStartMassCollectionSeq.cs index 057cef871..3ac0c13ec 100644 --- a/TestBenchFramework/BenchControl/TestMethods/FixedStartMassCollection/FixedStartMassCollectionSeq.cs +++ b/TestBenchFramework/BenchControl/TestMethods/FixedStartMassCollection/FixedStartMassCollectionSeq.cs @@ -311,9 +311,8 @@ namespace TBF.BenchControl.TestMethods.FixedStartMassCollection /// Measurement loop - preparation - readRegisters1 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); - readRegisters2 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); - queryEnd1 = cBrd.QueryMeasurementEndOp(); + readRegistersOp = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); + queryEnd1 = cBrd.QueryMeasurementEndOp(); queryEnd2 = cBrd.QueryMeasurementEndOp(); bool firstTime = true; /// To reset sums for averaging diff --git a/TestBenchFramework/BenchControl/TestMethods/FlyingStart/FlyingStartSeq.cs b/TestBenchFramework/BenchControl/TestMethods/FlyingStart/FlyingStartSeq.cs index 0eeb220df..3ec7c4c01 100644 --- a/TestBenchFramework/BenchControl/TestMethods/FlyingStart/FlyingStartSeq.cs +++ b/TestBenchFramework/BenchControl/TestMethods/FlyingStart/FlyingStartSeq.cs @@ -141,9 +141,8 @@ namespace TBF.BenchControl.TestMethods.FlyingStart while (!e.Contains(Event.MeasurementStarted)); /// Measurement loop - preparation - readRegisters1 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); - readRegisters2 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); - queryEnd1 = cBrd.QueryMeasurementEndOp(); + readRegistersOp = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); + queryEnd1 = cBrd.QueryMeasurementEndOp(); queryEnd2 = cBrd.QueryMeasurementEndOp(); bool firstTime = true; /// To reset sums for averaging diff --git a/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/FlyingStartCollectionMethodSeq.cs b/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/FlyingStartCollectionMethodSeq.cs index c71fd129e..843622a78 100644 --- a/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/FlyingStartCollectionMethodSeq.cs +++ b/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/FlyingStartCollectionMethodSeq.cs @@ -252,45 +252,59 @@ namespace TBF.BenchControl.TestMethods.FlyingStartCollectionMethod } while (!e.Contains(Event.MeasurementStarted)); + /// Reset iPerl volume measurement - foreach (var rr in sensPath.RegisterReaders) - { - if (rr is WaterMeters.iPerl.WaterMeter) - { - (rr as WaterMeters.iPerl.WaterMeter).Reset(); - } - } + //foreach (var rr in sensPath.RegisterReaders) + //{ + // if (rr is WaterMeters.iPerl.WaterMeter) + // { + // (rr as WaterMeters.iPerl.WaterMeter).Reset(); + // } + //} + /// Measurement loop - preparation - readRegisters1 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); - readRegisters2 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); - queryEnd1 = cBrd.QueryMeasurementEndOp(); - queryEnd2 = cBrd.QueryMeasurementEndOp(); + readRegistersOp = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMTimes, ref WMRefPulses); + queryEnd1 = cBrd.QueryMeasurementEndOp(); bool firstTime = true; /// To reset sums for averaging ResetAveragedData(); int estimtdEndTime = StateMachine.Time + (int)tstRslt.TstTime; /// Measurement loop - begin - while (true) - { - //-------------------------------- - switch (ReadRegistersTempPressAmbient(measureOperations, true)) - { - case Event.Error: { retVal = Event.Error; goto stopTest; } - case Event.UiCmdStop: { retVal = Event.UiCmdStop; goto stopTest; } - case Event.MeasurementCompleted: goto test_completed; - } + State.Create("Read water meters") + .AddOperation(checkUiOp) + .AddOperations(measureOperations) + .AddOperation(readRegistersOp) + .AddOperation(benchPath.TempIn.ReadTempOp(ref tempIn)) + .AddOperation(benchPath.TempOut.ReadTempOp(ref tempOut)) + .AddOperation(outPath.TempDiv.ReadTempOp(ref tempDiv)) + .AddOperation(benchPath.PressIn.ReadPressureOp(ref pressIn)) + .AddOperation(benchPath.PressOut.ReadPressureOp(ref pressOut)) + .AddOperation(outPath.Balance.ReadMassOp(ref mass)) + .AddOperation(StateMachine.ControlBoard.UpdateTankWeightOp()) + .AddOperation((StateMachine.Ambient != null) + ? StateMachine.Ambient.ReadAmbientOp(airTemperature, airPressure, airHumidity) + : null) + .AddOperation(queryEnd1) + .AddOperation(processDataLoggingOp) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto stopTest; + if (e.Contains(Event.UiCmdStop)) goto stopTest; + if (e.Contains(Event.MeasurementCompleted)) goto test_completed; //------------------------------------------------ int remainingTime = Math.Max(estimtdEndTime - StateMachine.Time, 0); - Bridge.OnActivity(this, string.Format("{0} ... {1} s", Strings.Test_in_progress, remainingTime)); + Bridge.OnActivity(this, string.Format("{0} ... {1} s", Strings.Test_in_progress, remainingTime)); //------------------------------------------------ if (firstTime) { firstTime = false; /// Do the following only once - tstRslt.TempInStart = tempIn.Val; + tstRslt.TempInStart = tempIn.Val; tstRslt.TempOutStart = tempOut.Val; tstRslt.TempDivStart = tempDiv.Val; tstRslt.PressInStart = pressIn.Val; @@ -304,7 +318,7 @@ namespace TBF.BenchControl.TestMethods.FlyingStartCollectionMethod tstRslt.PressOutEnd = pressOut.Val; tstRslt.MassEndRaw = mass.Val; - AccumulateAveragedData(); + AccumulateAveragedData(); refFreq.Val = cBrd.ReferenceFreq; refFlow.Val = cBrd.ReferenceFlow; @@ -312,18 +326,19 @@ namespace TBF.BenchControl.TestMethods.FlyingStartCollectionMethod tstRslt.AmbientPressAve = airPressure.Val; tstRslt.AmbientHumiAve = airHumidity.Val; - string logstr = string.Format("E={0} f={1} q={2}", cBrd.EtPulses(0), cBrd.ReferenceFreq, - cBrd.ReferenceFlow * outPath.FlowMeter.NominalFlow); - for (int i = 0; i < Program.WMsCount; i++) - { - logstr += string.Format(" M{0}=({1},{2})", i + 1, WMRefPulses[i], WMPulses[i]); - } - log.Debug(logstr); + string logstr = string.Format("E={0} f={1} q={2}", cBrd.EtPulses(0), cBrd.ReferenceFreq, + cBrd.ReferenceFlow * outPath.FlowMeter.NominalFlow); + for (int i = 0; i < Program.WMsCount; i++) + { + logstr += string.Format(" M{0}=({1},{2})", i + 1, WMRefPulses[i], WMPulses[i]); + } + log.Debug(logstr); float progress = Formulas.TestProgress(cBrd.EtPulses(0), totalPulses, estFlowSetTime, test.TstTime); Bridge.OnTestProgress(this, GetTestProgressData(test, tstRslt, true, cBrd, cBrd.TTime, progress)); - } + } + while (true); /// Measurement loop - end test_completed: @@ -334,7 +349,7 @@ namespace TBF.BenchControl.TestMethods.FlyingStartCollectionMethod .AddOperation(outPath.TempDiv.ReadTempOp(ref tempDiv)) .AddOperation(benchPath.PressIn.ReadPressureOp(ref pressIn)) .AddOperation(benchPath.PressOut.ReadPressureOp(ref pressOut)) - .AddOperation(readRegisters1) + .AddOperation(readRegistersOp) .AddOperation((StateMachine.Ambient != null) ? StateMachine.Ambient.ReadAmbientOp(airTemperature, airPressure, airHumidity) : null) .AddOperation(outPath.Balance.ReadMassOp(ref mass)) @@ -362,7 +377,7 @@ namespace TBF.BenchControl.TestMethods.FlyingStartCollectionMethod .AddOperation(outPath.TempDiv.ReadTempOp(ref tempDiv)) .AddOperation(benchPath.PressIn.ReadPressureOp(ref pressIn)) .AddOperation(benchPath.PressOut.ReadPressureOp(ref pressOut)) - .AddOperation(readRegisters1) + .AddOperation(readRegistersOp) .AddOperation((StateMachine.Ambient != null) ? StateMachine.Ambient.ReadAmbientOp(airTemperature, airPressure, airHumidity) : null) .AddOperation(outPath.Balance.ReadStableMassOp(ref endMass, 5)) @@ -436,9 +451,18 @@ namespace TBF.BenchControl.TestMethods.FlyingStartCollectionMethod tstRslt.Meters[i].VolumeStart = 0; /// liter tstRslt.Meters[i].VolumeEnd = 0; /// liter tstRslt.Meters[i].PulsesPerLiter = (sensPath.RegisterReaders[i] == null ? 1.0f : sensPath.RegisterReaders[i].PulsesPerLtr); - if (sensPath.RegisterReaders[i].PulsesPerLtr <= float.Epsilon) tstRslt.Meters[i].VolumeMeter = 0; - else tstRslt.Meters[i].VolumeMeter = Convert.ToSingle(WMPulses[i]) / sensPath.RegisterReaders[i].PulsesPerLtr; - tstRslt.Meters[i].VolumeRef = tstRslt.ConstMaster * WMRefPulses[i]; /// liter + if (sensPath.RegisterReaders[i] is WaterMeters.iPerl.WaterMeter) + { + WaterMeters.iPerl.WaterMeter iPerl = (sensPath.RegisterReaders[i] as WaterMeters.iPerl.WaterMeter); + tstRslt.Meters[i].VolumeMeter = (float)(iPerl.VolumeLtrEnd - iPerl.VolumeLtrStart); + tstRslt.Meters[i].VolumeRef = tstRslt.VolumeCTV * (float)(iPerl.TimestampSecEnd - iPerl.TimestampSecStart) / tstRslt.Time; + } + else + { + if (sensPath.RegisterReaders[i].PulsesPerLtr <= float.Epsilon) tstRslt.Meters[i].VolumeMeter = 0; + else tstRslt.Meters[i].VolumeMeter = Convert.ToSingle(WMPulses[i]) / sensPath.RegisterReaders[i].PulsesPerLtr; + tstRslt.Meters[i].VolumeRef = tstRslt.ConstMaster * WMRefPulses[i]; /// liter + } tstRslt.Meters[i].PulsesMeter = WMPulses[i]; tstRslt.Meters[i].PulsesMaster = WMRefPulses[i]; tstRslt.Meters[i].Time = cBrd.TTime; diff --git a/TestBenchFramework/BenchControl/TestMethods/ReferenceFlowmeterCalibration/ReferenceFlowmeterCalibrationSeq.cs b/TestBenchFramework/BenchControl/TestMethods/ReferenceFlowmeterCalibration/ReferenceFlowmeterCalibrationSeq.cs index 420703f07..b0bb823af 100644 --- a/TestBenchFramework/BenchControl/TestMethods/ReferenceFlowmeterCalibration/ReferenceFlowmeterCalibrationSeq.cs +++ b/TestBenchFramework/BenchControl/TestMethods/ReferenceFlowmeterCalibration/ReferenceFlowmeterCalibrationSeq.cs @@ -213,9 +213,8 @@ namespace TBF.BenchControl.TestMethods.ReferenceFlowmeterCalibration while (!e.Contains(Event.MeasurementStarted)); /// Measurement loop - preparation - readRegisters1 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); - readRegisters2 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); - queryEnd1 = cBrd.QueryMeasurementEndOp(); + readRegistersOp = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); + queryEnd1 = cBrd.QueryMeasurementEndOp(); queryEnd2 = cBrd.QueryMeasurementEndOp(); bool firstTime = true; /// To reset sums for averaging @@ -279,7 +278,7 @@ namespace TBF.BenchControl.TestMethods.ReferenceFlowmeterCalibration .AddOperation(outPath.TempDiv.ReadTempOp(ref tempDiv)) .AddOperation(benchPath.PressIn.ReadPressureOp(ref pressIn)) .AddOperation(benchPath.PressOut.ReadPressureOp(ref pressOut)) - .AddOperation(readRegisters1) + .AddOperation(readRegistersOp) .AddOperation((StateMachine.Ambient != null) ? StateMachine.Ambient.ReadAmbientOp(airTemperature, airPressure, airHumidity) : null) .AddOperation(outPath.Balance.ReadMassOp(ref mass)) diff --git a/TestBenchFramework/BenchControl/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs b/TestBenchFramework/BenchControl/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs index 304dbb6fe..11cb38962 100644 --- a/TestBenchFramework/BenchControl/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs +++ b/TestBenchFramework/BenchControl/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs @@ -30,51 +30,100 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication public partial class iPerlCommunicationForm : Form, GenericDevices.IHasCompleted { - private static readonly ILog log = LogManager.GetLogger(typeof(iPerlCommunicationForm)); + const int CommTimeout = 1500; + const int MaxCommRetries = 3; + const int NrThreads = 2; /// 1, 2 or 4 threads + + + private static readonly ILog log = LogManager.GetLogger(typeof(iPerlCommunicationForm)); protected static readonly ILog rfidDataLogger = LogManager.GetLogger("RfidData"); #region DLL_Interface - [DllImport("libRfid.dll", EntryPoint = "getDllVersion")] - public static extern unsafe int getDllVersion(); + [DllImport("libRfid1.dll", EntryPoint = "getDllVersion")] static extern unsafe int getDllVersion1(); + [DllImport("libRfid1.dll", EntryPoint = "openPort")] static extern unsafe int openPort1(int comPort); + [DllImport("libRfid1.dll", EntryPoint = "closePort")] static extern unsafe int closePort1(); + [DllImport("libRfid1.dll", EntryPoint = "readRequestPort")] static extern unsafe int readRequestPort1(MessageID messageId, int offset, int lenght, byte* ptr, int timeout_ms); + [DllImport("libRfid1.dll", EntryPoint = "writeRequestPort")] static extern unsafe int writeRequestPort1(MessageID messageId, int offset, int lenght, byte* ptr, int timeout_ms); - [DllImport("libRfid.dll", EntryPoint = "openPort")] - static extern unsafe int openPort(int comPort); + [DllImport("libRfid2.dll", EntryPoint = "getDllVersion")] public static extern unsafe int getDllVersion2(); + [DllImport("libRfid2.dll", EntryPoint = "openPort")] static extern unsafe int openPort2(int comPort); + [DllImport("libRfid2.dll", EntryPoint = "closePort")] static extern unsafe int closePort2(); + [DllImport("libRfid2.dll", EntryPoint = "readRequestPort")] static extern unsafe int readRequestPort2(MessageID messageId, int offset, int lenght, byte* ptr, int timeout_ms); + [DllImport("libRfid2.dll", EntryPoint = "writeRequestPort")] static extern unsafe int writeRequestPort2(MessageID messageId, int offset, int lenght, byte* ptr, int timeout_ms); - [DllImport("libRfid.dll", EntryPoint = "closePort")] - static extern unsafe int closePort(); + [DllImport("libRfid3.dll", EntryPoint = "getDllVersion")] public static extern unsafe int getDllVersion3(); + [DllImport("libRfid3.dll", EntryPoint = "openPort")] static extern unsafe int openPort3(int comPort); + [DllImport("libRfid3.dll", EntryPoint = "closePort")] static extern unsafe int closePort3(); + [DllImport("libRfid3.dll", EntryPoint = "readRequestPort")] static extern unsafe int readRequestPort3(MessageID messageId, int offset, int lenght, byte* ptr, int timeout_ms); + [DllImport("libRfid3.dll", EntryPoint = "writeRequestPort")] static extern unsafe int writeRequestPort3(MessageID messageId, int offset, int lenght, byte* ptr, int timeout_ms); - [DllImport("libRfid.dll", EntryPoint = "readRequestPort")] - static extern unsafe int readRequestPort(MessageID messageId, int offset, int lenght, byte* ptr, int timeout_ms); + [DllImport("libRfid4.dll", EntryPoint = "getDllVersion")] public static extern unsafe int getDllVersion4(); + [DllImport("libRfid4.dll", EntryPoint = "openPort")] static extern unsafe int openPort4(int comPort); + [DllImport("libRfid4.dll", EntryPoint = "closePort")] static extern unsafe int closePort4(); + [DllImport("libRfid4.dll", EntryPoint = "readRequestPort")] static extern unsafe int readRequestPort4(MessageID messageId, int offset, int lenght, byte* ptr, int timeout_ms); + [DllImport("libRfid4.dll", EntryPoint = "writeRequestPort")] static extern unsafe int writeRequestPort4(MessageID messageId, int offset, int lenght, byte* ptr, int timeout_ms); - [DllImport("libRfid.dll", EntryPoint = "writeRequestPort")] - static extern unsafe int writeRequestPort(MessageID messageId, int offset, int lenght, byte* ptr, int timeout_ms); - - static int currentPort; + static int[] currentPort; /// /// Wrapper function with safe interface and unsafe body /// + /// 0..3 + /// Com port number /// Value returned by openPort(...) - public static unsafe int OpenPort(int comPort) + public static unsafe int OpenPort(int boardNr, int comPort) { - currentPort = comPort; - return openPort(comPort); + currentPort[boardNr] = comPort; + switch (boardNr) + { + default: + case 0: return openPort1(comPort); + case 1: return openPort2(comPort); + case 2: return openPort3(comPort); + case 3: return openPort4(comPort); + } } - /// + /// + /// Wrapper function with safe interface and unsafe body + /// + /// 0..3 + /// Com port number + /// Value returned by openPort(...) + public static unsafe int ClosePort(int boardNr) + { + switch (boardNr) + { + default: + case 0: return closePort1(); + case 1: return closePort2(); + case 2: return closePort3(); + case 3: return closePort4(); + } + } + + /// /// Wrapper function with safe interface and unsafe body /// /// Value returned by readRequestPort(...) - public static unsafe int ReadRequestPort(MessageID messageID, int offset, int lenght, out byte[] buffer, int timeout) + public static unsafe int ReadRequestPort(int boardNr, MessageID messageID, int offset, int lenght, out byte[] buffer, int timeout) { byte[] buf = new byte[1000]; int retv; fixed (byte* pBuf = buf) { - retv = readRequestPort(messageID, offset, lenght, pBuf, timeout); - rfidDataLogger.InfoFormat("Group={0}, Port={1}, ReadRequestPort({2}, {3}, {4}, ...) returned {5} {6}", currentGroup, currentPort, messageID, offset, lenght, retv, (retv != 0) ? "!" : ""); + switch (boardNr) + { + default: + case 0: retv = readRequestPort1(messageID, offset, lenght, pBuf, timeout); break; + case 1: retv = readRequestPort2(messageID, offset, lenght, pBuf, timeout); break; + case 2: retv = readRequestPort3(messageID, offset, lenght, pBuf, timeout); break; + case 3: retv = readRequestPort4(messageID, offset, lenght, pBuf, timeout); break; + } + + rfidDataLogger.InfoFormat("Group={0}, Port={1}, ReadRequestPort({2}, {3}, {4}, ...) returned {5} {6}", currentGroup, currentPort[boardNr], messageID, offset, lenght, retv, (retv != 0) ? "!" : ""); buffer = new byte[lenght]; for (int i = 0; i < lenght; i++) buffer[i] = buf[i]; @@ -87,23 +136,31 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication /// Wrapper function with safe interface adn unsafe body /// /// Value returned by writeRequestPort(...) - public static unsafe int WriteRequestPort(MessageID messageID, int offset, int lenght, byte[] buffer, int timeout) + public static unsafe int WriteRequestPort(int boardNr, MessageID messageID, int offset, int lenght, byte[] buffer, int timeout) { int retv; fixed (byte* pBuf = buffer) { - retv = writeRequestPort(messageID, offset, lenght, pBuf, timeout); + switch (boardNr) + { + default: + case 0: retv = writeRequestPort1(messageID, offset, lenght, pBuf, timeout); break; + case 1: retv = writeRequestPort2(messageID, offset, lenght, pBuf, timeout); break; + case 2: retv = writeRequestPort3(messageID, offset, lenght, pBuf, timeout); break; + case 3: retv = writeRequestPort4(messageID, offset, lenght, pBuf, timeout); break; + } + if (lenght == 1) { - rfidDataLogger.InfoFormat("Group={0}, Port={1}, WriteRequestPort({3}, {4}, {5}, {6}) returned {2} {7}", currentGroup, currentPort, retv, messageID, offset, lenght, pBuf[0].ToString("X2"), (retv != 0) ? "!" : ""); + rfidDataLogger.InfoFormat("Group={0}, Port={1}, WriteRequestPort({3}, {4}, {5}, {6}) returned {2} {7}", currentGroup, currentPort[boardNr], retv, messageID, offset, lenght, pBuf[0].ToString("X2"), (retv != 0) ? "!" : ""); } else if (lenght == 2) { - rfidDataLogger.InfoFormat("Group={0}, Port={1}, WriteRequestPort({3}, {4}, {5}, {6} {7}) returned {2} {8}", currentGroup, currentPort, retv, messageID, offset, lenght, pBuf[0].ToString("X2"), pBuf[1].ToString("X2"), (retv != 0) ? "!" : ""); + rfidDataLogger.InfoFormat("Group={0}, Port={1}, WriteRequestPort({3}, {4}, {5}, {6} {7}) returned {2} {8}", currentGroup, currentPort[boardNr], retv, messageID, offset, lenght, pBuf[0].ToString("X2"), pBuf[1].ToString("X2"), (retv != 0) ? "!" : ""); } else { - rfidDataLogger.InfoFormat("Group={0}, Port={1}, WriteRequestPort({3}, {4}, {5}, {6} {7} ...) returned {2} {8}", currentGroup, currentPort, retv, messageID, offset, lenght, pBuf[0].ToString("X2"), pBuf[1].ToString("X2"), (retv != 0) ? "!" : ""); + rfidDataLogger.InfoFormat("Group={0}, Port={1}, WriteRequestPort({3}, {4}, {5}, {6} {7} ...) returned {2} {8}", currentGroup, currentPort[boardNr], retv, messageID, offset, lenght, pBuf[0].ToString("X2"), pBuf[1].ToString("X2"), (retv != 0) ? "!" : ""); } } return retv; @@ -112,9 +169,6 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication #endregion DLL_Interface - const int CommTimeout = 250; - const int MaxCommRetries = 5; - const string ReadConfigurationStr = "Read configuration"; /// Example: "Read configuration" or "Read configuration if enabled" const string SetTestModeStr = "Set Test mode"; /// Example: "Set Test mode" or "Set Test mode A0" (hexadecimal number is the required 'testModeConfig' const string SetActiveModeStr = "Set Active mode"; @@ -202,6 +256,8 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication formCompleted = false; tr = null; + currentPort = new int[4]; + /// Find QuidoRS foreach (var comp in StateMachine.Components) { @@ -265,17 +321,20 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication { WaterMeters.iPerl.WaterMeter iPerlWM = wm as WaterMeters.iPerl.WaterMeter; iPerlCommunicationForm.waterMeters.Add(iPerlWM); - if (!rfidPortNrs.Contains(iPerlWM.RfidComPortNr)) rfidPortNrs.Add(iPerlWM.RfidComPortNr); - if (iPerlWM.Group > lastGroup) lastGroup = iPerlWM.Group; - } + if (!rfidPortNrs.Contains(iPerlWM.RfidComPortNr)) + { + rfidPortNrs.Add(iPerlWM.RfidComPortNr); - /// Only one thread - { - int threadId = workerThreads.Count; - Thread thread = new Thread(iPerlCommunicationForm.Worker); - workerThreads.Add(thread); - stopWorkerThreads.Add(false); - thread.Start(new Boxes.IntBox(threadId)); + int newThreadId = workerThreads.Count; + if (newThreadId < NrThreads) + { + Thread thread = new Thread(iPerlCommunicationForm.Worker); + workerThreads.Add(thread); + stopWorkerThreads.Add(false); + thread.Start(new Boxes.IntBox(newThreadId)); + } + } + if (iPerlWM.Group > lastGroup) lastGroup = iPerlWM.Group; } #endif activityLabel.Text = activity; @@ -352,6 +411,10 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication Thread.Sleep(200); } currentGroup++; + + TBF.LocalSettings ls = Program.LocalSettings; + Left = (ls.iPerlCommunicationsFormLeft != 0) ? ls.iPerlCommunicationsFormLeft : 150; + Top = (ls.iPerlCommunicationsFormTop != 0) ? ls.iPerlCommunicationsFormTop : 150; } private void NormalClose() @@ -360,6 +423,9 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication AllCompletedHandler = null; formCompleted = true; + Program.LocalSettings.iPerlCommunicationsFormLeft = Location.X; + Program.LocalSettings.iPerlCommunicationsFormTop = Location.Y; + Program.LocalSettings.Save(); DialogResult = DialogResult.OK; Close(); @@ -436,10 +502,9 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication if (stopWorkerThreads[threadId]) break; - for (int rid = 0; rid < rfidPortNrs.Count; rid++) + for (int rfidPortIx = threadId; rfidPortIx < threadId + 4; rfidPortIx += NrThreads) { - int rfidPortNr = rfidPortNrs[rid]; - + int rfidPortNr = rfidPortNrs[rfidPortIx]; int wmNr = 0; bool wmFound = false; foreach (var wm in waterMeters) @@ -449,31 +514,31 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication wmFound = true; if (wm.DebugLevel == Entities.DebugMode.Normal) { - CommErr error; - string resultStr = string.Empty; + CommErr error; + string resultStr = string.Empty; - if (activity.ToLower().Contains(ReadConfigurationStr.ToLower())) error = ReadConfiguration(wm, ref resultStr); - else if (activity.ToLower().Contains(SetTestModeStr.ToLower())) error = SetTestMode(wm, ref resultStr); - else if (activity.ToLower().Equals(SetActiveModeStr.ToLower())) error = SetActiveMode(wm, ref resultStr); - else if (activity.ToLower().Equals(ReadCalibrationStr.ToLower())) error = ReadCalibration(wm, ref resultStr); - else if (activity.ToLower().Equals(WriteCalibrationFactorStr.ToLower())) error = WriteCalibrationFactor(wm, ref resultStr); - else if (activity.ToLower().Equals(ResetQ2CorrectionStr.ToLower())) error = ResetQ2Correction(wm, ref resultStr); - else if (activity.ToLower().Equals(WriteQ2CorrectionStr.ToLower())) error = WriteQ2Correction(wm, ref resultStr); - else - { - error = CommErr.None; - resultStr = "Invalid activity"; - } + if (activity.ToLower().Contains(ReadConfigurationStr.ToLower())) error = ReadConfiguration(wm, ref resultStr); + else if (activity.ToLower().Contains(SetTestModeStr.ToLower())) error = SetTestMode(wm, ref resultStr); + else if (activity.ToLower().Equals(SetActiveModeStr.ToLower())) error = SetActiveMode(wm, ref resultStr); + else if (activity.ToLower().Equals(ReadCalibrationStr.ToLower())) error = ReadCalibration(wm, ref resultStr); + else if (activity.ToLower().Equals(WriteCalibrationFactorStr.ToLower())) error = WriteCalibrationFactor(wm, ref resultStr); + else if (activity.ToLower().Equals(ResetQ2CorrectionStr.ToLower())) error = ResetQ2Correction(wm, ref resultStr); + else if (activity.ToLower().Equals(WriteQ2CorrectionStr.ToLower())) error = WriteQ2Correction(wm, ref resultStr); + else + { + error = CommErr.None; + resultStr = "Invalid activity"; + } - if (error == CommErr.None) OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, resultStr)); + if (error == CommErr.None) OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, resultStr)); else if (wm.Disabled || error == CommErr.Disabled) OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, "Watermeter is disabled")); - else - { - OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, string.Format("{0} failed ({1}) !!!", activity, error))); + else + { + OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, string.Format("{0} failed ({1}) !!!", activity, error))); rfidDataLogger.ErrorFormat("Group={0}, Port={1}, {2} failed ({3}) !!!", currentGroup, currentPort, activity, error); wm.Disabled = true; - } - } + } + } else { OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, "Simulation")); @@ -497,6 +562,8 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication /// true on success static CommErr ReadConfiguration(WaterMeters.iPerl.WaterMeter wm, ref string resultStr) { + int boardNr = wm.RfidComPortNr - 51; + /// /// The activity is "Read configuration" (this enables the watermeter, resets error flag) /// or "Read configuration if enabled" (this keeps th error flag). @@ -508,7 +575,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication if (wm.Disabled) return CommErr.Disabled; - if (OpenPort(wm.RfidComPortNr) != 0) return CommErr.OpenPort; /// Open RFID port + if (OpenPort(boardNr, wm.RfidComPortNr) != 0) return CommErr.OpenPort; /// Open RFID port CommErr error = CommErr.Read; @@ -516,7 +583,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication byte[] config = null; for (int j = 0; j < MaxCommRetries; j++) { - if (0 == ReadRequestPort(MessageID.Configuration, 0, ConfigStruct.Length, out config, CommTimeout)) + if (0 == ReadRequestPort(boardNr, MessageID.Configuration, 0, ConfigStruct.Length, out config, CommTimeout)) { error = CommErr.None; wm.ConfigStruct = ConfigStruct.FromByteArray(config); @@ -525,7 +592,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication } } - closePort(); /// Close RFID port + ClosePort(boardNr); /// Close RFID port return error; } @@ -542,6 +609,8 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication /// true on success static CommErr SetTestMode(WaterMeters.iPerl.WaterMeter wm, ref string resultStr) { + int boardNr = wm.RfidComPortNr - 51; + if (wm.Disabled) return CommErr.Disabled; Byte testModeConfig = 0xA0; /// Default value @@ -559,11 +628,12 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication if (wm.ConfigStruct.MeterState == MeterState.Test && wm.ConfigStruct.TestModeConfig == testModeConfig) { /// Already in the correct test mode + resultStr = "Already " + wm.ConfigStruct.ToString(1); return CommErr.None; } /// Communication necessary - if (OpenPort(wm.RfidComPortNr) != 0) return CommErr.OpenPort; /// Open RFID port + if (OpenPort(boardNr, wm.RfidComPortNr) != 0) return CommErr.OpenPort; /// Open RFID port CommErr error = CommErr.None; @@ -574,7 +644,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication byte[] cmd = new byte[1] { (byte)6 }; for (int j = 0; j < MaxCommRetries; j++) { - if (0 == WriteRequestPort(MessageID.Command, 0, 1, cmd, CommTimeout)) { error = CommErr.None; break; } + if (0 == WriteRequestPort(boardNr, MessageID.Command, 0, 1, cmd, CommTimeout)) { error = CommErr.None; break; } } } @@ -585,7 +655,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication byte[] tstMdCfg = new byte[1] { testModeConfig }; for (int j = 0; j < MaxCommRetries; j++) { - if (0 == WriteRequestPort(MessageID.Configuration, 21, 1, tstMdCfg, CommTimeout)) + if (0 == WriteRequestPort(boardNr, MessageID.Configuration, 21, 1, tstMdCfg, CommTimeout)) { wm.ConfigStruct.Update(21, tstMdCfg); error = CommErr.None; @@ -601,7 +671,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication byte[] cmd = new byte[1] { (byte)7 }; for (int j = 0; j < MaxCommRetries; j++) { - if (0 == WriteRequestPort(MessageID.Command, 0, 1, cmd, CommTimeout)) { error = CommErr.None; break; } + if (0 == WriteRequestPort(boardNr, MessageID.Command, 0, 1, cmd, CommTimeout)) { error = CommErr.None; break; } } } @@ -613,7 +683,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication byte[] cfg_0_3 = null; for (int j = 0; j < MaxCommRetries; j++) { - if (0 == ReadRequestPort(MessageID.Configuration, 0, 4, out cfg_0_3, CommTimeout)) + if (0 == ReadRequestPort(boardNr, MessageID.Configuration, 0, 4, out cfg_0_3, CommTimeout)) { wm.ConfigStruct.Update(0, cfg_0_3); if (wm.ConfigStruct.MeterState == MeterState.Test) @@ -626,7 +696,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication } } - closePort(); /// Close RFID port + ClosePort(boardNr); /// Close RFID port return error; } @@ -641,9 +711,11 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication /// true on success static CommErr SetActiveMode(WaterMeters.iPerl.WaterMeter wm, ref string resultStr) { + int boardNr = wm.RfidComPortNr - 51; + if (wm.Disabled) return CommErr.Disabled; - if (OpenPort(wm.RfidComPortNr) != 0) return CommErr.OpenPort; /// Open RFID port + if (OpenPort(boardNr, wm.RfidComPortNr) != 0) return CommErr.OpenPort; /// Open RFID port CommErr error = CommErr.CmdActive; @@ -651,7 +723,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication byte[] cmd = new byte[1] { (byte)6 }; for (int j = 0; j < MaxCommRetries; j++) { - if (0 == WriteRequestPort(MessageID.Command, 0, 1, cmd, CommTimeout)) { error = CommErr.None; break; } + if (0 == WriteRequestPort(boardNr, MessageID.Command, 0, 1, cmd, CommTimeout)) { error = CommErr.None; break; } } if (error == CommErr.None) @@ -662,7 +734,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication byte[] cfg_0_3 = null; for (int j = 0; j < MaxCommRetries; j++) { - if (0 == ReadRequestPort(MessageID.Configuration, 0, 4, out cfg_0_3, CommTimeout)) + if (0 == ReadRequestPort(boardNr, MessageID.Configuration, 0, 4, out cfg_0_3, CommTimeout)) { wm.ConfigStruct.Update(0, cfg_0_3); if (wm.ConfigStruct.MeterState == MeterState.Active) @@ -675,7 +747,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication } } - closePort(); /// Close RFID port + ClosePort(boardNr); /// Close RFID port return error; } @@ -689,9 +761,11 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication /// true on success static CommErr ReadCalibration(WaterMeters.iPerl.WaterMeter wm, ref string resultStr) { + int boardNr = wm.RfidComPortNr - 51; + if (wm.Disabled) return CommErr.Disabled; - if (OpenPort(wm.RfidComPortNr) != 0) return CommErr.OpenPort; /// Open RFID port + if (OpenPort(boardNr, wm.RfidComPortNr) != 0) return CommErr.OpenPort; /// Open RFID port CommErr error = CommErr.Read; @@ -699,7 +773,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication byte[] calib = null; for (int j = 0; j < MaxCommRetries; j++) { - if (0 == ReadRequestPort(MessageID.Calibration, 0, CalibrationStruct.Length, out calib, CommTimeout)) + if (0 == ReadRequestPort(boardNr, MessageID.Calibration, 0, CalibrationStruct.Length, out calib, CommTimeout)) { error = CommErr.None; wm.CalibrationStruct = CalibrationStruct.FromByteArray(calib); @@ -708,7 +782,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication } } - closePort(); /// Close RFID port + ClosePort(boardNr); /// Close RFID port return error; } @@ -723,9 +797,11 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication /// true on success static CommErr WriteCalibrationFactor(WaterMeters.iPerl.WaterMeter wm, ref string resultStr) { + int boardNr = wm.RfidComPortNr - 51; + if (wm.Disabled) return CommErr.Disabled; - if (OpenPort(wm.RfidComPortNr) != 0) return CommErr.OpenPort; /// Open RFID port + if (OpenPort(boardNr, wm.RfidComPortNr) != 0) return CommErr.OpenPort; /// Open RFID port CommErr error = CommErr.Write; @@ -736,7 +812,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication byte[] data = new byte[2] { (byte)(newCalFactor & 0x00FF), (byte)((newCalFactor >> 8) & 0x00FF) }; for (int j = 0; j < MaxCommRetries; j++) { - if (0 == WriteRequestPort(MessageID.Calibration, 2, 2, data, CommTimeout)) { error = CommErr.None; break; } + if (0 == WriteRequestPort(boardNr, MessageID.Calibration, 2, 2, data, CommTimeout)) { error = CommErr.None; break; } } if (error == CommErr.None) @@ -747,7 +823,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication byte[] calib_2_3 = null; for (int j = 0; j < MaxCommRetries; j++) { - if (0 == ReadRequestPort(MessageID.Calibration, 2, 2, out calib_2_3, CommTimeout)) + if (0 == ReadRequestPort(boardNr, MessageID.Calibration, 2, 2, out calib_2_3, CommTimeout)) { error = CommErr.None; wm.CalibrationStruct.Update(calib_2_3, 2); @@ -757,7 +833,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication } } - closePort(); /// Close RFID port + ClosePort(boardNr); /// Close RFID port return error; } @@ -775,9 +851,11 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication /// true on success static CommErr ResetQ2Correction(WaterMeters.iPerl.WaterMeter wm, ref string resultStr) { + int boardNr = wm.RfidComPortNr - 51; + if (wm.Disabled) return CommErr.Disabled; - if (OpenPort(wm.RfidComPortNr) != 0) return CommErr.OpenPort; /// Open RFID port + if (OpenPort(boardNr, wm.RfidComPortNr) != 0) return CommErr.OpenPort; /// Open RFID port CommErr error = CommErr.Write; @@ -788,7 +866,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication for (int j = 0; j < MaxCommRetries; j++) { - if (0 == WriteRequestPort(MessageID.MetrologyMemory, Q2CorrFactorsAddr, 2, wrData, CommTimeout)) { error = CommErr.None; break; } + if (0 == WriteRequestPort(boardNr, MessageID.MetrologyMemory, Q2CorrFactorsAddr, 2, wrData, CommTimeout)) { error = CommErr.None; break; } } if (error == CommErr.None) @@ -799,7 +877,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication byte[] rdData = null; for (int j = 0; j < MaxCommRetries; j++) { - if ((0 == ReadRequestPort(MessageID.MetrologyMemory, Q2CorrFactorsAddr, 2, out rdData, CommTimeout)) && + if ((0 == ReadRequestPort(boardNr, MessageID.MetrologyMemory, Q2CorrFactorsAddr, 2, out rdData, CommTimeout)) && (rdData != null) && (rdData.Length == 2) && (rdData[0] == 0) && (rdData[1] == 0)) { error = CommErr.None; @@ -809,7 +887,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication } } - closePort(); /// Close RFID port + ClosePort(boardNr); /// Close RFID port return error; } @@ -824,9 +902,11 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication /// true on success static CommErr WriteQ2Correction(WaterMeters.iPerl.WaterMeter wm, ref string resultStr) { + int boardNr = wm.RfidComPortNr - 51; + if (wm.Disabled) return CommErr.Disabled; - if (OpenPort(wm.RfidComPortNr) != 0) return CommErr.OpenPort; /// Open RFID port + if (OpenPort(boardNr, wm.RfidComPortNr) != 0) return CommErr.OpenPort; /// Open RFID port CommErr error = CommErr.Write; @@ -837,7 +917,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication for (int j = 0; j < MaxCommRetries; j++) { - if (0 == WriteRequestPort(MessageID.MetrologyMemory, Q2CorrFactorsAddr, 2, wrData, CommTimeout)) { error = CommErr.None; break; } + if (0 == WriteRequestPort(boardNr, MessageID.MetrologyMemory, Q2CorrFactorsAddr, 2, wrData, CommTimeout)) { error = CommErr.None; break; } } if (error == CommErr.None) @@ -848,7 +928,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication byte[] rdData = null; for (int j = 0; j < MaxCommRetries; j++) { - if ((0 == ReadRequestPort(MessageID.MetrologyMemory, Q2CorrFactorsAddr, 2, out rdData, CommTimeout)) && + if ((0 == ReadRequestPort(boardNr, MessageID.MetrologyMemory, Q2CorrFactorsAddr, 2, out rdData, CommTimeout)) && (rdData != null) && (rdData.Length == 2) && (rdData[0] == q2CorrRFlow) && (rdData[1] == q2CorrRFlow)) { error = CommErr.None; diff --git a/TestBenchFramework/BenchControl/TestMethods/iPerlCommunication/iPerlCommunicationSeq.cs b/TestBenchFramework/BenchControl/TestMethods/iPerlCommunication/iPerlCommunicationSeq.cs index 2cab720ac..49ecb0235 100644 --- a/TestBenchFramework/BenchControl/TestMethods/iPerlCommunication/iPerlCommunicationSeq.cs +++ b/TestBenchFramework/BenchControl/TestMethods/iPerlCommunication/iPerlCommunicationSeq.cs @@ -23,7 +23,12 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication /// void OpenIPerlCommForm(iPerlCommunicationSeq myRef, string activity) { - myRef.modelessDlg = new iPerlCommunicationForm(WaterMeters, activity); + IList wMtrs = new List(); + foreach (var rr in sensPath.RegisterReaders) + { + if (rr is GenericDevices.IWaterMeter) wMtrs.Add(rr as GenericDevices.IWaterMeter); + } + myRef.modelessDlg = new iPerlCommunicationForm(wMtrs, activity); modelessDlg.Show(); } diff --git a/TestBenchFramework/BenchControl/WaterMeters/iPerl/Enums.cs b/TestBenchFramework/BenchControl/WaterMeters/iPerl/Enums.cs index 88905fe3c..4d7ae0232 100644 --- a/TestBenchFramework/BenchControl/WaterMeters/iPerl/Enums.cs +++ b/TestBenchFramework/BenchControl/WaterMeters/iPerl/Enums.cs @@ -48,6 +48,7 @@ namespace TBF.BenchControl.WaterMeters.iPerl DN26 = 4, /// DN25* DN32 = 5, DN40 = 6, + AutoDetect, Count /// Number of meter types } diff --git a/TestBenchFramework/BenchControl/WaterMeters/iPerl/OptoTelegramRaw.cs b/TestBenchFramework/BenchControl/WaterMeters/iPerl/OptoTelegramRaw.cs index 03a583172..9df86982a 100644 --- a/TestBenchFramework/BenchControl/WaterMeters/iPerl/OptoTelegramRaw.cs +++ b/TestBenchFramework/BenchControl/WaterMeters/iPerl/OptoTelegramRaw.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Globalization; namespace TBF.BenchControl.WaterMeters.iPerl { @@ -9,24 +7,29 @@ namespace TBF.BenchControl.WaterMeters.iPerl { public static readonly int Length = 42; - public Int32 EMF; + public UInt32 EmfRaw; public Int16 MagneticField; - public Int16 Flow; - public Int32 Volume; + public Int16 FlowRaw; + public Int32 VolumeRaw; public Int16 Impedance; - public UInt32 Timestamp; + public Int64 Timestamp; public byte GG; + string sourceStr; + public OptoTelegramRaw() { } public override string ToString() { - return ""; + return sourceStr; } /// + /// Parses optical telegram and returns OptoTelegramRaw object + /// + /// /// Create a configuration structure from a complete byte array /// /// Telegram description: @@ -48,23 +51,38 @@ namespace TBF.BenchControl.WaterMeters.iPerl /// FFFFFE 51EA 0000 65324E 0087 F6319DFF 86 /// FFDD3A 51F9 0000 65324E 0088 F631A60B 45 /// ... - /// + /// /// A complete byte array data /// ConfigStruct or null when byte array was not complete - public static OptoTelegramRaw FromString(string telegram, MeterType meterType) + public static OptoTelegramRaw FromString(string telegram) { if ((telegram == null) || (telegram.Length < Length) || - (telegram[6] != '\t') || (telegram[11] != '\t') || - (telegram[16] != '\t') || (telegram[23] != '\t') || - (telegram[28] != '\t') || (telegram[37] != '\t') || - (telegram[40] != '\r') || (telegram[41] != '\n')) + (telegram[6] != '\t') || (telegram[11] != '\t') || (telegram[16] != '\t') || + (telegram[23] != '\t') || (telegram[28] != '\t') || (telegram[37] != '\t') || + (telegram[40] != '\r') || (telegram[41] != '\n')) { return null; } OptoTelegramRaw opto = new OptoTelegramRaw(); - return opto; + bool f1 = UInt32.TryParse(telegram.Substring(0, 6), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out opto.EmfRaw); + bool f2 = Int16.TryParse(telegram.Substring(7, 4), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out opto.MagneticField); + bool f3 = Int16.TryParse(telegram.Substring(12, 4), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out opto.FlowRaw); + bool f4 = Int32.TryParse(telegram.Substring(17, 6), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out opto.VolumeRaw); + bool f5 = Int16.TryParse(telegram.Substring(24, 4), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out opto.Impedance); + bool f6 = Int64.TryParse(telegram.Substring(29, 8), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out opto.Timestamp); + bool f7 = byte.TryParse(telegram.Substring(38, 2), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out opto.GG); + + if (f1 && f2 && f3 && f4 && f5 && f6 && f7) + { + opto.sourceStr = telegram.Substring(0, Length - 2); + return opto; + } + else + { + return null; + } } } } diff --git a/TestBenchFramework/BenchControl/WaterMeters/iPerl/WaterMeter.cs b/TestBenchFramework/BenchControl/WaterMeters/iPerl/WaterMeter.cs index db06f0a9a..31c26e1d2 100644 --- a/TestBenchFramework/BenchControl/WaterMeters/iPerl/WaterMeter.cs +++ b/TestBenchFramework/BenchControl/WaterMeters/iPerl/WaterMeter.cs @@ -18,9 +18,10 @@ namespace TBF.BenchControl.WaterMeters.iPerl public class WaterMeter : ComponentBase, IDevice, GenericDevices.IWaterMeter, GenericDevices.IRegisterReader, IOperation { private static readonly ILog log = LogManager.GetLogger(typeof(WaterMeter)); - protected static readonly ILog optoDataLogger = LogManager.GetLogger("OptoData"); + protected ILog optoDataLogger; /// Instance logger for opto-port data public override string ToString() { return string.Format("iPerl({0})", Cfg.ToString(1)); } + readonly WaterMeterCfg iPerlCfg; public int RfidComPortNr { get { return iPerlCfg.RfidComPortNr; } } @@ -97,14 +98,37 @@ namespace TBF.BenchControl.WaterMeters.iPerl } - /// - /// Volume of water in liter set by OptoTelegramRreceived(...) - /// - private double volumeLtr; - private double volumeLtrStart; + int sampleNr; + + /// + /// Volume of water from the opto telegram + /// + bool lastVolumeRawValid; /// true = valid + private Int32 lastVolumeRaw; /// Last read raw volume + private double volumeLtr; /// + private double volumeLtr0; + + public double VolumeLtrStart; + public double VolumeLtrEnd; + double volumeLtrEnd1; + double volumeLtrEnd2; + + /// + /// Timestamp from the opto telegram + /// + bool lastTimestampValid; + private Int64 lastTimestamp; + private double timestampSec; + private double timestampSec0; + + public double TimestampSecStart; + public double TimestampSecEnd; + double timestampSecEnd1; + double timestampSecEnd2; private Boxes.IntBox pulses; private Boxes.IntBox refPulses; + private Boxes.DoubleBox timeSec; /// @@ -112,11 +136,6 @@ namespace TBF.BenchControl.WaterMeters.iPerl /// private SerialPort optoSerialPort; -#if USE_SEPARATE_WORKER_THREAD - private Thread workerThread; - private bool stopWorkerThread; -#endif - public WaterMeter() { @@ -132,37 +151,39 @@ namespace TBF.BenchControl.WaterMeters.iPerl log.Debug(this.ToString()); } - static bool initOnceDone; + int NrFormName(string name) + { + int len = name.Length; + if (len < 2) return 0; + + int loNr = (int)name[len - 1] - (int)'0'; + int hiNr = (int)name[len - 2] - (int)'0'; + if (hiNr < 1 || hiNr > 4) hiNr = 0; + + return 10 * hiNr + loNr; + } public void Initialize() { if (DebugLevel == Entities.DebugMode.Normal) { - if (!initOnceDone) - { - initOnceDone = true; - optoDataLogger.Fatal("------------------------------------------------------------------------"); - optoDataLogger.Fatal("Program restarted"); - } + int nr = NrFormName(Name); + optoDataLogger = LogManager.GetLogger("OptoData_" + nr.ToString()); + optoDataLogger.Fatal("------------------------------------------------------------------------"); + optoDataLogger.Fatal("Program restarted"); + /// Prepare serial port optoSerialPort = new SerialPort(string.Format("COM{0}", iPerlCfg.OptoComPortNr), - 9600, Parity.None, 8, StopBits.One); + 9600, Parity.None, 8, StopBits.One); optoSerialPort.Handshake = Handshake.None; - optoSerialPort.Open(); -#if USE_SEPARATE_WORKER_THREAD - stopWorkerThread = false; - workerThread = new Thread(Worker); - workerThread.Start(); -#endif + OpenSerialPort(); } } public void RunDeviceBefore() { -#if !USE_SEPARATE_WORKER_THREAD ReadOptoSerialPort(); -#endif } public void RunDeviceAfter() @@ -173,12 +194,8 @@ namespace TBF.BenchControl.WaterMeters.iPerl { if (DebugLevel == Entities.DebugMode.Normal) { -#if USE_SEPARATE_WORKER_THREAD - stopWorkerThread = true; - workerThread.Join(2000); -#endif - optoSerialPort.Close(); - } + CloseSerialPort(); + } } /// @@ -196,7 +213,7 @@ namespace TBF.BenchControl.WaterMeters.iPerl /// Events: Event.ReadRegisterDone, Event.Error /// /// Reference to a variable for the water meter pulses - /// Reference to a variable for the related reference flowmeter pulses + /// Reference to a variable for the related reference flowmeter pulses /// Reference to operation object instance public IOperation ReadRegisterOp(ref Boxes.IntBox pulses, ref Boxes.IntBox refPulses) { @@ -205,11 +222,40 @@ namespace TBF.BenchControl.WaterMeters.iPerl return this; } + /// + /// Events: Event.ReadRegisterDone, Event.Error + /// + /// Reference to a variable for the water meter pulses + /// Reference to a variable for the related time in seconds + /// Reference to operation object instance + public IOperation ReadRegisterOp(ref Boxes.IntBox pulses, ref Boxes.DoubleBox timeSec) + { + this.pulses = pulses; + this.timeSec = timeSec; + return this; + } + + /// + /// Events: ReadReferenceDone, Error + /// + /// Reference to a variable for the water meter pulses + /// Reference to a variable for the related time in seconds + /// Reference to a variable for the water meter pulses + /// Reference to operation object instance + public IOperation ReadRegisterOp(ref Boxes.IntBox pulses, ref Boxes.DoubleBox timeSec, ref Boxes.IntBox refPulses) + { + this.pulses = pulses; + this.timeSec = timeSec; + this.refPulses = refPulses; + return this; + } + /// /// Events: ReadReferenceDone, Error /// /// Reference to a variable for the water meter pulses - /// Reference to operation object instance + /// Reference to a variable for the water meter pulses + /// Reference to operation object instance public IOperation ReadReferenceForRegisterOp(ref Boxes.IntBox pulses, ref Boxes.IntBox refPulses) { this.pulses = pulses; @@ -221,50 +267,96 @@ namespace TBF.BenchControl.WaterMeters.iPerl /// Start this operation public void Start() { - ReadPulses(); - } + sampleNr = 0; + + volumeLtr = 0; + volumeLtr0 = 0; + timestampSec = 0; + timestampSec0 = 0; + + CloseSerialPort(); + OpenSerialPort(); + ReadPulses(); + } /// Run this operation /// eventDone public Event Run() { + sampleNr++; ReadPulses(); + if (sampleNr == 3) + { + VolumeLtrStart = volumeLtr; + TimestampSecStart = timestampSec; + } + + /// Shift data in pipelines + VolumeLtrEnd = volumeLtrEnd2; + volumeLtrEnd2 = volumeLtrEnd1; + volumeLtrEnd1 = volumeLtr; + + TimestampSecEnd = timestampSecEnd2; + timestampSecEnd2 = timestampSecEnd1; + timestampSecEnd1 = timestampSec; + return Event.ReadRegisterDone; } /// Stop this operation public void Stop() { - } + } void ReadPulses() { - pulses.Val = (int)((volumeLtr - volumeLtrStart) / (double)PulsesPerLtr + 0.5); - refPulses.Val = StateMachine.ControlBoard.EtPulses(0); + pulses.Val = (int)((volumeLtr - volumeLtr0) * (double)PulsesPerLtr + 0.5); + if (timeSec != null) timeSec.Val = timestampSec - timestampSec0; + if (refPulses != null) refPulses.Val = StateMachine.ControlBoard.EtPulses(0); } - public void Reset() - { - volumeLtrStart = volumeLtr; - } - -#if USE_SEPARATE_WORKER_THREAD - void Worker() - { - while (!stopWorkerThread) - { - Thread.Sleep(250); - if (stopWorkerThread) break; - ReadOptoSerialPort(); - } - } -#endif + bool optoSerialPortParsingEnabled; bool synchronized; bool synchronized2; string partOfTelegram; + /// Open RFID serial port and start parsing serial data + private void OpenSerialPort() + { + if (optoSerialPort != null) + { + optoSerialPort.Open(); + StartParsingOptoSerialPort(); + } + } + + /// Stop parsing serial data and close RFID serial port + private void CloseSerialPort() + { + if (optoSerialPort != null) + { + StopParsingOptoSerialPort(); + optoSerialPort.Close(); + } + } + + /// Flush internal buffers and start parsing the opto serial port data + void StartParsingOptoSerialPort() + { + synchronized = false; + synchronized2 = false; + partOfTelegram = string.Empty; + optoSerialPortParsingEnabled = true; + } + + /// Stop parsig the opto serial port data + void StopParsingOptoSerialPort() + { + optoSerialPortParsingEnabled = false; + } + /// /// 9600 Bd, 8 data bits, 1 stop bit, no parity /// @@ -279,6 +371,8 @@ namespace TBF.BenchControl.WaterMeters.iPerl /// void ReadOptoSerialPort() { + if (!optoSerialPortParsingEnabled) return; + if (DebugLevel == Entities.DebugMode.Normal || DebugLevel == Entities.DebugMode.Record) { int nrBytes = optoSerialPort.BytesToRead; @@ -290,7 +384,7 @@ namespace TBF.BenchControl.WaterMeters.iPerl string allRcvd = partOfTelegram + received; - OptoTelegram opto; + OptoTelegramRaw opto; while (true) { int pos = allRcvd.IndexOf("\r\n"); @@ -313,7 +407,7 @@ namespace TBF.BenchControl.WaterMeters.iPerl synchronized = true; } // CR+LF found and (pos >= OptoTelegram.Length - 2) - else if ((null != (opto = OptoTelegram.FromString(allRcvd.Substring(pos - OptoTelegram.Length + 2), iPerlCfg.MeterType)))) + else if (null != (opto = OptoTelegramRaw.FromString(allRcvd.Substring(pos - OptoTelegramRaw.Length + 2)))) { OptoTelegramRreceived(opto, synchronized2); synchronized2 = synchronized; @@ -341,11 +435,87 @@ namespace TBF.BenchControl.WaterMeters.iPerl } } - void OptoTelegramRreceived(OptoTelegram optoTelegram, bool async) + + void OptoTelegramRreceived(OptoTelegramRaw optoTelegram, bool async) { - volumeLtr = optoTelegram.Volume; - optoDataLogger.InfoFormat("{0}: {1}", Name, optoTelegram); - } + Int32 uncorrectedRawVolume = 0; + if (!lastVolumeRawValid) + { + lastVolumeRaw = optoTelegram.VolumeRaw; + lastVolumeRawValid = true; + } + else + { + uncorrectedRawVolume = (Int32)((lastVolumeRaw & 0x7F000000) | (optoTelegram.VolumeRaw & 0x00FFFFFF)); + if (Math.Abs(uncorrectedRawVolume - lastVolumeRaw) <= 0x007FFFFF) + { + lastVolumeRaw = uncorrectedRawVolume; + } + else if (Math.Abs(uncorrectedRawVolume + 0x01000000 - lastVolumeRaw) <= 0x007FFFFF) + { + lastVolumeRaw = uncorrectedRawVolume + 0x01000000; + } + else if (Math.Abs(uncorrectedRawVolume - 0x01000000 - lastVolumeRaw) <= 0x007FFFFF) + { + lastVolumeRaw = uncorrectedRawVolume - 0x01000000; + } + else + { + optoDataLogger.Info("Fatal error"); + } + } + + + Int64 uncorrectedTimestamp = 0; + if (!lastTimestampValid) + { + lastTimestamp = optoTelegram.Timestamp; + lastTimestampValid = true; + } + else + { + uncorrectedTimestamp = (Int64)((lastTimestamp & 0x7FFFFFFF00000000) | (optoTelegram.Timestamp & 0xFFFFFFFF)); + if (Math.Abs(uncorrectedTimestamp - lastTimestamp) <= 0x7FFFFFFF) + { + lastTimestamp = uncorrectedTimestamp; + } + else if (Math.Abs(uncorrectedTimestamp + 0x100000000 - lastTimestamp) <= 0x7FFFFFFF) + { + lastTimestamp = uncorrectedTimestamp + 0x100000000; + } + else if (Math.Abs(uncorrectedTimestamp - 0x100000000 - lastTimestamp) <= 0x7FFFFFFF) + { + lastTimestamp = uncorrectedTimestamp - 0x100000000; + } + else + { + optoDataLogger.Info("Fatal error2"); + } + } + + if (volumeLtr == 0 && volumeLtr0 == 0) + { + volumeLtr = (double)lastVolumeRaw * ScalingFactor() / 16000.0; + volumeLtr0 = volumeLtr; + } + else + { + volumeLtr = (double)lastVolumeRaw * ScalingFactor() / 16000.0; + } + + if (timestampSec == 0 && timestampSec0 == 0) + { + timestampSec = (double)lastTimestamp / 8192.0; + timestampSec0 = timestampSec; + } + else + { + timestampSec = (double)lastTimestamp / 8192.0; + } + + optoDataLogger.InfoFormat("{0} {1} {2} ltr {3} {4}", optoTelegram, lastTimestamp, lastVolumeRaw.ToString("X8"), timestampSec.ToString("F1"), volumeLtr.ToString("F3")); + } + /// /// Called from the state machine when a test is selected and UI needs to be updated. @@ -359,5 +529,56 @@ namespace TBF.BenchControl.WaterMeters.iPerl public event EventHandler OptoReceivedHandler; - } + public static double UnitVolume(VolumeUnits units) + { + switch (units) + { + default: + case VolumeUnits.m3: return 1000.0; /// liter + case VolumeUnits.UK_gallon: return 4.546092; /// liter + case VolumeUnits.US_gallon: return 3.785412; // liter + } + } + + public double ScalingFactor() + { + if ((iPerlCfg.MeterType == MeterType.AutoDetect) && (CalibrationStruct != null)) + { + return WaterMeter.ScalingFactor(CalibrationStruct.MeterType); + } + else if (iPerlCfg.MeterType != MeterType.AutoDetect) + { + return WaterMeter.ScalingFactor(iPerlCfg.MeterType); + } + else + { + return WaterMeter.ScalingFactor(MeterType.DN20); + } + } + + /// + /// Scaling factor: + /// 0, 1 (DN15, Coax) . . . . 1 + /// 2 (DN20) . . . . . . . . 2 + /// 3 (DN25) . . . . . . . . 4 + /// 4, 5 (DN26, DN32) . . . . 8 + /// 6 (DN40) . . . . . . . . 16 + /// + /// MeterType (0..6) + /// Scaling factor + public static double ScalingFactor(MeterType meterType) + { + switch (meterType) + { + default: + case MeterType.DN15: + case MeterType.CoaxManifold: return 1.0; + case MeterType.DN20: return 2.0; + case MeterType.DN25: return 4.0; + case MeterType.DN26: + case MeterType.DN32: return 8.0; + case MeterType.DN40: return 16.0; + } + } + } } diff --git a/TestBenchFramework/LocalSettings.cs b/TestBenchFramework/LocalSettings.cs index 4a91fc3f3..825a98342 100644 --- a/TestBenchFramework/LocalSettings.cs +++ b/TestBenchFramework/LocalSettings.cs @@ -69,6 +69,10 @@ namespace TBF public int PathsDlgWidth; public int PathsDlgHeight; + /// iPerlCommunicationsForm + public int iPerlCommunicationsFormLeft; + public int iPerlCommunicationsFormTop; + [XmlArrayAttribute("FeedingColumnWidths")] public int[] FeedingColumnWidths; [XmlIgnore] diff --git a/TestBenchFramework/Properties/AssemblyInfo.cs b/TestBenchFramework/Properties/AssemblyInfo.cs index d58c6d29d..7a59dabbe 100644 --- a/TestBenchFramework/Properties/AssemblyInfo.cs +++ b/TestBenchFramework/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("1.5.82.1")] -[assembly: AssemblyFileVersion("1.5.82.1")] +[assembly: AssemblyVersion("1.5.84.1")] +[assembly: AssemblyFileVersion("1.5.84.1")]