From d39c71c7e72eec902f22db09ed69ef40ef68c98b Mon Sep 17 00:00:00 2001 From: Thomas Wiedebusch Date: Wed, 11 Feb 2026 09:53:00 +0100 Subject: [PATCH] FM2014TestBench: - initial setup to test multiple FM2014 - 14.Step --- .../FM2014/FM2014Core/FM2014.cs | 436 ++++++++++-------- .../Ui/Fm2014sTest/FM2014TestBenchWindow.xaml | 10 +- .../Fm2014sTest/FM2014TestBenchWindow.xaml.cs | 179 ++++--- 3 files changed, 354 insertions(+), 271 deletions(-) diff --git a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs index 2331e130..9a13a498 100644 --- a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs +++ b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs @@ -387,7 +387,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core public UInt16 RefPulsesRequired { get => _refPulsesRequired; - set + private set { // Check limits and equality if (value < TIME_MEASUREMENT_INPUT_MIN_pulses || @@ -405,7 +405,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core public UInt16 DutPulsesRequired { get => _dutPulsesRequired; - set + private set { // Check limits and equality if (value < TIME_MEASUREMENT_INPUT_MIN_pulses || @@ -475,46 +475,46 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// public Double DutTimeMeasured_s { get; private set; } - private UInt32 _ref_pulse_per_cm; + private UInt32 _refPulses_per_cm; /// /// Reference pulses per cubic-meter /// - public UInt32 Ref_pulse_per_cm + public UInt32 RefPulses_per_cm { - get => _ref_pulse_per_cm; + get => _refPulses_per_cm; set { // Check limits and equality if (value < PULSES_PER_CM_REGULATION_SETUP_MIN || value > REF_PULSES_PER_CM_REGULATION_INPUT_MAX || - value == _ref_pulse_per_cm) + value == _refPulses_per_cm) return; - _ref_pulse_per_cm = value; - if (_dut_pulse_per_cm != 0 && _ref_pulse_per_cm != 0) - RefToDutScale_norm = Math.Round((Double)_ref_pulse_per_cm / _dut_pulse_per_cm, 5); + _refPulses_per_cm = value; + if (_dutPulses_per_cm != 0 && _refPulses_per_cm != 0) + RefToDutScale_norm = Math.Round((Double)_refPulses_per_cm / _dutPulses_per_cm, 5); } } - private UInt16 _dut_pulse_per_cm; + private UInt16 _dutPulses_per_cm; /// /// Device under test pulses per cubic-meter /// - public UInt16 Dut_pulse_per_cm + public UInt16 DutPulses_per_cm { - get => _dut_pulse_per_cm; - set + get => _dutPulses_per_cm; + private set { // Check limits and equality, the DUT max input is 9999 as this will be // directly stored to FM2014'V' - 'DUT pulses per volume' if (value < PULSES_PER_CM_REGULATION_SETUP_MIN || value > PULSES_PER_CM_REGULATION_SETUP_MAX || - value == _dut_pulse_per_cm) + value == _dutPulses_per_cm) return; - _dut_pulse_per_cm = value; - if (_dut_pulse_per_cm != 0 && _ref_pulse_per_cm != 0) - RefToDutScale_norm = Math.Round((Double)_ref_pulse_per_cm / _dut_pulse_per_cm, 5); + _dutPulses_per_cm = value; + if (_dutPulses_per_cm != 0 && _refPulses_per_cm != 0) + RefToDutScale_norm = Math.Round((Double)_refPulses_per_cm / _dutPulses_per_cm, 5); } } @@ -570,20 +570,20 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } } - private Byte _fm2014CurrentOutputAttenuation = 3; + private Byte _currentOutputAttenuation = 3; /// /// Filter value to attenuate the velocity of the current output on the tolerance display. /// This value will be sent to the FM2014 /// - public Byte FM2014CurrentOutputAttenuation + public Byte CurrentOutputAttenuation { - get => _fm2014CurrentOutputAttenuation; - set + get => _currentOutputAttenuation; + private set { if (value < ATTENUATION_MIN || value > ATTENUATION_MAX) return; - _fm2014CurrentOutputAttenuation = value; + _currentOutputAttenuation = value; } } @@ -594,7 +594,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core public UInt16 DoublePulseDeadtime_ms { get => _doublePulseDeadtime_ms; - set + private set { if (value > DOUBLE_PULSE_DEADTIME_MAX_ms) return; @@ -669,6 +669,11 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// public Boolean MeasurementIsReady { get; private set; } + /// + /// The FM2014 has a misfunction + /// + public Boolean ErrorIsDetected { get; private set; } + /// /// FM2014 application firmware version. /// @@ -693,18 +698,9 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// - It is a broadcast command which will reset all connected devices! /// /// - /// + /// /// - Initial. /// - /// - /// - Delayed reset to allow other tasks to finish. - /// - /// - /// - Support for multiple FM2014s. - /// - /// - /// - Statics. - /// public static Boolean ResetHardwareAllDevices() { if (SharedCyclicMeasSequ == CyclicMeasSequ.IDLE) @@ -842,7 +838,11 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// - REF counter, /// - DUT counter, /// - REF and DUT counters together using the synchronized backup. - /// - Each FM2014 can use a different REF and/or DUT setting as the REF is parallel for all FM2014s. + /// - If REF and DUT pulse counters are on the cyclic sequence: + /// - 'q' synchronized backup of both pulse counters, + /// - 'l' read REF backup pulses, + /// - 'u' read DUT backup pulses + /// will be used. /// Preconditions: /// - The has to be executed in advance. /// - REF and/or DUT counter have to be activated @@ -853,29 +853,15 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// Exit: /// - Set to false. /// + /// + /// /// true if initialization successfully executed or /// marks the already started cyclic requests /// for all registered FM2014s - /// + /// /// - Initial. /// - /// - /// - If REF and DUT pulse counters are on the cyclic sequence: - /// - 'q' synchronized backup of both pulse counters, - /// - 'l' read REF backup pulses, - /// - 'u' read DUT backup pulses - /// will be used. - /// - /// - /// - Support for multiple FM2014s. - /// - /// - /// - If any FM2014 has REF and DUT pulse counter on then use for ALL the synchronized readout. - /// - /// - /// - Static. - /// - public static Boolean PulseCounterMeasurement() + public static Boolean PulseCounterMeasurement(Boolean refPulseCtrOn, Boolean dutPulseCtrOn) { // If the cyclic task has already been started everything is fine if (SharedCyclicMeasSequ == CyclicMeasSequ.PULSE_CTR) @@ -1026,7 +1012,8 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } /// - /// The regulation measurement compares the DUT to REF tolerance for all FM2014s which are connected and logged in. + /// The regulation measurement compares the DUT to REF tolerance for all FM2014s which are + /// connected and logged in. /// /// ATTENTION: /// The settings from the first listed FM2014 will be used for ALL FM2014s! @@ -1034,9 +1021,6 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// /// Preconditions: /// - The has to be executed in advance, - /// - The REF pulses per cubic meter has to be preset, - /// - The DUT pulses per cubic meter has to be preset, - /// - The Scale for REF to DUT pulses has to be preset. /// Initial setup: /// - Setup double impulse deadtime, /// - Setup damping to attenuate the result, @@ -1044,22 +1028,21 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// - Setup REF pulse counting mode to get REF pulses for flow rate. /// Cyclic: /// - Request damped or undamped tolerance, - /// - Request REF pulse counter value and uses to calculate + /// - Request REF pulse counter value and uses to calculate /// the 'Flow rate'. /// Exit: /// - Set to false. /// + /// + /// + /// + /// /// - /// + /// /// - Initial. /// - /// - /// - Support for multiple FM2014s. - /// - /// - /// - Static. - /// - public static Boolean RegulationMeasurement() + public static Boolean RegulationMeasurement(UInt32 refPulses_per_cm, UInt16 dutPulses_per_cm, + UInt16 doublePulseDeadtime_ms, Byte currentOutputAttenuation) { // If the cyclic task has already been started everything is fine if (SharedCyclicMeasSequ == CyclicMeasSequ.REGULATION) @@ -1069,22 +1052,36 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE) return false; + // Initially, check if any device is connected and logged in, if not => exit var firstActiveFm2014 = GetFirstConnectedAndLoggedInFm2014(); if (firstActiveFm2014 == null) return false; + // Publish setting to all connected and logged in FM2014s as those will be delivered + // for all via broadcast + foreach (var fm2014 in RegisteredFm2014s.Where(fm2014 => fm2014.IsLoggedOn)) + { + fm2014.RefPulses_per_cm = refPulses_per_cm; + fm2014.DutPulses_per_cm = dutPulses_per_cm; + fm2014.DoublePulseDeadtime_ms = doublePulseDeadtime_ms; + fm2014.CurrentOutputAttenuation = currentOutputAttenuation; + // Remove the measurement ready lock used for cyclic request + fm2014.MeasurementIsReady = false; + // Remove error marker + fm2014.ErrorIsDetected = false; + } + // Check if regulation can be done - if (firstActiveFm2014.Ref_pulse_per_cm < PULSES_PER_CM_REGULATION_SETUP_MIN || - firstActiveFm2014.Dut_pulse_per_cm < PULSES_PER_CM_REGULATION_SETUP_MIN || - firstActiveFm2014.Ref_pulse_per_cm > PULSES_PER_CM_REGULATION_SETUP_MAX || - firstActiveFm2014.Dut_pulse_per_cm > PULSES_PER_CM_REGULATION_SETUP_MAX || + if (refPulses_per_cm < PULSES_PER_CM_REGULATION_SETUP_MIN || + dutPulses_per_cm < PULSES_PER_CM_REGULATION_SETUP_MIN || + refPulses_per_cm > REF_PULSES_PER_CM_REGULATION_INPUT_MAX || + dutPulses_per_cm > PULSES_PER_CM_REGULATION_SETUP_MAX || firstActiveFm2014.RefToDutScale_norm < REF_TO_DUT_SCALE_MIN || firstActiveFm2014.RefToDutScale_norm > REF_TO_DUT_SCALE_MAX) { return false; } - var cmdName = CmdName.CMD_NA; var measurementInfo = Resources.StrMeasMsgRegulation; // Prepare regulation measurement @@ -1097,7 +1094,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } cmdName = CmdName.CMD_MEAS_SET_ATTN; - if (!Write(cmdName, firstActiveFm2014, firstActiveFm2014.FM2014CurrentOutputAttenuation)) + if (!Write(cmdName, firstActiveFm2014, firstActiveFm2014.CurrentOutputAttenuation)) { return false; } @@ -1180,7 +1177,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core specificInfoObj: response)); // Convert to m³/h (3600 s/h) based on REF pulse rate - fm2014.RefFlowRate_cm_per_h = 3600.0 / (period * TMR_RESOLUTION_s) / fm2014.Ref_pulse_per_cm; + fm2014.RefFlowRate_cm_per_h = 3600.0 / (period * TMR_RESOLUTION_s) / fm2014.RefPulses_per_cm; // Publish the calculated flow rate [m³/h] cmdName = CmdName.CMD_CAL_FLOW_REF_PERIOD; info = GetCmdInfo(cmdName); @@ -1222,7 +1219,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core specificInfoObj: response)); // Convert to m³/h (3600 s/h) based on DUT pulse rate - fm2014.DutFlowRate_cm_per_h = 3600.0 / (period * TMR_RESOLUTION_s) / fm2014.Dut_pulse_per_cm; + fm2014.DutFlowRate_cm_per_h = 3600.0 / (period * TMR_RESOLUTION_s) / fm2014.DutPulses_per_cm; // Publish the calculated flow rate [m³/h] cmdName = CmdName.CMD_CAL_FLOW_DUT_PERIOD; info = GetCmdInfo(cmdName); @@ -1252,7 +1249,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core specificInfoObj: response)); // Convert to m³/h (3600 s/h) and save the value - fm2014.RefFlowRate_cm_per_h = 3600.0 * refFrequency / fm2014.Ref_pulse_per_cm; + fm2014.RefFlowRate_cm_per_h = 3600.0 * refFrequency / fm2014.RefPulses_per_cm; // Publish the calculated flow rate [m³/h] cmdName = CmdName.CMD_CAL_FLOW_REF_FREQU; info = GetCmdInfo(cmdName); @@ -1279,40 +1276,41 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } /// - /// The calibration measurement compares the DUT to REF tolerance for all FM2014s which are connected and logged in. + /// The pulse time measurement counts the timer ticks for the REF and/or DUT for all connected and + /// logged in FM2014. + /// + /// It supports: + /// - REF time measurement alone, + /// - DUT time measurement alone, + /// - REF and DUT time measurement synchronized to the rising edge of first impulse after setup of + /// required DUT pulses. /// /// ATTENTION: - /// The settings from the first listed FM2014 will be used for ALL FM2014s! + /// The settings will be used for ALL FM2014s! /// These settings will be delivered via broadcast to all connected and logged in devices! /// /// Preconditions: /// - The has to be executed in advance, - /// - The REF pulses to count has to be preset, - /// - The DUT pulses to count has to be preset, - /// - Setup double impulse deadtime using the whichautomatically - /// calculates the and . /// Initial setup: /// - Setup double pulse deadtime, - /// - Setup REF pulses to count, - /// - Setup DUT pulses to count. + /// - Setup REF pulses required to count down and measure the time of it, + /// - Setup DUT pulses required to count down and measure the time of it. /// Cyclic: - /// - Request damped or undamped tolerance, - /// - Request REF pulse counter value and uses to calculate - /// the 'Flow rate'. + /// - Request remaining pulses for REF and DUT. + /// Final: + /// - Read out timer ticks for REF and/or DUT and convert it to a time in seconds. /// Exit: - /// - Set to false. + /// - Set to Idle. + /// null if not active, limited by number format to 65535 + /// null if not active, limited by number format to 65535 + /// 0 if double impulse deadtime detection is off /// /// - /// + /// /// - Initial. /// - /// - /// - Support for multiple FM2014s. - /// - /// - /// - Static. - /// - public static Boolean CalibrationMeasurement() + public static Boolean PulseTimeMeasurement(UInt16? refPulsesRequired = null, UInt16? dutPulsesRequired = null, + UInt16 doublePulseDeadtime_ms = 0) { // If the cyclic task has already been started everything is fine if (SharedCyclicMeasSequ == CyclicMeasSequ.CALIBRATION) @@ -1322,25 +1320,41 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE) return false; + // Initially, check if any device is connected and logged in, if not => exit var firstActiveFm2014 = GetFirstConnectedAndLoggedInFm2014(); if (firstActiveFm2014 == null) return false; // Check if regulation can be done - if (firstActiveFm2014.RefPulsesRequired < TIME_MEASUREMENT_INPUT_MIN_pulses || - firstActiveFm2014.DutPulsesRequired < TIME_MEASUREMENT_INPUT_MIN_pulses) + if ((refPulsesRequired == null && dutPulsesRequired == null) || + refPulsesRequired < TIME_MEASUREMENT_INPUT_MIN_pulses || + dutPulsesRequired < TIME_MEASUREMENT_INPUT_MIN_pulses || + doublePulseDeadtime_ms > DOUBLE_PULSE_DEADTIME_MAX_ms) { return false; } + // Publish setting to all connected and logged in FM2014s as those will be delivered + // for all via broadcast + foreach (var fm2014 in RegisteredFm2014s.Where(fm2014 => fm2014.IsLoggedOn)) + { + fm2014.RefPulsesRequired = refPulsesRequired ?? 0; + fm2014.DutPulsesRequired = dutPulsesRequired ?? 0; + fm2014.DoublePulseDeadtime_ms = doublePulseDeadtime_ms; + // Remove the measurement ready lock used for cyclic request + fm2014.MeasurementIsReady = false; + // Remove error marker + fm2014.ErrorIsDetected = false; + } + var cmdName = CmdName.CMD_NA; var measurementInfo = Resources.StrMeasMsgCalibration; - // Prepare calibration measurement + // Prepare pulse time measurement try { - // Check if double pulse deadtime has been set - if (Math.Abs(DOUBLE_PULSE_DEADTIME_MIN_ms - firstActiveFm2014.DoublePulseDeadtime_ms) < 0.9) + // Check if double pulse deadtime has been set or si switched off + if (DOUBLE_PULSE_DEADTIME_MIN_ms == firstActiveFm2014.DoublePulseDeadtime_ms) { InitActualProcessProgress(3, broadcast: true); // This is a command without parameter @@ -1365,15 +1379,22 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } } - cmdName = CmdName.CMD_REF_SET_PLS; - if (!Write(cmdName, firstActiveFm2014, firstActiveFm2014.RefPulsesRequired, true)) + if (firstActiveFm2014.RefPulsesRequired != 0) { - return false; + cmdName = CmdName.CMD_REF_SET_PLS; + if (!Write(cmdName, firstActiveFm2014, firstActiveFm2014.RefPulsesRequired, true)) + { + return false; + } } - cmdName = CmdName.CMD_DUT_SET_PLS; - if (!Write(cmdName, firstActiveFm2014, firstActiveFm2014.DutPulsesRequired, true)) + + if (firstActiveFm2014.DutPulsesRequired != 0) { - return false; + cmdName = CmdName.CMD_DUT_SET_PLS; + if (!Write(cmdName, firstActiveFm2014, firstActiveFm2014.DutPulsesRequired, true)) + { + return false; + } } } catch (Exception e) @@ -1389,14 +1410,12 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core { // Mark calibration measurement as active SharedCyclicMeasSequ = CyclicMeasSequ.CALIBRATION; - InitActualProcessProgress(firstActiveFm2014.RefPulsesRequired, disableWriteReadIncrease: true); - // Remove all measurement ready markers as those are taken to lock the repeated readout of - // the measurement results - foreach (var fm2014 in RegisteredFm2014s.Where(fm2014 => fm2014.IsLoggedOn)) - { - fm2014.MeasurementIsReady = false; - } + // Set up the progress maximal counter value base on required pulses for REF or DUT + InitActualProcessProgress( + firstActiveFm2014.RefPulsesRequired != 0 + ? firstActiveFm2014.RefPulsesRequired + : firstActiveFm2014.DutPulsesRequired, disableWriteReadIncrease: true); do { @@ -1404,35 +1423,53 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core { try { - ActualProcessProgress = firstActiveFm2014.RefPulsesRequired - firstActiveFm2014.RefPulsesRemaining; - - cmdName = CmdName.CMD_REF_GET_PLS_RMN; - var info = GetCmdInfo(cmdName); + String info; String responseStr; - if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014)) + + // Read the remaining REF pulses if required + if (firstActiveFm2014.RefPulsesRequired != 0) { - if (Read(cmdName, fm2014, out responseStr) && - ushort.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var pulses)) + // Feed the progress counter + ActualProcessProgress = firstActiveFm2014.RefPulsesRequired - + firstActiveFm2014.RefPulsesRemaining; + cmdName = CmdName.CMD_REF_GET_PLS_RMN; + info = GetCmdInfo(cmdName); + if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014)) { - fm2014.RefPulsesRemaining = pulses; - var response = new CmdResponse(cmdName, info, pulses); - PublishResponse(fm2014, new ProcessExecEventArgs("", - actualProcessPercent: ActualProcessProgress_percent, - actualProcessMessage: measurementInfo, specificInfoObj: response)); + if (Read(cmdName, fm2014, out responseStr) && + ushort.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), + out var pulses)) + { + fm2014.RefPulsesRemaining = pulses; + var response = new CmdResponse(cmdName, info, pulses); + PublishResponse(fm2014, new ProcessExecEventArgs("", + actualProcessPercent: ActualProcessProgress_percent, + actualProcessMessage: measurementInfo, specificInfoObj: response)); + } } } - cmdName = CmdName.CMD_DUT_GET_PLS_RMN; - info = GetCmdInfo(cmdName); - if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014)) + // Read the remaining DUT pulses if required + if (firstActiveFm2014.DutPulsesRequired != 0) { - if (Read(cmdName, fm2014, out responseStr) && - ushort.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var pulses)) + // Feed the progress counter but only if not done for REF pulses + if (firstActiveFm2014.RefPulsesRequired == 0) + ActualProcessProgress = firstActiveFm2014.DutPulsesRequired - + firstActiveFm2014.DutPulsesRemaining; + cmdName = CmdName.CMD_DUT_GET_PLS_RMN; + info = GetCmdInfo(cmdName); + if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014)) { - fm2014.DutPulsesRemaining = pulses; - var response = new CmdResponse(cmdName, info, pulses); - PublishResponse(fm2014, new ProcessExecEventArgs("", actualProcessMessage: measurementInfo, - specificInfoObj: response)); + if (Read(cmdName, fm2014, out responseStr) && + ushort.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), + out var pulses)) + { + fm2014.DutPulsesRemaining = pulses; + var response = new CmdResponse(cmdName, info, pulses); + PublishResponse(fm2014, new ProcessExecEventArgs("", + actualProcessMessage: measurementInfo, + specificInfoObj: response)); + } } } @@ -1441,73 +1478,88 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core if (fm2014.RefPulsesRemaining == 0 && fm2014.DutPulsesRemaining == 0) { var retVal = true; - // Read out the result - cmdName = CmdName.CMD_REF_GET_TMR; - info = GetCmdInfo(cmdName); - if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014)) + + // Read the REF timer ticks for the counted pulses + if (firstActiveFm2014.RefPulsesRequired != 0) { - if (Read(cmdName, fm2014, out responseStr) && - uint.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var timerTicks)) + cmdName = CmdName.CMD_REF_GET_TMR; + info = GetCmdInfo(cmdName); + if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014)) { - // Is converting to a real time in seconds - fm2014.RefTimerTicksMeasured = timerTicks; - var response = new CmdResponse(cmdName, info, doubleValue: fm2014.RefTimeMeasured_s, - unit: Units.GetInfo(Units.Name.TIME_s)); - PublishResponse(fm2014, new ProcessExecEventArgs("", actualProcessMessage: measurementInfo, - specificInfoObj: response)); + if (Read(cmdName, fm2014, out responseStr) && + uint.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), + out var timerTicks)) + { + // Is converting to a real time in seconds + fm2014.RefTimerTicksMeasured = timerTicks; + var response = new CmdResponse(cmdName, info, doubleValue: fm2014.RefTimeMeasured_s, + unit: Units.GetInfo(Units.Name.TIME_s)); + PublishResponse(fm2014, new ProcessExecEventArgs("", + actualProcessMessage: measurementInfo, + specificInfoObj: response)); + } + else + { + retVal = false; + } } else { retVal = false; } } - else + + // Read the DUT timer ticks for the counted pulses + if (firstActiveFm2014.DutPulsesRequired != 0) { - retVal = false; + cmdName = CmdName.CMD_DUT_GET_TMR; + info = GetCmdInfo(cmdName); + if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014)) + { + if (Read(cmdName, fm2014, out responseStr) && + uint.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), + out var timerTicks)) + { + // Is converting to a real time in seconds + fm2014.DutTimerTicksMeasured = timerTicks; + var response = new CmdResponse(cmdName, info, doubleValue: fm2014.DutTimeMeasured_s, + unit: Units.GetInfo(Units.Name.TIME_s)); + PublishResponse(fm2014, new ProcessExecEventArgs("", + actualProcessMessage: measurementInfo, + specificInfoObj: response)); + } + else + { + retVal = false; + } + } + else + { + retVal = false; + } } - cmdName = CmdName.CMD_DUT_GET_TMR; - info = GetCmdInfo(cmdName); - if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014)) + // Calculate the DUT to REF tolerance if both timer had been active + if (firstActiveFm2014.RefPulsesRequired != 0 && firstActiveFm2014.DutPulsesRequired != 0) { - if (Read(cmdName, fm2014, out responseStr) && - uint.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), - out var timerTicks)) + cmdName = CmdName.CMD_CAL_DUT_TO_REF_TOL; + info = GetCmdInfo(cmdName); + // Is converting to a real time in seconds + if (fm2014.RefTimeMeasured_s > 0.0) { - // Is converting to a real time in seconds - fm2014.DutTimerTicksMeasured = timerTicks; - var response = new CmdResponse(cmdName, info, doubleValue: fm2014.DutTimeMeasured_s, - unit: Units.GetInfo(Units.Name.TIME_s)); + fm2014.DutToRefToleranceMeasured_percent = + (1.0 - fm2014.DutTimeMeasured_s / fm2014.RefTimeMeasured_s) * 100.0; + var response = new CmdResponse(cmdName, info, + doubleValue: fm2014.DutToRefToleranceMeasured_percent, + unit: Units.GetInfo(Units.Name.PERCENT)); PublishResponse(fm2014, new ProcessExecEventArgs("", actualProcessMessage: measurementInfo, specificInfoObj: response)); } - else - { - retVal = false; - } - } - else - { - retVal = false; - } - cmdName = CmdName.CMD_CAL_DUT_TO_REF_TOL; - info = GetCmdInfo(cmdName); - // Is converting to a real time in seconds - if (fm2014.RefTimeMeasured_s > 0.0) - { - fm2014.DutToRefToleranceMeasured_percent = - (1.0 - fm2014.DutTimeMeasured_s / fm2014.RefTimeMeasured_s) * 100.0; - var response = new CmdResponse(cmdName, info, - doubleValue: fm2014.DutToRefToleranceMeasured_percent, - unit: Units.GetInfo(Units.Name.PERCENT)); - PublishResponse(fm2014, new ProcessExecEventArgs("", - actualProcessMessage: measurementInfo, - specificInfoObj: response)); } - if (retVal) - fm2014.MeasurementIsReady = true; + // Exclude this FM2014 from further looping as the measurement is completed + if (retVal) fm2014.MeasurementIsReady = true; } } catch (Exception e) @@ -1520,7 +1572,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core // Check all remaining DUT and REF pulses are counted on all connected devices and finalize process by // reading out all results - //TODO THW rework to skip device which are not logged in and logout if timeout + //TODO THW rework to take timeout for unresponsive device into account if (RegisteredFm2014s.All(fm2014 => fm2014.RefPulsesRemaining == 0 && fm2014.DutPulsesRemaining == 0)) { @@ -1877,14 +1929,14 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core { // Set to zero if it doesn't fit to the limit which can be stored as indicator for invalid value // which should be recovered by 'Ref_pulses_per_cm = Dut_pulses_per_cm * RefToDutScale_norm' - var limitedRefPulsesPerCm = Ref_pulse_per_cm <= PULSES_PER_CM_REGULATION_SETUP_MAX ? - Ref_pulse_per_cm : REF_PULSES_PER_VOLUME_INVALID_MARKER; + var limitedRefPulsesPerCm = RefPulses_per_cm <= PULSES_PER_CM_REGULATION_SETUP_MAX ? + RefPulses_per_cm : REF_PULSES_PER_VOLUME_INVALID_MARKER; var retVal = Write(cmdName, this, (UInt16)limitedRefPulsesPerCm); if (retVal) { cmdName = CmdName.CMD_DUT_LPP_SCALE; - retVal = Write(cmdName, this, Dut_pulse_per_cm); + retVal = Write(cmdName, this, DutPulses_per_cm); } if (retVal) @@ -1897,7 +1949,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core if (retVal) { cmdName = CmdName.CMD_MEAS_SET_ATTN; - retVal = Write(cmdName, this, FM2014CurrentOutputAttenuation); + retVal = Write(cmdName, this, CurrentOutputAttenuation); } if (retVal) @@ -1983,8 +2035,8 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core { cmdName = CmdName.CMD_MEAS_SET_ATTN; var info = GetCmdInfo(cmdName); - FM2014CurrentOutputAttenuation = attenuation; - var response = new CmdResponse(cmdName, info, FM2014CurrentOutputAttenuation); + CurrentOutputAttenuation = attenuation; + var response = new CmdResponse(cmdName, info, CurrentOutputAttenuation); PublishResponse(this, new ProcessExecEventArgs("", actualProcessMessage: measurementInfoStr, specificInfoObj: response)); } @@ -2012,8 +2064,8 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core { cmdName = CmdName.CMD_DUT_LPP_SCALE; var info = GetCmdInfo(cmdName); - Dut_pulse_per_cm = value; - var response = new CmdResponse(cmdName, info, Dut_pulse_per_cm); + DutPulses_per_cm = value; + var response = new CmdResponse(cmdName, info, DutPulses_per_cm); PublishResponse(this, new ProcessExecEventArgs("", actualProcessMessage: measurementInfoStr, specificInfoObj: response)); @@ -2021,8 +2073,8 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core cmdName = CmdName.CMD_REF_LPP_SCALE; info = GetCmdInfo(cmdName); // Calculate REF pulses per cubic meter - Ref_pulse_per_cm = (UInt32)Math.Round(Dut_pulse_per_cm * RefToDutScale_norm, 1); - response = new CmdResponse(cmdName, info, (Int32)Ref_pulse_per_cm); + RefPulses_per_cm = (UInt32)Math.Round(DutPulses_per_cm * RefToDutScale_norm, 1); + response = new CmdResponse(cmdName, info, (Int32)RefPulses_per_cm); PublishResponse(this, new ProcessExecEventArgs("", actualProcessMessage: measurementInfoStr, specificInfoObj: response)); diff --git a/FM2014TestApp/Ui/Fm2014sTest/FM2014TestBenchWindow.xaml b/FM2014TestApp/Ui/Fm2014sTest/FM2014TestBenchWindow.xaml index 546066c1..7576ceb2 100644 --- a/FM2014TestApp/Ui/Fm2014sTest/FM2014TestBenchWindow.xaml +++ b/FM2014TestApp/Ui/Fm2014sTest/FM2014TestBenchWindow.xaml @@ -326,11 +326,11 @@ -