From 45fbf4f85422798196fa3022ded47506c55b8a14 Mon Sep 17 00:00:00 2001 From: Thomas Wiedebusch Date: Sat, 7 Feb 2026 15:28:46 +0100 Subject: [PATCH] FM2014TestBench: - initial setup to test multiple FM2014 - 8.Step --- .../FM2014/FM2014Core/Consts/FM2014CmdDef.cs | 10 +- .../FM2014/FM2014Core/FM2014.cs | 376 +++++++++++++++--- .../Properties/Resources.Designer.cs | 26 +- .../FM2014Core/Properties/Resources.de.resx | 10 +- .../FM2014Core/Properties/Resources.resx | 14 +- .../FrmFm2014TestApp.cs | 4 +- .../Ui/Fm2014sTest/FM2014TestBenchWindow.xaml | 72 +++- .../Fm2014sTest/FM2014TestBenchWindow.xaml.cs | 182 +++++++-- .../Properties/Resources.Designer.cs | 146 +++++-- .../Fm2014sTest/Properties/Resources.de.resx | 58 ++- .../Ui/Fm2014sTest/Properties/Resources.resx | 58 ++- 11 files changed, 784 insertions(+), 172 deletions(-) diff --git a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Consts/FM2014CmdDef.cs b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Consts/FM2014CmdDef.cs index c51a716b..3aa19e6a 100644 --- a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Consts/FM2014CmdDef.cs +++ b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Consts/FM2014CmdDef.cs @@ -237,6 +237,11 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co /// CMD_GET_REF_FREQU, + /// + /// Calculate DUT to REF tolerance based on timer values + /// + CMD_CAL_DUT_TO_REF_TOL, + /// /// Calculate frequency from REF period /// @@ -309,9 +314,9 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co REGULATION, /// - /// Time measurement ongoing + /// Calibration measurement ongoing /// - TIME + CALIBRATION } /// @@ -551,6 +556,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co // Measurement result request new Cmd(CmdName.CMD_DUT_GET_TMR, "X", CmdType.INDIVIDUAL, Resources.StrCmdMsgDutGetTmr), new Cmd(CmdName.CMD_REF_GET_TMR, "Y", CmdType.INDIVIDUAL, Resources.StrCmdMsgRefGetTmr), + new Cmd(CmdName.CMD_CAL_DUT_TO_REF_TOL, "", CmdType.INDIVIDUAL, Resources.StrCalDutToRefTol), new Cmd(CmdName.CMD_GET_UDTLC, "Z", CmdType.INDIVIDUAL, Resources.StrCmdMsgGetUdtlc), new Cmd(CmdName.CMD_GET_DTLC, "z", CmdType.INDIVIDUAL, Resources.StrCmdMsgGetDtlc), new Cmd(CmdName.CMD_GET_REF_PERIOD, UNICODE_DLE, CmdType.INDIVIDUAL, Resources.StrCmdMsgGetRefPeriod), diff --git a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs index bd730fec..2878c1bf 100644 --- a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs +++ b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs @@ -88,7 +88,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// Default tolerance if not properly setup. /// public const Int32 STANDARD_NOMINAL_TOLERANCE_INPUT_percent = 3; - + /// /// Default tolerance if not properly setup. /// @@ -98,69 +98,69 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// Standard tolerance (nominal 3 %) multiplicator for calculation of value based on feedback from FM2014 /// (+/- 255 digits). /// - public const Double STANDARD_TOLERANCE_VALUE_percent = 3.3; - + private const Double STANDARD_TOLERANCE_VALUE_percent = 3.3; + /// /// Extended tolerance (nominal 5 %) multiplicator for calculation of value based on feedback from FM2014 /// (+/- 255 digits). /// - public const Double EXTENDED_TOLERANCE_VALUE_percent = 5.5; + private const Double EXTENDED_TOLERANCE_VALUE_percent = 5.5; /// /// Resolution of tolerance raw value feedback from FM2014 (+/- 255 digits). /// - public const Double RESOLUTION_TOLERANCE_RAW_VALUE = 255; + private const Double RESOLUTION_TOLERANCE_RAW_VALUE = 255; /// /// Minimal value for attenuation. /// - public const Int32 ATTENUATION_MIN = 1; + public const Byte ATTENUATION_MIN = 1; /// /// Maximal value for attenuation. /// - public const Int32 ATTENUATION_MAX = 9; + public const Byte ATTENUATION_MAX = 9; /// - /// Minimal value for double pulse lock time in seconds. + /// Minimal value for double pulse lock time in milliseconds, 0.0 means it is disabled. /// - public const Double DOUBLE_PULSE_LOCK_TIME_MIN_s = 0.0; + public const Double DOUBLE_PULSE_DEADTIME_MIN_ms = 0.0; /// - /// Maximal value for double pulse lock time in seconds. - /// A timeout will be rose if the time between two subsequent pulses on REF or DUT exceeds after 21.889 s + /// Maximal value for double pulse lock time in milliseconds. + /// A timeout will be risen if the time between two subsequent pulses on REF or DUT exceeds after 21,889.0 ms /// - public const Double DOUBLE_PULSE_LOCK_TIME_MAX_s = 22.0; + public const Double DOUBLE_PULSE_DEADTIME_MAX_ms = 22000.0; /// /// Minimal input value for double pulse lock multiplier (multiplier for double pulse lock time in milliseconds). /// - public const Int32 DOUBLE_PULSE_LOCK_MULTIPLIER_INPUT_MIN = 1; + private const Byte DOUBLE_PULSE_DEADTIME_MULTIPLIER_INPUT_MIN = 1; /// /// Maximal input value for double pulse lock multiplier (multiplier for double pulse lock time in milliseconds). /// - public const Int32 DOUBLE_PULSE_LOCK_MULTIPLIER_INPUT_MAX = 99; + private const Byte DOUBLE_PULSE_DEADTIME_MULTIPLIER_INPUT_MAX = 99; /// /// Minimal input value for double pulse lock time in milliseconds. /// - public const Int32 DOUBLE_PULSE_LOCK_TIME_INPUT_MIN_ms = 0; + private const UInt16 DOUBLE_PULSE_BASE_DEADTIME_MIN_ms = 0; /// /// Maximal input value for double pulse lock time in milliseconds. /// - public const Int32 DOUBLE_PULSE_LOCK_TIME_INPUT_MAX_ms = 9999; + private const UInt16 DOUBLE_PULSE_BASE_DEADTIME_MAX_ms = 9999; /// /// FM2014 minimal pulses for REF and DUT time measurement. /// - public const UInt32 TIME_MEASUREMENT_INPUT_MIN_pulses = 1; + public const UInt16 TIME_MEASUREMENT_INPUT_MIN_pulses = 1; /// /// FM2014 maximal pulses for REF and DUT time measurement. /// - public const UInt32 TIME_MEASUREMENT_INPUT_MAX_pulses = 0xFFFF; + public const UInt16 TIME_MEASUREMENT_INPUT_MAX_pulses = 0xFFFF; /// /// Minimal baudrate for serial communication. @@ -269,7 +269,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core { if (value > BAUDRATE_INPUT_MAX || value < BAUDRATE_INPUT_MIN) _baudrate = BAUDRATE_INPUT_MIN; - else + else _baudrate = value; } } @@ -359,7 +359,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core percentage = EXTENDED_TOLERANCE_VALUE_percent; else percentage = STANDARD_TOLERANCE_VALUE_percent; - + _tolerance_percent = value; ToleranceRawToPercentScale = percentage / RESOLUTION_TOLERANCE_RAW_VALUE; } @@ -370,18 +370,17 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// public Boolean UseDampedTolerance { get; set; } - private UInt32 _refRequiredTimeMeasurement_pulses; + private UInt16 _refRequiredTimeMeasurement_pulses; /// /// Required REF pulses for time measurement. /// - public UInt32 RefRequiredTimeMeasurement_pulses + public UInt16 RefRequiredTimeMeasurement_pulses { get => _refRequiredTimeMeasurement_pulses; - private set + set { // Check limits and equality if (value < TIME_MEASUREMENT_INPUT_MIN_pulses || - value > TIME_MEASUREMENT_INPUT_MAX_pulses || value == _refRequiredTimeMeasurement_pulses) return; @@ -389,18 +388,17 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } } - private UInt32 _dutRequiredTimeMeasurement_pulses; + private UInt16 _dutRequiredTimeMeasurement_pulses; /// /// Required DUT pulses for time measurement. /// - public UInt32 DutRequiredTimeMeasurement_pulses + public UInt16 DutRequiredTimeMeasurement_pulses { get => _dutRequiredTimeMeasurement_pulses; - private set + set { // Check limits and equality if (value < TIME_MEASUREMENT_INPUT_MIN_pulses || - value > TIME_MEASUREMENT_INPUT_MAX_pulses || value == _dutRequiredTimeMeasurement_pulses) return; @@ -408,11 +406,11 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } } - private Int32 _refMeasuredTimer_ticks; + private UInt32 _refMeasuredTimer_ticks; /// /// REF timer ticks of measured pulses /// - public Int32 RefMeasuredTimer_ticks + public UInt32 RefMeasuredTimer_ticks { get => _refMeasuredTimer_ticks; private set @@ -422,11 +420,11 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } } - private Int32 _dutMeasuredTimer_ticks; + private UInt32 _dutMeasuredTimer_ticks; /// /// DUT timer ticks of measured pulses /// - public Int32 DutMeasuredTimer_ticks + public UInt32 DutMeasuredTimer_ticks { get => _dutMeasuredTimer_ticks; private set @@ -437,14 +435,25 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } /// + /// Maximal tolerance for DUT to REF calibration used as threshold for verification in percent + /// + public Double DutToRefCalibrationToleranceMax_percent { set; get; } + + /// + /// Minimal tolerance for DUT to REF calibration used as threshold for verification in percent + /// + public Double DutToRefCalibrationToleranceMin_percent { set; get; } + + /// + /// /// Remaining REF pulses for time measurement. /// - public UInt32 RefRemainingTimeMeasurement_pulses { get; private set; } + public UInt16 RefRemainingTimeMeasurement_pulses { get; private set; } /// /// Remaining DT pulses for time measurement. /// - public UInt32 DutRemainingTimeMeasurement_pulses { get; private set; } + public UInt16 DutRemainingTimeMeasurement_pulses { get; private set; } /// /// Measured REF time of required pulses. @@ -477,11 +486,11 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } } - private UInt32 _dut_pulse_per_cm; + private UInt16 _dut_pulse_per_cm; /// /// Device under test pulses per cubic-meter /// - public UInt32 Dut_pulse_per_cm + public UInt16 Dut_pulse_per_cm { get => _dut_pulse_per_cm; set @@ -551,32 +560,95 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } } - private Byte _attenuation = 3; + private Byte _fm2014CurrentOutputAttenuation = 3; /// - /// Filter value to attenuate the velocity of - /// the current output on the tolerance display + /// Filter value to attenuate the velocity of the current output on the tolerance display. + /// This value will be sent to the FM2014 /// - public Byte Attenuation + public Byte FM2014CurrentOutputAttenuation { - get => _attenuation; + get => _fm2014CurrentOutputAttenuation; set { if (value < ATTENUATION_MIN || value > ATTENUATION_MAX) return; - _attenuation = value; + _fm2014CurrentOutputAttenuation = value; + } + } + + private Double _doublePulseDeadtime_ms = 0.0; + /// + /// Double pulse deadtime in milliseconds to avoid on small oscillating input a repeated pulse. + /// + public Double DoublePulseDeadtime_ms + { + get => _doublePulseDeadtime_ms; + set + { + if (value < DOUBLE_PULSE_DEADTIME_MIN_ms || + value > DOUBLE_PULSE_DEADTIME_MAX_ms) + return; + _doublePulseDeadtime_ms = value; + + // Calculate and set up the values 'S' and 's' needed for the FM2014 + var tempBase_ms = (UInt16) value; + var tempMultiplier = 1; + while (tempBase_ms > DOUBLE_PULSE_BASE_DEADTIME_MAX_ms && + tempMultiplier < DOUBLE_PULSE_DEADTIME_MULTIPLIER_INPUT_MAX) + { + tempMultiplier++; + tempBase_ms = (UInt16)(value / tempMultiplier); + } + DoublePulseBaseDeadTime_ms = tempBase_ms; + DoublePulseMultiplier = (Byte)tempMultiplier; + } + } + + private Byte _doublePulseMultiplier = DOUBLE_PULSE_DEADTIME_MULTIPLIER_INPUT_MIN; + /// + /// Multiplier to extend the double pulse deadtime by maximum x 99, + /// as it is a multiplier the minimal value is 1. + /// + private Byte DoublePulseMultiplier + { + get => _doublePulseMultiplier; + set + { + if (value < DOUBLE_PULSE_DEADTIME_MULTIPLIER_INPUT_MIN || + value > DOUBLE_PULSE_DEADTIME_MULTIPLIER_INPUT_MAX) + return; + + _doublePulseMultiplier = value; + } + } + + private UInt16 _doublePulseBaseDeadTime_ms = DOUBLE_PULSE_BASE_DEADTIME_MIN_ms; + + /// + /// Base value for double impulse deadtime from 0 to 9999 milliseconds . + /// + private UInt16 DoublePulseBaseDeadTime_ms + { + get => _doublePulseBaseDeadTime_ms; + set + { + if (value > DOUBLE_PULSE_BASE_DEADTIME_MAX_ms) + return; + + _doublePulseBaseDeadTime_ms = value; } } /// /// The measured flow rate in cubic meters per hour using the REF /// - public Double RefFlowRate_cm_per_h { private set; get; } + private Double RefFlowRate_cm_per_h { set; get; } /// /// The measured flow rate in cubic meters per hour using the DUT /// - public Double DutFlowRate_cm_per_h { private set; get; } + private Double DutFlowRate_cm_per_h { set; get; } /// /// Successfully logged on to FM2014 @@ -597,7 +669,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core #region ------------------------------------------- static methods -------------------------------------------- /// - /// Reset the measurement but only if receive task is active: + /// Reset the measurement for all connected and logged in devices but only if receive task is active: /// - This should prepare the hardware for a new measurement which takes about 4 s. /// - It is a broadcast command which will reset all connected devices! /// @@ -749,17 +821,22 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } /// - /// The regulation measurement compares the DUT to REF tolerance: + /// The regulation measurement compares the DUT to REF tolerance + /// + /// ATTENTION: + /// The settings from the first listed FM2014 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 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, + /// - Setup double impulse deadtime, /// - Setup damping to attenuate the result, /// - Setup scale between REF to DUT pulses, - /// - Setup ref pulse counting mode to get REF pulses for flow rate. + /// - 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 @@ -792,8 +869,10 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core return false; // Check if regulation can be done - if (firstActiveFm2014.Ref_pulse_per_cm == 0 || - firstActiveFm2014.Dut_pulse_per_cm == 0 || + 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 || firstActiveFm2014.RefToDutScale_norm < REF_TO_DUT_SCALE_MIN || firstActiveFm2014.RefToDutScale_norm > REF_TO_DUT_SCALE_MAX) { @@ -814,7 +893,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } ActualProcessProgress++; cmdName = CmdName.CMD_MEAS_SET_ATTN; - if (!Write(cmdName, firstActiveFm2014, firstActiveFm2014.Attenuation)) + if (!Write(cmdName, firstActiveFm2014, firstActiveFm2014.FM2014CurrentOutputAttenuation)) { return false; } @@ -998,6 +1077,181 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core return true; } + /// + /// The calibration measurement compares the DUT to REF tolerance + /// + /// ATTENTION: + /// The settings from the first listed FM2014 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. + /// Cyclic: + /// - Request damped or undamped tolerance, + /// - 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 CalibrationMeasurement() + { + // If the cyclic task has already been started everything is fine + if (SharedCyclicMeasSequ == CyclicMeasSequ.CALIBRATION) + return true; + + // Marked measurement isn't pulse counter measurement, other FM2014s cannot activate this + if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE) + return false; + + var firstActiveFm2014 = GetFirstConnectedAndLoggedInFm2014(); + if (firstActiveFm2014 == null) + return false; + + // Check if regulation can be done + if (firstActiveFm2014.RefRequiredTimeMeasurement_pulses < TIME_MEASUREMENT_INPUT_MIN_pulses || + firstActiveFm2014.DutRequiredTimeMeasurement_pulses < TIME_MEASUREMENT_INPUT_MIN_pulses) + { + return false; + } + + var cmdName = CmdName.CMD_NA; + var measurementInfo = Resources.StrMeasMsgCalibration; + InitActualProcessProgress(3); + + // Prepare calibration measurement + try + { + // Check if double pulse deadtime has been set + if (Math.Abs(DOUBLE_PULSE_DEADTIME_MIN_ms - firstActiveFm2014.DoublePulseDeadtime_ms) < 0.9) + { + // This is a command without parameter + cmdName = CmdName.CMD_SET_DBPL_UNLOCK; + if (!Write(cmdName, firstActiveFm2014)) + { + return false; + } + } + else + { + cmdName = CmdName.CMD_SET_DPLS_LOCK_TMR; + if (!Write(cmdName, firstActiveFm2014, firstActiveFm2014.DoublePulseBaseDeadTime_ms)) + { + return false; + } + cmdName = CmdName.CMD_SET_DPLS_LOCK_MULT; + if (!Write(cmdName, firstActiveFm2014, firstActiveFm2014.DoublePulseMultiplier)) + { + return false; + } + } + + ActualProcessProgress++; + cmdName = CmdName.CMD_REF_SET_PLS; + if (!Write(cmdName, firstActiveFm2014, firstActiveFm2014.RefRequiredTimeMeasurement_pulses, true)) + { + return false; + } + ActualProcessProgress++; + cmdName = CmdName.CMD_DUT_SET_PLS; + if (!Write(cmdName, firstActiveFm2014, firstActiveFm2014.DutRequiredTimeMeasurement_pulses, true)) + { + return false; + } + ActualProcessProgress++; + } + catch (Exception e) + { + var response = new CmdResponse(cmdName, e.Message); + PublishResponse(firstActiveFm2014, new ProcessExecEventArgs(Resources.StrError, + specificInfoObj: response, statusReturn: StatusReturn.Failed)); + return false; + } + + // Measurement Loop + Task.Run(() => + { + // Mark calibration measurement as active + SharedCyclicMeasSequ = CyclicMeasSequ.CALIBRATION; + InitActualProcessProgress(firstActiveFm2014.RefRequiredTimeMeasurement_pulses); + + do + { + foreach (var fm2014 in RegisteredFm2014s.Where(fm2014 => fm2014.IsLoggedOn)) + { + try + { + String responseStr; + cmdName = CmdName.CMD_REF_GET_PLS_RMN; + var info = GetCmdInfo(cmdName); + if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014)) + { + if (Read(cmdName, fm2014, out responseStr) && + ushort.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var pulses)) + { + fm2014.RefRequiredTimeMeasurement_pulses = pulses; + var response = new CmdResponse(cmdName, info, pulses); + PublishResponse(fm2014, new ProcessExecEventArgs("", + actualProcessMessage: measurementInfo, + specificInfoObj: response)); + ActualProcessProgress = fm2014.RefRequiredTimeMeasurement_pulses - + fm2014.RefRemainingTimeMeasurement_pulses; + } + } + cmdName = CmdName.CMD_DUT_GET_PLS_RMN; + info = GetCmdInfo(cmdName); + if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014)) + { + if (Read(cmdName, fm2014, out responseStr) && + ushort.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var pulses)) + { + fm2014.DutRemainingTimeMeasurement_pulses = pulses; + var response = new CmdResponse(cmdName, info, pulses); + PublishResponse(fm2014, new ProcessExecEventArgs("", + actualProcessMessage: measurementInfo, + specificInfoObj: response)); + } + } + } + catch (Exception e) + { + var response = new CmdResponse(cmdName, e.Message); + PublishResponse(fm2014, new ProcessExecEventArgs(Resources.StrError, + specificInfoObj: response, statusReturn: StatusReturn.Failed)); + } + } + // Check all remaining DUT and REF pulses are counted on all connected devices and finalize process by + // reading out all results + if (RegisteredFm2014s.All(fm2014 => fm2014.RefRemainingTimeMeasurement_pulses == 0 && + fm2014.DutRemainingTimeMeasurement_pulses == 0)) + { + // Read out the result + SharedCyclicMeasSequ = CyclicMeasSequ.IDLE; + } + } while (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE); + + }, SharedCancellationToken); + + return true; + } + /// /// Read FM2014: /// - Accesses directly to the 'SerialPort.ReadTo', @@ -1061,6 +1315,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// /// /// + /// /// /// /// - Initial. @@ -1068,7 +1323,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// /// - Support for multiple FM2014s. /// - private static Boolean Write(CmdName cmdName, FM2014 fm2014, Object dataObj = null) + private static Boolean Write(CmdName cmdName, FM2014 fm2014, Object dataObj = null, Boolean isHexFormat = false) { if (fm2014 == null) return false; @@ -1131,9 +1386,10 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core // The data contains the preceding setup, the command code and string delimiter will be added here else if (dataObj is UInt16 || dataObj is Byte) { - SharedSerialPort.Write($"{dataObj}{cmdCodeStr}{END_OF_STR}"); + var valueStr = isHexFormat ? $"{dataObj:X}{cmdCodeStr}" : $"{dataObj}{cmdCodeStr}"; + SharedSerialPort.Write($"{valueStr}{END_OF_STR}"); response = new CmdResponse(cmdName, - $"{Resources.StrCommDirectionSetup}: {info}: {dataObj}{cmdCodeStr}"); + $"{Resources.StrCommDirectionSetup}: {info}: {valueStr}"); } else @@ -1526,7 +1782,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core if (retVal) { cmdName = CmdName.CMD_DUT_LPP_SCALE; - retVal = Write(cmdName, this, (UInt16)Dut_pulse_per_cm); + retVal = Write(cmdName, this, Dut_pulse_per_cm); } if (retVal) @@ -1539,7 +1795,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core if (retVal) { cmdName = CmdName.CMD_MEAS_SET_ATTN; - retVal = Write(cmdName, this, Attenuation); + retVal = Write(cmdName, this, FM2014CurrentOutputAttenuation); } if (retVal) @@ -1625,8 +1881,8 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core { cmdName = CmdName.CMD_MEAS_SET_ATTN; var info = GetCmdInfo(cmdName); - Attenuation = attenuation; - var response = new CmdResponse(cmdName, info, Attenuation); + FM2014CurrentOutputAttenuation = attenuation; + var response = new CmdResponse(cmdName, info, FM2014CurrentOutputAttenuation); PublishResponse(this, new ProcessExecEventArgs("", actualProcessMessage: measurementInfoStr, specificInfoObj: response)); } @@ -1650,12 +1906,12 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core if (str.Contains(StandAlonePartSearchDutPpvStr)) { var strCleaned = Regex.Replace(str, "[^0-9]", string.Empty); - if (uint.TryParse(strCleaned, out var value)) + if (ushort.TryParse(strCleaned, out var value)) { cmdName = CmdName.CMD_DUT_LPP_SCALE; var info = GetCmdInfo(cmdName); Dut_pulse_per_cm = value; - var response = new CmdResponse(cmdName, info, (Int32)Dut_pulse_per_cm); + var response = new CmdResponse(cmdName, info, Dut_pulse_per_cm); PublishResponse(this, new ProcessExecEventArgs("", actualProcessMessage: measurementInfoStr, specificInfoObj: response)); diff --git a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Properties/Resources.Designer.cs b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Properties/Resources.Designer.cs index 8fe3b623..7fe19bb1 100644 --- a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Properties/Resources.Designer.cs +++ b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Properties/Resources.Designer.cs @@ -79,6 +79,15 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Pr } } + /// + /// Looks up a localized string similar to DUT to REF tolerance. + /// + internal static string StrCalDutToRefTol { + get { + return ResourceManager.GetString("StrCalDutToRefTol", resourceCulture); + } + } + /// /// Looks up a localized string similar to REF flow rate f(REF frequency). /// @@ -161,7 +170,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Pr } /// - /// Looks up a localized string similar to Set double pulse dead time multiplier. + /// Looks up a localized string similar to Set double pulse deadtime multiplier. /// internal static string StrCmdMsgDplsLockMult { get { @@ -170,7 +179,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Pr } /// - /// Looks up a localized string similar to Set double pulse dead time milliseconds. + /// Looks up a localized string similar to Set double pulse deadtime milliseconds. /// internal static string StrCmdMsgDplsLockTmr { get { @@ -251,7 +260,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Pr } /// - /// Looks up a localized string similar to Damped tolerance DUT to REF. + /// Looks up a localized string similar to DUT to REF tolerance (damped). /// internal static string StrCmdMsgGetDtlc { get { @@ -296,7 +305,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Pr } /// - /// Looks up a localized string similar to Undamped tolerance DUT to REF. + /// Looks up a localized string similar to DUT to REF tolerance (un-damped). /// internal static string StrCmdMsgGetUdtlc { get { @@ -637,6 +646,15 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Pr } } + /// + /// Looks up a localized string similar to Calibration DUT to REF. + /// + internal static string StrMeasMsgCalibration { + get { + return ResourceManager.GetString("StrMeasMsgCalibration", resourceCulture); + } + } + /// /// Looks up a localized string similar to DUT pulse counter. /// diff --git a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Properties/Resources.de.resx b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Properties/Resources.de.resx index 36a7dd7e..9c2ccd3c 100644 --- a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Properties/Resources.de.resx +++ b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Properties/Resources.de.resx @@ -202,10 +202,10 @@ REF Zeiteinheiten - Ungedämpfte Toleranz DUT zu REF + DUT zu REF Toleranz (Ungedämpft) - Gedämpfte Toleranz DUT zu REF + DUT zu REF Toleranz (gedämpft) REF Periodendauer @@ -324,4 +324,10 @@ Antwort + + DUT zu REF Toleranz + + + Kalibrierung DUT zu REF + \ No newline at end of file diff --git a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Properties/Resources.resx b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Properties/Resources.resx index d293ca20..3ac592ed 100644 --- a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Properties/Resources.resx +++ b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Properties/Resources.resx @@ -163,10 +163,10 @@ REF to DUT pulse ratio - Set double pulse dead time milliseconds + Set double pulse deadtime milliseconds - Set double pulse dead time multiplier + Set double pulse deadtime multiplier REF to DUT attenuation @@ -202,10 +202,10 @@ REF timer ticks - Undamped tolerance DUT to REF + DUT to REF tolerance (un-damped) - Damped tolerance DUT to REF + DUT to REF tolerance (damped) REF period @@ -324,4 +324,10 @@ Response + + DUT to REF tolerance + + + Calibration DUT to REF + \ No newline at end of file diff --git a/FM2014TestApp/Ui/FM2014TestBenchWinFrms/FrmFm2014TestApp.cs b/FM2014TestApp/Ui/FM2014TestBenchWinFrms/FrmFm2014TestApp.cs index 940e6227..9348cd2a 100644 --- a/FM2014TestApp/Ui/FM2014TestBenchWinFrms/FrmFm2014TestApp.cs +++ b/FM2014TestApp/Ui/FM2014TestBenchWinFrms/FrmFm2014TestApp.cs @@ -857,9 +857,9 @@ namespace Sensus.Ui.FM2014TestApp if (Fm2014 != null) { if (byte.TryParse(cbxAttenuation.SelectedItem.ToString(), out var attenuation) && - attenuation > 0 && attenuation <= 9 && Fm2014.Attenuation != attenuation) + attenuation > 0 && attenuation <= 9 && Fm2014.FM2014CurrentOutputAttenuation != attenuation) { - Fm2014.Attenuation = attenuation; + Fm2014.FM2014CurrentOutputAttenuation = attenuation; _regulationSetupHasChanged = true; btnSaveRegulationSetup.Enabled = true; } diff --git a/FM2014TestApp/Ui/Fm2014sTest/FM2014TestBenchWindow.xaml b/FM2014TestApp/Ui/Fm2014sTest/FM2014TestBenchWindow.xaml index 3e7089c9..24c01657 100644 --- a/FM2014TestApp/Ui/Fm2014sTest/FM2014TestBenchWindow.xaml +++ b/FM2014TestApp/Ui/Fm2014sTest/FM2014TestBenchWindow.xaml @@ -247,16 +247,16 @@ - - - - - - - - - - + + + + + + + + + + @@ -281,6 +281,7 @@