FM2014TestBench: - initial setup to test multiple FM2014 - 8.Step

This commit is contained in:
Thomas Wiedebusch 2026-02-07 15:28:46 +01:00
parent 6c282372d3
commit 45fbf4f854
11 changed files with 784 additions and 172 deletions

View File

@ -237,6 +237,11 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
/// </summary>
CMD_GET_REF_FREQU,
/// <summary>
/// Calculate DUT to REF tolerance based on timer values
/// </summary>
CMD_CAL_DUT_TO_REF_TOL,
/// <summary>
/// Calculate frequency from REF period
/// </summary>
@ -309,9 +314,9 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
REGULATION,
/// <summary>
/// Time measurement ongoing
/// Calibration measurement ongoing
/// </summary>
TIME
CALIBRATION
}
/// <summary>
@ -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),

View File

@ -88,7 +88,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
/// Default tolerance if not properly setup.
/// </summary>
public const Int32 STANDARD_NOMINAL_TOLERANCE_INPUT_percent = 3;
/// <summary>
/// Default tolerance if not properly setup.
/// </summary>
@ -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).
/// </summary>
public const Double STANDARD_TOLERANCE_VALUE_percent = 3.3;
private const Double STANDARD_TOLERANCE_VALUE_percent = 3.3;
/// <summary>
/// Extended tolerance (nominal 5 %) multiplicator for calculation of value based on feedback from FM2014
/// (+/- 255 digits).
/// </summary>
public const Double EXTENDED_TOLERANCE_VALUE_percent = 5.5;
private const Double EXTENDED_TOLERANCE_VALUE_percent = 5.5;
/// <summary>
/// Resolution of tolerance raw value feedback from FM2014 (+/- 255 digits).
/// </summary>
public const Double RESOLUTION_TOLERANCE_RAW_VALUE = 255;
private const Double RESOLUTION_TOLERANCE_RAW_VALUE = 255;
/// <summary>
/// Minimal value for attenuation.
/// </summary>
public const Int32 ATTENUATION_MIN = 1;
public const Byte ATTENUATION_MIN = 1;
/// <summary>
/// Maximal value for attenuation.
/// </summary>
public const Int32 ATTENUATION_MAX = 9;
public const Byte ATTENUATION_MAX = 9;
/// <summary>
/// Minimal value for double pulse lock time in seconds.
/// Minimal value for double pulse lock time in milliseconds, 0.0 means it is disabled.
/// </summary>
public const Double DOUBLE_PULSE_LOCK_TIME_MIN_s = 0.0;
public const Double DOUBLE_PULSE_DEADTIME_MIN_ms = 0.0;
/// <summary>
/// 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
/// </summary>
public const Double DOUBLE_PULSE_LOCK_TIME_MAX_s = 22.0;
public const Double DOUBLE_PULSE_DEADTIME_MAX_ms = 22000.0;
/// <summary>
/// Minimal input value for double pulse lock multiplier (multiplier for double pulse lock time in milliseconds).
/// </summary>
public const Int32 DOUBLE_PULSE_LOCK_MULTIPLIER_INPUT_MIN = 1;
private const Byte DOUBLE_PULSE_DEADTIME_MULTIPLIER_INPUT_MIN = 1;
/// <summary>
/// Maximal input value for double pulse lock multiplier (multiplier for double pulse lock time in milliseconds).
/// </summary>
public const Int32 DOUBLE_PULSE_LOCK_MULTIPLIER_INPUT_MAX = 99;
private const Byte DOUBLE_PULSE_DEADTIME_MULTIPLIER_INPUT_MAX = 99;
/// <summary>
/// Minimal input value for double pulse lock time in milliseconds.
/// </summary>
public const Int32 DOUBLE_PULSE_LOCK_TIME_INPUT_MIN_ms = 0;
private const UInt16 DOUBLE_PULSE_BASE_DEADTIME_MIN_ms = 0;
/// <summary>
/// Maximal input value for double pulse lock time in milliseconds.
/// </summary>
public const Int32 DOUBLE_PULSE_LOCK_TIME_INPUT_MAX_ms = 9999;
private const UInt16 DOUBLE_PULSE_BASE_DEADTIME_MAX_ms = 9999;
/// <summary>
/// FM2014 minimal pulses for REF and DUT time measurement.
/// </summary>
public const UInt32 TIME_MEASUREMENT_INPUT_MIN_pulses = 1;
public const UInt16 TIME_MEASUREMENT_INPUT_MIN_pulses = 1;
/// <summary>
/// FM2014 maximal pulses for REF and DUT time measurement.
/// </summary>
public const UInt32 TIME_MEASUREMENT_INPUT_MAX_pulses = 0xFFFF;
public const UInt16 TIME_MEASUREMENT_INPUT_MAX_pulses = 0xFFFF;
/// <summary>
/// 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
/// </summary>
public Boolean UseDampedTolerance { get; set; }
private UInt32 _refRequiredTimeMeasurement_pulses;
private UInt16 _refRequiredTimeMeasurement_pulses;
/// <summary>
/// Required REF pulses for time measurement.
/// </summary>
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;
/// <summary>
/// Required DUT pulses for time measurement.
/// </summary>
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;
/// <summary>
/// REF timer ticks of measured pulses
/// </summary>
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;
/// <summary>
/// DUT timer ticks of measured pulses
/// </summary>
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
}
/// <summary>
/// Maximal tolerance for DUT to REF calibration used as threshold for verification in percent
/// </summary>
public Double DutToRefCalibrationToleranceMax_percent { set; get; }
/// <summary>
/// Minimal tolerance for DUT to REF calibration used as threshold for verification in percent
/// </summary>
public Double DutToRefCalibrationToleranceMin_percent { set; get; }
/// <summary>
///
/// Remaining REF pulses for time measurement.
/// </summary>
public UInt32 RefRemainingTimeMeasurement_pulses { get; private set; }
public UInt16 RefRemainingTimeMeasurement_pulses { get; private set; }
/// <summary>
/// Remaining DT pulses for time measurement.
/// </summary>
public UInt32 DutRemainingTimeMeasurement_pulses { get; private set; }
public UInt16 DutRemainingTimeMeasurement_pulses { get; private set; }
/// <summary>
/// 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;
/// <summary>
/// Device under test pulses per cubic-meter
/// </summary>
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;
/// <summary>
/// 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
/// </summary>
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;
/// <summary>
/// Double pulse deadtime in milliseconds to avoid on small oscillating input a repeated pulse.
/// </summary>
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;
/// <summary>
/// Multiplier to extend the double pulse deadtime by maximum x 99,
/// as it is a multiplier the minimal value is 1.
/// </summary>
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;
/// <summary>
/// Base value for double impulse deadtime from 0 to 9999 milliseconds .
/// </summary>
private UInt16 DoublePulseBaseDeadTime_ms
{
get => _doublePulseBaseDeadTime_ms;
set
{
if (value > DOUBLE_PULSE_BASE_DEADTIME_MAX_ms)
return;
_doublePulseBaseDeadTime_ms = value;
}
}
/// <summary>
/// The measured flow rate in cubic meters per hour using the REF
/// </summary>
public Double RefFlowRate_cm_per_h { private set; get; }
private Double RefFlowRate_cm_per_h { set; get; }
/// <summary>
/// The measured flow rate in cubic meters per hour using the DUT
/// </summary>
public Double DutFlowRate_cm_per_h { private set; get; }
private Double DutFlowRate_cm_per_h { set; get; }
/// <summary>
/// Successfully logged on to FM2014
@ -597,7 +669,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
#region ------------------------------------------- static methods --------------------------------------------
/// <summary>
/// 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!
/// </summary>
@ -749,17 +821,22 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
}
/// <summary>
/// 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 <see cref="ResetHardwareAllDevices"/> has to be executed in advance,
/// - The <see cref="Ref_pulse_per_cm"/>REF pulses per cubic meter has to be preset,
/// - The <see cref="Dut_pulse_per_cm"/>DUT pulses per cubic meter has to be preset,
/// - The <see cref="RefToDutScale_norm"/>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 <see cref="Ref_pulse_per_cm"/> 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;
}
/// <summary>
/// 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 <see cref="ResetHardwareAllDevices"/> has to be executed in advance,
/// - The <see cref="RefRequiredTimeMeasurement_pulses"/>REF pulses to count has to be preset,
/// - The <see cref="DutRemainingTimeMeasurement_pulses"/>DUT pulses to count has to be preset,
/// - Setup double impulse deadtime using the <see cref="DoublePulseDeadtime_ms"/> whichautomatically
/// calculates the <see cref="DoublePulseMultiplier"/> and <see cref="DoublePulseBaseDeadTime_ms"/>.
/// 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 <see cref="Ref_pulse_per_cm"/> to calculate
/// <see cref="RefFlowRate_cm_per_h"/>the 'Flow rate'.
/// Exit:
/// - Set <see cref="SharedCyclicMeasSequ"/> to false.
/// </summary>
/// <returns></returns>
/// <remarks date="2026-Jan-14..21" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
/// <remarks date="2026-Jan-28..29" author="Thomas Wiedebusch">
/// - Support for multiple FM2014s.
/// </remarks>
/// <remarks date="2026-Feb-05" author="Thomas Wiedebusch">
/// - Static.
/// </remarks>
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;
}
/// <summary>
/// Read FM2014:
/// - Accesses directly to the 'SerialPort.ReadTo',
@ -1061,6 +1315,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
/// <param name="cmdName"></param>
/// <param name="fm2014"></param>
/// <param name="dataObj"></param>
/// <param name="isHexFormat"></param>
/// <returns></returns>
/// <remarks date="2026-Jan-12..23" author="Thomas Wiedebusch">
/// - Initial.
@ -1068,7 +1323,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
/// <remarks date="2026-Jan-28..30" author="Thomas Wiedebusch">
/// - Support for multiple FM2014s.
/// </remarks>
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));

View File

@ -79,6 +79,15 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Pr
}
}
/// <summary>
/// Looks up a localized string similar to DUT to REF tolerance.
/// </summary>
internal static string StrCalDutToRefTol {
get {
return ResourceManager.GetString("StrCalDutToRefTol", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to REF flow rate f(REF frequency).
/// </summary>
@ -161,7 +170,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Pr
}
/// <summary>
/// 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.
/// </summary>
internal static string StrCmdMsgDplsLockMult {
get {
@ -170,7 +179,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Pr
}
/// <summary>
/// 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.
/// </summary>
internal static string StrCmdMsgDplsLockTmr {
get {
@ -251,7 +260,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Pr
}
/// <summary>
/// Looks up a localized string similar to Damped tolerance DUT to REF.
/// Looks up a localized string similar to DUT to REF tolerance (damped).
/// </summary>
internal static string StrCmdMsgGetDtlc {
get {
@ -296,7 +305,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Pr
}
/// <summary>
/// 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).
/// </summary>
internal static string StrCmdMsgGetUdtlc {
get {
@ -637,6 +646,15 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Pr
}
}
/// <summary>
/// Looks up a localized string similar to Calibration DUT to REF.
/// </summary>
internal static string StrMeasMsgCalibration {
get {
return ResourceManager.GetString("StrMeasMsgCalibration", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to DUT pulse counter.
/// </summary>

View File

@ -202,10 +202,10 @@
<value>REF Zeiteinheiten</value>
</data>
<data name="StrCmdMsgGetUdtlc" xml:space="preserve">
<value>Ungedämpfte Toleranz DUT zu REF</value>
<value>DUT zu REF Toleranz (Ungedämpft)</value>
</data>
<data name="StrCmdMsgGetDtlc" xml:space="preserve">
<value>Gedämpfte Toleranz DUT zu REF</value>
<value>DUT zu REF Toleranz (gedämpft)</value>
</data>
<data name="StrCmdMsgGetRefPeriod" xml:space="preserve">
<value>REF Periodendauer</value>
@ -324,4 +324,10 @@
<data name="StrCommResponse" xml:space="preserve">
<value>Antwort</value>
</data>
<data name="StrCalDutToRefTol" xml:space="preserve">
<value>DUT zu REF Toleranz</value>
</data>
<data name="StrMeasMsgCalibration" xml:space="preserve">
<value>Kalibrierung DUT zu REF</value>
</data>
</root>

View File

@ -163,10 +163,10 @@
<value>REF to DUT pulse ratio</value>
</data>
<data name="StrCmdMsgDplsLockTmr" xml:space="preserve">
<value>Set double pulse dead time milliseconds</value>
<value>Set double pulse deadtime milliseconds</value>
</data>
<data name="StrCmdMsgDplsLockMult" xml:space="preserve">
<value>Set double pulse dead time multiplier</value>
<value>Set double pulse deadtime multiplier</value>
</data>
<data name="StrCmdMsgMeasSetAttn" xml:space="preserve">
<value>REF to DUT attenuation</value>
@ -202,10 +202,10 @@
<value>REF timer ticks</value>
</data>
<data name="StrCmdMsgGetUdtlc" xml:space="preserve">
<value>Undamped tolerance DUT to REF</value>
<value>DUT to REF tolerance (un-damped)</value>
</data>
<data name="StrCmdMsgGetDtlc" xml:space="preserve">
<value>Damped tolerance DUT to REF</value>
<value>DUT to REF tolerance (damped)</value>
</data>
<data name="StrCmdMsgGetRefPeriod" xml:space="preserve">
<value>REF period</value>
@ -324,4 +324,10 @@
<data name="StrCommResponse" xml:space="preserve">
<value>Response</value>
</data>
<data name="StrCalDutToRefTol" xml:space="preserve">
<value>DUT to REF tolerance</value>
</data>
<data name="StrMeasMsgCalibration" xml:space="preserve">
<value>Calibration DUT to REF</value>
</data>
</root>

View File

@ -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;
}

View File

@ -247,16 +247,16 @@
<Rectangle HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="-1,0,0,0" Grid.Row="0" Grid.RowSpan="12" Grid.Column="21" Grid.ColumnSpan="2" Stroke="LightGray"/>
<Rectangle HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="-1,0,0,0" Grid.Row="0" Grid.RowSpan="12" Grid.Column="23" Grid.ColumnSpan="2" Stroke="LightGray"/>
<CheckBox x:Name="chkSlot1" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="5" Grid.ColumnSpan="2" Content="1" IsChecked="True" Click="chkSlot1_Click"/>
<CheckBox x:Name="chkSlot2" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="7" Grid.ColumnSpan="2" Content="2" IsChecked="True" Click="chkSlot1_Click"/>
<CheckBox x:Name="chkSlot3" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="9" Grid.ColumnSpan="2" Content="3" IsChecked="True" Click="chkSlot1_Click"/>
<CheckBox x:Name="chkSlot4" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="11" Grid.ColumnSpan="2" Content="4" IsChecked="True" Click="chkSlot1_Click"/>
<CheckBox x:Name="chkSlot5" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="13" Grid.ColumnSpan="2" Content="5" IsChecked="True" Click="chkSlot1_Click"/>
<CheckBox x:Name="chkSlot6" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="15" Grid.ColumnSpan="2" Content="6" IsChecked="True" Click="chkSlot1_Click"/>
<CheckBox x:Name="chkSlot7" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="17" Grid.ColumnSpan="2" Content="7" IsChecked="True" Click="chkSlot1_Click"/>
<CheckBox x:Name="chkSlot8" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="19" Grid.ColumnSpan="2" Content="8" IsChecked="True" Click="chkSlot1_Click"/>
<CheckBox x:Name="chkSlot9" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="21" Grid.ColumnSpan="2" Content="9" IsChecked="True" Click="chkSlot1_Click"/>
<CheckBox x:Name="chkSlot10" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="23" Grid.ColumnSpan="2" Content="10" IsChecked="True" Click="chkSlot1_Click"/>
<CheckBox x:Name="chkSlot1" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="5" Grid.ColumnSpan="2" Content="1" IsChecked="True" Click="chkAnySlot_Click"/>
<CheckBox x:Name="chkSlot2" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="7" Grid.ColumnSpan="2" Content="2" IsChecked="True" Click="chkAnySlot_Click"/>
<CheckBox x:Name="chkSlot3" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="9" Grid.ColumnSpan="2" Content="3" IsChecked="True" Click="chkAnySlot_Click"/>
<CheckBox x:Name="chkSlot4" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="11" Grid.ColumnSpan="2" Content="4" IsChecked="True" Click="chkAnySlot_Click"/>
<CheckBox x:Name="chkSlot5" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="13" Grid.ColumnSpan="2" Content="5" IsChecked="True" Click="chkAnySlot_Click"/>
<CheckBox x:Name="chkSlot6" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="15" Grid.ColumnSpan="2" Content="6" IsChecked="True" Click="chkAnySlot_Click"/>
<CheckBox x:Name="chkSlot7" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="17" Grid.ColumnSpan="2" Content="7" IsChecked="True" Click="chkAnySlot_Click"/>
<CheckBox x:Name="chkSlot8" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="19" Grid.ColumnSpan="2" Content="8" IsChecked="True" Click="chkAnySlot_Click"/>
<CheckBox x:Name="chkSlot9" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="21" Grid.ColumnSpan="2" Content="9" IsChecked="True" Click="chkAnySlot_Click"/>
<CheckBox x:Name="chkSlot10" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" Grid.Row="0" Grid.Column="23" Grid.ColumnSpan="2" Content="10" IsChecked="True" Click="chkAnySlot_Click"/>
</Grid>
</GroupBox>
@ -281,6 +281,7 @@
<Label x:Name="lblTotalProcessText" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="1,0,1,0" Grid.Row="26" Grid.Column="4" Grid.ColumnSpan="8" Content="" />
<Label x:Name="lblActualProgressPercent" HorizontalAlignment="Right" VerticalAlignment="Stretch" Margin="1,0,1,0" Grid.Row="25" Grid.Column="37" Grid.ColumnSpan="3" Content="0,0 %" />
<Label x:Name="lblTotalProgressPercent" HorizontalAlignment="Right" VerticalAlignment="Stretch" Margin="1,0,1,0" Grid.Row="26" Grid.Column="37" Grid.ColumnSpan="3" Content="0,0 %" />
<!-- Measurements -->
<TabControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="1,2,2,2" Grid.Row="17" Grid.RowSpan="8" Grid.Column="0" Grid.ColumnSpan="26" >
<!-- REF to Scale Calibration -->
@ -339,7 +340,56 @@
<!-- DUT to REF Calibration -->
<TabItem x:Name="tabDutToRefCalibration" Header="DUT to REF Calibration">
<Grid Background="#FFE5E5E5"/>
<Grid Background="#FFE5E5E5" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="2,2,2,2">
<Grid.RowDefinitions>
<RowDefinition Height="26"/>
<RowDefinition Height="26"/>
<RowDefinition Height="26"/>
<RowDefinition Height="26"/>
<RowDefinition Height="26"/>
<RowDefinition Height="*"/>
<RowDefinition Height="26"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label x:Name="lblRefRequiredPulses" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,0" Grid.Row="1" Grid.Column="17" Grid.ColumnSpan="6" Content="REF Required Pulses:" />
<Label x:Name="lblDutRequiredPulses" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,0" Grid.Row="2" Grid.Column="17" Grid.ColumnSpan="6" Content="DUT Required Pulses:" />
<Label x:Name="lblDutToRefTolMin" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,0" Grid.Row="3" Grid.Column="17" Grid.ColumnSpan="6" Content="Double Pulse Deadtime [ms]:" />
<Label x:Name="lblDutToRefTolMax" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,0" Grid.Row="4" Grid.Column="17" Grid.ColumnSpan="6" Content="DUT/REF Tolerance max [%]:" />
<Label x:Name="lblDoublePulseDeadtime" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,0" Grid.Row="5" Grid.Column="17" Grid.ColumnSpan="6" Content="DUT/REF Tolerance min [%]:" />
<TextBox x:Name="tbxRefRequiredPulse" VerticalAlignment="Stretch" Margin="0,0,0,0" Grid.Row="1" Grid.Column="23" Grid.ColumnSpan="2" Text="500" MaxLines="1" HorizontalContentAlignment="Right" TabIndex="111" /><!--KeyDown="tbxRefRequiredPulses_KeyDown" LostFocus="tbxRefRequiredPulses_LostFocus" TextChanged="tbxRefRequiredPulses_TextChanged" /-->
<TextBox x:Name="tbxDutRequiredPulses" VerticalAlignment="Stretch" Margin="0,0,0,0" Grid.Row="2" Grid.Column="23" Grid.ColumnSpan="2" Text="50" MaxLines="1" HorizontalContentAlignment="Right" TabIndex="112" /><!--KeyDown="tbxDutRequiredPulses_KeyDown" LostFocus="tbxDutRequiredPulses_LostFocus" TextChanged="tbxDutRequiredPulses_TextChanged"/-->
<TextBox x:Name="tbxDoublePulseDeadtime" VerticalAlignment="Stretch" Margin="0,0,0,0" Grid.Row="3" Grid.Column="23" Grid.ColumnSpan="2" Text="0.005" MaxLines="1" HorizontalContentAlignment="Right" TabIndex="113" />
<TextBox x:Name="tbxDutToRefTolMin" VerticalAlignment="Stretch" Margin="0,0,0,0" Grid.Row="4" Grid.Column="23" Grid.ColumnSpan="2" Text="1.0" MaxLines="1" HorizontalContentAlignment="Right" TabIndex="114" />
<TextBox x:Name="tbxDutToRefTolMax" VerticalAlignment="Stretch" Margin="0,0,0,0" Grid.Row="5" Grid.Column="23" Grid.ColumnSpan="2" Text="-0.5" MaxLines="1" HorizontalContentAlignment="Right" TabIndex="115" />
<Button x:Name="btnDutToRefCalibration" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,0" Grid.Row="6" Grid.Column="0" Grid.ColumnSpan="4" Content="Start Calibration" Click="btnDutToRefCalibration_Click" TabIndex="110" />
</Grid>
</TabItem>
<!-- REF to Scale Calibration -->

View File

@ -133,11 +133,28 @@ namespace Sensus.Ui.FM2014TestBench
private String _lastLoggingTextToAvoidRepetition;
// DUT to REF regulation label index published to UcFM2014s measurement positions 0..6
private const Int32 REG_LBL_IDX_TOLERANCE = 0;
private const Int32 REG_LBL_IDX_DUT_TO_REF_TOL = 0;
private const Int32 REG_LBL_IDX_REF_FREQU = 1;
private const Int32 REG_LBL_IDX_FLOW_RATE = 2;
private const Int32 REG_MEASURE_COUNT = 3;
// DUT to REF calibration label index published to UcFM2014s measurement positions 0..6
private const Int32 CAL_LBL_IDX_REF_REQ_PLS = 0;
private const Int32 CAL_LBL_IDX_REF_RMN_PLS = 1;
private const Int32 CAL_LBL_IDX_DUT_REQ_PLS = 2;
private const Int32 CAL_LBL_IDX_DUT_RMN_PLS = 3;
private const Int32 CAL_LBL_IDX_REF_MEAS_TMR = 4;
private const Int32 CAL_LBL_IDX_DUT_MEAS_TMR = 5;
private const Int32 CAL_LBL_IDX_DUT_TO_REF_TOL = 6;
private const Int32 CAL_MEASURE_COUNT = 7;
// Pulse counter measurements label index published to UcFM2014s measurement positions 0..6
private const Int32 CTR_LBL_IDX_REF_PLS = 0;
private const Int32 CTR_LBL_IDX_DUT_PLS = 1;
private const Int32 CTR_LBL_IDX_REF_FREQU = 2;
private const Int32 CTR_LBL_IDX_FLOW_RATE = 3;
private const Int32 CTR_MEASURE_COUNT = 4;
#endregion ---------------------------------------- Properties ------------------------------------------------
#region ------------------------------------------- FormControls ----------------------------------------------
/// <summary>
@ -523,9 +540,9 @@ namespace Sensus.Ui.FM2014TestBench
lblSlotSelection.Content = Properties.Resources.StrLblSlotSelection;
// Regulation Setup
lblRefPulsesPerCm.Content = Properties.Resources.StrLblRefPulsesPerCm;
lblRefPulsesPerCm.Content = Properties.Resources.StrLblRatioRefPulsesPerCm;
tbxRefPulsesPerCm.Text = "";
lblDutPulsesPerCm.Content = Properties.Resources.StrLblDutPulsesPerCm;
lblDutPulsesPerCm.Content = Properties.Resources.StrLblRatioDutPulsesPerCm;
tbxDutPulsesPerCm.Text = "";
lblScaleRefToDut.Content = Properties.Resources.StrLblScaleRefToDut;
tbxScaleRefToDut.Text = "";
@ -556,7 +573,8 @@ namespace Sensus.Ui.FM2014TestBench
//btnManualRefCalibration.Text = Properties.Resources.StrBtnStartCalibration;
//// Process status
lblActualProcessLabel.Content = Properties.Resources.StrLblProcessStatus;
lblActualProcessLabel.Content = Properties.Resources.StrLblActualProcessStatus;
lblTotalProcessLabel.Content = Properties.Resources.StrLblOverallProcessStatus;
lblTimeText.Text = Properties.Resources.StrLblTime;
ActionControl(false);
@ -628,7 +646,7 @@ namespace Sensus.Ui.FM2014TestBench
ResetCancellationToken();
FM2014.SharedCancellationToken = _cancellationToken;
UpdateContentControl(lblTotalProcessLabel, Properties.Resources.StrMsgConnecting);
UpdateContentControl(lblTotalProcessText, Properties.Resources.StrMsgConnecting);
var comPort = cbxFM2014ComPort.SelectedItem.ToString();
@ -984,17 +1002,16 @@ namespace Sensus.Ui.FM2014TestBench
/// <summary>
/// Feedback from FM2014being parsed to GUI
/// </summary>
/// <remarks date="2026-Feb-02..06" author="Thomas Wiedebusch">
/// <remarks date="2026-Feb-02..07" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
private void DataReceived_Handler(Object sender, ProcessExecEventArgs e)
{
try
{
// Remind the FM2014 user control based on the address of the FM2014 to dispatch received message to the
// correct device
UcFM2014Device ucFm2014 = null;
UcFM2014Device ucFm2014;
if (sender is FM2014 fm2014)
{
var idx = fm2014.Address - 1;
@ -1029,13 +1046,13 @@ namespace Sensus.Ui.FM2014TestBench
// Data dispatcher
var resp = (CmdResponse)e.SpecificInfoObj;
String valueStr;
if (e.StatusReturn == StatusReturn.Failed)
{
LogErrorText(resp.AnswerStr);
//ErrorHandler(resp.CmdName);
}
else if (resp.IntValue == null && resp.DoubleValue == null)
{
LogText(resp.AnswerStr);
@ -1045,6 +1062,12 @@ namespace Sensus.Ui.FM2014TestBench
LogText($"{resp.AnswerStr}: {resp.IntValue:D} {resp.SiUnit}");
switch (resp.CmdName)
{
case CmdName.CMD_REF_GET_PLS_RMN:
ucFm2014.SetValue(CAL_LBL_IDX_REF_RMN_PLS, $"{resp.IntValue:D}");
break;
case CmdName.CMD_DUT_GET_PLS_RMN:
ucFm2014.SetValue(CAL_LBL_IDX_DUT_RMN_PLS, $"{resp.IntValue:D}");
break;
case CmdName.CMD_REF_GET_PLS_CTR:
case CmdName.CMD_REF_GET_PLS_CTR_BU:
//UpdateTextBox(tbxMeasuredRefPulses, $"{resp.IntValue:D}");
@ -1063,7 +1086,7 @@ namespace Sensus.Ui.FM2014TestBench
Dispatcher.Invoke(() => cbxAttenuation.SelectedItem = $"{resp.IntValue}");
break;
case CmdName.CMD_GET_REF_FREQU:
var valueStr = $"{resp.IntValue:D}";
valueStr = $"{resp.IntValue:D}";
if (resp.IntValue < FM2014.REF_FREQU_MIN || resp.IntValue > FM2014.REF_FREQU_MAX)
ucFm2014.SetValue(REG_LBL_IDX_REF_FREQU, valueStr, ColorProcessFailed);
else
@ -1076,13 +1099,29 @@ namespace Sensus.Ui.FM2014TestBench
LogText($"{resp.AnswerStr}: {resp.DoubleValue:F2} {resp.SiUnit}");
switch (resp.CmdName)
{
case CmdName.CMD_REF_GET_TMR:
valueStr = $"{resp.DoubleValue:F3}";
ucFm2014.SetValue(CAL_LBL_IDX_REF_MEAS_TMR, valueStr);
break;
case CmdName.CMD_DUT_GET_TMR:
valueStr = $"{resp.DoubleValue:F3}";
ucFm2014.SetValue(CAL_LBL_IDX_DUT_MEAS_TMR, valueStr);
break;
case CmdName.CMD_CAL_DUT_TO_REF_TOL:
valueStr = $"{resp.DoubleValue:F2}";
if ((Double)resp.DoubleValue > fm2014.DutToRefCalibrationToleranceMax_percent ||
(Double)resp.DoubleValue < fm2014.DutToRefCalibrationToleranceMin_percent)
ucFm2014.SetValue(CAL_LBL_IDX_DUT_TO_REF_TOL, valueStr, ColorProcessFailed);
else
ucFm2014.SetValue(CAL_LBL_IDX_DUT_TO_REF_TOL, valueStr, ColorSuccess);
break;
case CmdName.CMD_GET_UDTLC:
case CmdName.CMD_GET_DTLC:
var valueStr = $"{resp.DoubleValue:F2}";
valueStr = $"{resp.DoubleValue:F2}";
if (Math.Abs((Double)resp.DoubleValue) > fm2014.Tolerance_percent)
ucFm2014.SetValue(REG_LBL_IDX_TOLERANCE, valueStr, ColorProcessFailed);
ucFm2014.SetValue(REG_LBL_IDX_DUT_TO_REF_TOL, valueStr, ColorProcessFailed);
else
ucFm2014.SetValue(REG_LBL_IDX_TOLERANCE, valueStr);
ucFm2014.SetValue(REG_LBL_IDX_DUT_TO_REF_TOL, valueStr);
break;
case CmdName.CMD_REF_SET_SCALE:
UpdateTextBox(tbxScaleRefToDut, $"{resp.DoubleValue:F4}");
@ -1116,7 +1155,7 @@ namespace Sensus.Ui.FM2014TestBench
}
}
}
catch (Exception exception)
catch (Exception)
{
//
}
@ -1137,6 +1176,80 @@ namespace Sensus.Ui.FM2014TestBench
Connect();
}
/// <summary>
/// Start and stop the DUT to REF calibration measurement.
/// </summary>
/// <remarks date="2026-Feb-07" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
private void btnDutToRefCalibration_Click(Object sender, EventArgs e)
{
_startTime = DateTimeOffset.UtcNow;
if (FM2014.SharedCyclicMeasSequ == CyclicMeasSequ.IDLE)
{
ActionControl(true);
// Disable and hide dynamic measurement labels
foreach (var measLbl in MeasurementLabels)
UiElmEnable(measLbl, false, false);
// Set the measurement labels
UpdateContentControl(MeasurementLabels[CAL_LBL_IDX_REF_REQ_PLS], Properties.Resources.StrLblRequiredRefPulses);
UpdateContentControl(MeasurementLabels[CAL_LBL_IDX_REF_RMN_PLS], Properties.Resources.StrLblRemainingRefPulses);
UpdateContentControl(MeasurementLabels[CAL_LBL_IDX_DUT_REQ_PLS], Properties.Resources.StrLblRequiredDutPulses);
UpdateContentControl(MeasurementLabels[CAL_LBL_IDX_DUT_RMN_PLS], Properties.Resources.StrLblRemainingDutPulses);
UpdateContentControl(MeasurementLabels[CAL_LBL_IDX_REF_MEAS_TMR], Properties.Resources.StrLblMeasuredRefTime);
UpdateContentControl(MeasurementLabels[CAL_LBL_IDX_DUT_MEAS_TMR], Properties.Resources.StrLblMeasuredDutTime);
UpdateContentControl(MeasurementLabels[CAL_LBL_IDX_DUT_TO_REF_TOL], Properties.Resources.StrLblMeasuredDutToRefTolerance);
UiElmEnable(MeasurementLabels[CAL_LBL_IDX_REF_REQ_PLS], true);
UiElmEnable(MeasurementLabels[CAL_LBL_IDX_REF_RMN_PLS], true);
UiElmEnable(MeasurementLabels[CAL_LBL_IDX_DUT_REQ_PLS], true);
UiElmEnable(MeasurementLabels[CAL_LBL_IDX_DUT_RMN_PLS], true);
UiElmEnable(MeasurementLabels[CAL_LBL_IDX_REF_MEAS_TMR], true);
UiElmEnable(MeasurementLabels[CAL_LBL_IDX_DUT_MEAS_TMR], true);
UiElmEnable(MeasurementLabels[CAL_LBL_IDX_DUT_TO_REF_TOL], true);
if (FM2014.RegisteredFm2014s == null || FM2014.RegisteredFm2014s.Count == 0)
return;
// Adjust the user control
foreach (var fm2014 in FM2014.RegisteredFm2014s.Where(x => x.IsLoggedOn))
{
var idx = fm2014.Address - 1;
var ucFM2014 = (UcFM2014Device)UcFM2014s[idx];
ucFM2014.EnableMeasurements(CAL_MEASURE_COUNT);
//TODO THW test assignment
fm2014.RefRequiredTimeMeasurement_pulses = 500;
fm2014.DutRequiredTimeMeasurement_pulses = 500;
fm2014.DutToRefCalibrationToleranceMax_percent = 1.1;
fm2014.DutToRefCalibrationToleranceMin_percent = -0.5;
fm2014.DoublePulseDeadtime_ms = 0.0;
//TODO THW Test assignment
// Set initial required pulses as those are static upon the entire measurement
ucFM2014.SetValue(CAL_LBL_IDX_REF_REQ_PLS, $"{fm2014.RefRequiredTimeMeasurement_pulses}");
ucFM2014.SetValue(CAL_LBL_IDX_DUT_REQ_PLS, $"{fm2014.DutRequiredTimeMeasurement_pulses}");
}
if (FM2014.CalibrationMeasurement())
{
// Progress will be fed by the calibration routine
_autoProgressBar = false;
UpdateContentControl(btnDutToRefCalibration, Properties.Resources.StrBtnStopCalibration);
UiElmEnable(btnDutToRefCalibration, true);
}
}
else
{
_autoProgressBar = false;
// Deactivate the button temporary to avoid repeated execution as the reset takes a certain time
UiElmEnable(btnDutToRefCalibration, false);
FM2014.ResetHardwareAllDevices();
ActionControl(false);
UpdateContentControl(btnDutToRefCalibration, Properties.Resources.StrBtnStartCalibration);
}
}
/// <summary>
/// Start and stop the DUT to REF regulation measurement.
/// </summary>
@ -1149,19 +1262,18 @@ namespace Sensus.Ui.FM2014TestBench
if (FM2014.SharedCyclicMeasSequ == CyclicMeasSequ.IDLE)
{
ActionControl(true);
// Remove old measurement labels
// Disable and hide dynamic measurement labels
foreach (var measLbl in MeasurementLabels)
UiElmEnable(measLbl, false, false);
// Set the measurement labels
UpdateContentControl(MeasurementLabels[REG_LBL_IDX_TOLERANCE],
Properties.Resources.StrLblActualMeasuredToleranceDutToRef);
UpdateContentControl(MeasurementLabels[REG_LBL_IDX_DUT_TO_REF_TOL],
Properties.Resources.StrLblMeasuredDutToRefTolerance);
UpdateContentControl(MeasurementLabels[REG_LBL_IDX_REF_FREQU],
Properties.Resources.StrLblRefFrequencyHz);
UpdateContentControl(MeasurementLabels[REG_LBL_IDX_FLOW_RATE],
Properties.Resources.StrLblActualMeasuredFlowRate);
UiElmEnable(MeasurementLabels[REG_LBL_IDX_TOLERANCE], true);
Properties.Resources.StrLblMeasuredFlowRate);
UiElmEnable(MeasurementLabels[REG_LBL_IDX_DUT_TO_REF_TOL], true);
UiElmEnable(MeasurementLabels[REG_LBL_IDX_REF_FREQU], true);
UiElmEnable(MeasurementLabels[REG_LBL_IDX_FLOW_RATE], true);
@ -1238,7 +1350,8 @@ namespace Sensus.Ui.FM2014TestBench
}
/// <summary>
/// Attenuation item has changed.
/// FM2014 current attenuation item has changed:
/// - This will dispatch the new value to all FM2014s.
/// </summary>
/// <remarks date="2026-Jan-18" author="Thomas Wiedebusch">
/// - Initial.
@ -1253,13 +1366,15 @@ namespace Sensus.Ui.FM2014TestBench
Dispatcher.Invoke(() =>
{
if (byte.TryParse(cbxAttenuation.SelectedItem.ToString(), out var attenuation) &&
attenuation > 0 && attenuation <= 9 && firstFm2014.Attenuation != attenuation)
attenuation >= FM2014.ATTENUATION_MIN &&
attenuation <= FM2014.ATTENUATION_MAX &&
firstFm2014.FM2014CurrentOutputAttenuation != attenuation)
{
firstFm2014.Attenuation = attenuation;
firstFm2014.FM2014CurrentOutputAttenuation = attenuation;
// Dispatch settings to all connected FM2014
foreach (var fm2014 in FM2014.RegisteredFm2014s)
{
fm2014.Attenuation = firstFm2014.Attenuation;
fm2014.FM2014CurrentOutputAttenuation = attenuation;
}
_regulationSetupHasChanged = true;
btnSaveRegulationSetup.IsEnabled = true;
@ -1285,7 +1400,8 @@ namespace Sensus.Ui.FM2014TestBench
}
/// <summary>
/// Safe standalone measurement setup.
/// Safe standalone measurement setup:
/// - This will save the setup in all FM2014s.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
@ -1304,7 +1420,8 @@ namespace Sensus.Ui.FM2014TestBench
/// <summary>
/// Switch between damped or undamped tolerance display. This can be changed during the
/// 'Regulation Measurement' on the fly as it will just collect a different dataset and
/// not change anything on the measurement setup.
/// not change anything on the measurement setup:
/// - This will dispatch the new value to all FM2014s.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
@ -1389,7 +1506,8 @@ namespace Sensus.Ui.FM2014TestBench
}
/// <summary>
/// After manual input of the REF pulses per cubic meter the scale REF to DUT has to be recalculated
/// After manual input of the REF pulses per cubic meter the scale REF to DUT has to be recalculated:
/// - This will dispatch the new value to all FM2014s.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
@ -1487,7 +1605,8 @@ namespace Sensus.Ui.FM2014TestBench
}
/// <summary>
/// After manual input of the DUT pulses per cubic meter the scale REF to DUT has to be recalculated
/// After manual input of the DUT pulses per cubic meter the scale REF to DUT has to be recalculated:
/// - This will dispatch the new value to all FM2014s.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
@ -1516,10 +1635,10 @@ namespace Sensus.Ui.FM2014TestBench
var backupPulses_per_cm = firstFm2014.Dut_pulse_per_cm;
// Setup all FM2014s
if (int.TryParse(tbxDutPulsesPerCm.Text, out var pulses_per_cm))
if (ushort.TryParse(tbxDutPulsesPerCm.Text, out var pulses_per_cm))
{
// Try to set the new calculated REF pulses limited by the property setter
firstFm2014.Dut_pulse_per_cm = (UInt32)pulses_per_cm;
firstFm2014.Dut_pulse_per_cm = pulses_per_cm;
// Dispatch settings to all connected FM2014!!!!
foreach (var fm2014 in FM2014.RegisteredFm2014s)
@ -1586,7 +1705,8 @@ namespace Sensus.Ui.FM2014TestBench
/// <summary>
/// After manual input of measured weight scale or reservoir in liters this will calculate the
/// REF pulses per cubic meter and copy from REF pulses per cubic meter in 'Manual REF Calibration'
/// to 'Regulation Setup'.
/// to 'Regulation Setup':
/// - This will dispatch the new value to all FM2014s.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
@ -1667,7 +1787,7 @@ namespace Sensus.Ui.FM2014TestBench
}
}
private void chkSlot1_Click(Object sender, RoutedEventArgs e)
private void chkAnySlot_Click(Object sender, RoutedEventArgs e)
{
_configSetupHasChanged = true;
}

View File

@ -187,7 +187,7 @@ namespace Sensus.Ui.Fm2014TestBench.Properties {
}
/// <summary>
/// Looks up a localized string similar to Manual Calibration REF to Weight-Scale.
/// Looks up a localized string similar to REF to Volume Calibration.
/// </summary>
internal static string StrGbxManualRefCalibration {
get {
@ -205,20 +205,11 @@ namespace Sensus.Ui.Fm2014TestBench.Properties {
}
/// <summary>
/// Looks up a localized string similar to Flow Rate [m³/h]:.
/// Looks up a localized string similar to Actual Process:.
/// </summary>
internal static string StrLblActualMeasuredFlowRate {
internal static string StrLblActualProcessStatus {
get {
return ResourceManager.GetString("StrLblActualMeasuredFlowRate", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to DUT/REF Tolerance [%]:.
/// </summary>
internal static string StrLblActualMeasuredToleranceDutToRef {
get {
return ResourceManager.GetString("StrLblActualMeasuredToleranceDutToRef", resourceCulture);
return ResourceManager.GetString("StrLblActualProcessStatus", resourceCulture);
}
}
@ -232,7 +223,7 @@ namespace Sensus.Ui.Fm2014TestBench.Properties {
}
/// <summary>
/// Looks up a localized string similar to Serial Port.
/// Looks up a localized string similar to Serial Port:.
/// </summary>
internal static string StrLblComPort {
get {
@ -241,11 +232,29 @@ namespace Sensus.Ui.Fm2014TestBench.Properties {
}
/// <summary>
/// Looks up a localized string similar to DUT [pulses/m³]:.
/// Looks up a localized string similar to Double Pulses Deadtime:.
/// </summary>
internal static string StrLblDutPulsesPerCm {
internal static string StrLblDoublePulseDeadTime {
get {
return ResourceManager.GetString("StrLblDutPulsesPerCm", resourceCulture);
return ResourceManager.GetString("StrLblDoublePulseDeadTime", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to DUT/REF Tolerance max [%]:.
/// </summary>
internal static string StrLblDutToRefToleranceMax {
get {
return ResourceManager.GetString("StrLblDutToRefToleranceMax", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to DUT/REF Tolerance min [%]:.
/// </summary>
internal static string StrLblDutToRefToleranceMin {
get {
return ResourceManager.GetString("StrLblDutToRefToleranceMin", resourceCulture);
}
}
@ -322,7 +331,7 @@ namespace Sensus.Ui.Fm2014TestBench.Properties {
}
/// <summary>
/// Looks up a localized string similar to Measured DUT [pulses]:.
/// Looks up a localized string similar to DUT Captured Pulses: .
/// </summary>
internal static string StrLblMeasuredDutPulses {
get {
@ -331,7 +340,34 @@ namespace Sensus.Ui.Fm2014TestBench.Properties {
}
/// <summary>
/// Looks up a localized string similar to Measured REF [pulses]:.
/// Looks up a localized string similar to DUT Measured Time [s]:.
/// </summary>
internal static string StrLblMeasuredDutTime {
get {
return ResourceManager.GetString("StrLblMeasuredDutTime", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to DUT/REF Tolerance [%]:.
/// </summary>
internal static string StrLblMeasuredDutToRefTolerance {
get {
return ResourceManager.GetString("StrLblMeasuredDutToRefTolerance", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Flow Rate [m³/h]:.
/// </summary>
internal static string StrLblMeasuredFlowRate {
get {
return ResourceManager.GetString("StrLblMeasuredFlowRate", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to REF Captured Pulses:.
/// </summary>
internal static string StrLblMeasuredRefPulses {
get {
@ -339,12 +375,21 @@ namespace Sensus.Ui.Fm2014TestBench.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to REF Measured Time [s]:.
/// </summary>
internal static string StrLblMeasuredRefTime {
get {
return ResourceManager.GetString("StrLblMeasuredRefTime", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Volume [liters]:.
/// </summary>
internal static string StrLblMeasuredWeightScaleVolume {
internal static string StrLblMeasuredVolume {
get {
return ResourceManager.GetString("StrLblMeasuredWeightScaleVolume", resourceCulture);
return ResourceManager.GetString("StrLblMeasuredVolume", resourceCulture);
}
}
@ -385,11 +430,29 @@ namespace Sensus.Ui.Fm2014TestBench.Properties {
}
/// <summary>
/// Looks up a localized string similar to Process status.
/// Looks up a localized string similar to Overall Process:.
/// </summary>
internal static string StrLblProcessStatus {
internal static string StrLblOverallProcessStatus {
get {
return ResourceManager.GetString("StrLblProcessStatus", resourceCulture);
return ResourceManager.GetString("StrLblOverallProcessStatus", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to DUT Pulse Ratio [pulses/m³]:.
/// </summary>
internal static string StrLblRatioDutPulsesPerCm {
get {
return ResourceManager.GetString("StrLblRatioDutPulsesPerCm", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to REF Pulse Ratio [pulses/m³]:.
/// </summary>
internal static string StrLblRatioRefPulsesPerCm {
get {
return ResourceManager.GetString("StrLblRatioRefPulsesPerCm", resourceCulture);
}
}
@ -403,16 +466,43 @@ namespace Sensus.Ui.Fm2014TestBench.Properties {
}
/// <summary>
/// Looks up a localized string similar to REF [pulses/m³]:.
/// Looks up a localized string similar to DUT Remaining Pulses:.
/// </summary>
internal static string StrLblRefPulsesPerCm {
internal static string StrLblRemainingDutPulses {
get {
return ResourceManager.GetString("StrLblRefPulsesPerCm", resourceCulture);
return ResourceManager.GetString("StrLblRemainingDutPulses", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Scale REF/DUT [norm]:.
/// Looks up a localized string similar to REF Remaining Pulses:.
/// </summary>
internal static string StrLblRemainingRefPulses {
get {
return ResourceManager.GetString("StrLblRemainingRefPulses", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to DUT Required Pulses:.
/// </summary>
internal static string StrLblRequiredDutPulses {
get {
return ResourceManager.GetString("StrLblRequiredDutPulses", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to REF Required Pulses:.
/// </summary>
internal static string StrLblRequiredRefPulses {
get {
return ResourceManager.GetString("StrLblRequiredRefPulses", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to REF/DUT Ratio [norm]:.
/// </summary>
internal static string StrLblScaleRefToDut {
get {

View File

@ -168,17 +168,17 @@
<data name="StrLblFM2014Connected" xml:space="preserve">
<value>ONLINE</value>
</data>
<data name="StrLblRefPulsesPerCm" xml:space="preserve">
<value>REF [Pulse/m³]:</value>
<data name="StrLblRatioRefPulsesPerCm" xml:space="preserve">
<value>REF Pulsratio [Pulse/m³]:</value>
</data>
<data name="StrGbxRegulationSetup" xml:space="preserve">
<value>Regulierungseinstellungen</value>
</data>
<data name="StrLblDutPulsesPerCm" xml:space="preserve">
<value>DUT [Pulse/m³]:</value>
<data name="StrLblRatioDutPulsesPerCm" xml:space="preserve">
<value>DUT Pulsratio [Pulse/m³]:</value>
</data>
<data name="StrLblScaleRefToDut" xml:space="preserve">
<value>REF/DUT Relation [norm]:</value>
<value>REF/DUT Ratio [norm]:</value>
</data>
<data name="StrLblAttenuation" xml:space="preserve">
<value>Dämpfung []:</value>
@ -187,22 +187,22 @@
<value>Speichern</value>
</data>
<data name="StrGbxManualRefCalibration" xml:space="preserve">
<value>Handkalibrierung REF zu Waage</value>
<value>REF zu Volumen Kalibrierung</value>
</data>
<data name="StrLblMeasuredRefPulses" xml:space="preserve">
<value>Gemessene REF [Pulse]:</value>
<value>REF Erfaßte Imulse:</value>
</data>
<data name="StrLblMeasuredWeightScaleVolume" xml:space="preserve">
<data name="StrLblMeasuredVolume" xml:space="preserve">
<value>Volumen [Liter]:</value>
</data>
<data name="StrGbxDutToRefRegulation" xml:space="preserve">
<value>DUT zu REF Regulierung</value>
</data>
<data name="StrLblActualMeasuredFlowRate" xml:space="preserve">
<data name="StrLblMeasuredFlowRate" xml:space="preserve">
<value>Durchfluß [m³/h]:</value>
</data>
<data name="StrLblActualMeasuredToleranceDutToRef" xml:space="preserve">
<value>DUT/REF Abweichung [%]:</value>
<data name="StrLblMeasuredDutToRefTolerance" xml:space="preserve">
<value>DUT/REF Toleranz [%]:</value>
</data>
<data name="StrChkUseDampedTolerance" xml:space="preserve">
<value>Toleranzdämpfung Ein</value>
@ -210,8 +210,8 @@
<data name="StrLblWaitingForMeterResponse" xml:space="preserve">
<value>WARTE AUF FM2014 ANTWORT</value>
</data>
<data name="StrLblProcessStatus" xml:space="preserve">
<value>Prozeßfortschritt</value>
<data name="StrLblActualProcessStatus" xml:space="preserve">
<value>Aktueller Prozeß:</value>
</data>
<data name="StrLblTime" xml:space="preserve">
<value>Zeit [min:s]:</value>
@ -223,7 +223,7 @@
<value>REF Frequenz [Hz]:</value>
</data>
<data name="StrLblMeasuredDutPulses" xml:space="preserve">
<value>Gemessene DUT [Pulse]:</value>
<value>DUT Erfaßte Impulse:</value>
</data>
<data name="StrGbxDutToRefCalibration" xml:space="preserve">
<value>DUT zu REF Kalibrierung</value>
@ -252,4 +252,34 @@
<data name="StrLblSlotSelection" xml:space="preserve">
<value>Einbauplatz:</value>
</data>
<data name="StrLblRequiredRefPulses" xml:space="preserve">
<value>REF Erfordeliche Pulse:</value>
</data>
<data name="StrLblRemainingRefPulses" xml:space="preserve">
<value>REF Verbleibende Pulse:</value>
</data>
<data name="StrLblRequiredDutPulses" xml:space="preserve">
<value>DUT Erforderliche Pulse:</value>
</data>
<data name="StrLblRemainingDutPulses" xml:space="preserve">
<value>DUT Verbleibende Pulse:</value>
</data>
<data name="StrLblMeasuredRefTime" xml:space="preserve">
<value>REF Gemessene Zeit [s]:</value>
</data>
<data name="StrLblMeasuredDutTime" xml:space="preserve">
<value>DUT Gemessene Zeit [s]:</value>
</data>
<data name="StrLblDoublePulseDeadTime" xml:space="preserve">
<value>Doppelimpulstotozeit:</value>
</data>
<data name="StrLblDutToRefToleranceMin" xml:space="preserve">
<value>DUT/REF Toleranz min [%]:</value>
</data>
<data name="StrLblDutToRefToleranceMax" xml:space="preserve">
<value>DUT/REF Toleranz max [%]:</value>
</data>
<data name="StrLblOverallProcessStatus" xml:space="preserve">
<value>Gesamtprozeß:</value>
</data>
</root>

View File

@ -168,17 +168,17 @@
<data name="StrLblFM2014Connected" xml:space="preserve">
<value>ONLINE</value>
</data>
<data name="StrLblRefPulsesPerCm" xml:space="preserve">
<value>REF [pulses/m³]:</value>
<data name="StrLblRatioRefPulsesPerCm" xml:space="preserve">
<value>REF Pulse Ratio [pulses/m³]:</value>
</data>
<data name="StrGbxRegulationSetup" xml:space="preserve">
<value>Regulation Setup</value>
</data>
<data name="StrLblDutPulsesPerCm" xml:space="preserve">
<value>DUT [pulses/m³]:</value>
<data name="StrLblRatioDutPulsesPerCm" xml:space="preserve">
<value>DUT Pulse Ratio [pulses/m³]:</value>
</data>
<data name="StrLblScaleRefToDut" xml:space="preserve">
<value>Scale REF/DUT [norm]:</value>
<value>REF/DUT Ratio [norm]:</value>
</data>
<data name="StrLblAttenuation" xml:space="preserve">
<value>Attenuation []:</value>
@ -187,21 +187,21 @@
<value>Save</value>
</data>
<data name="StrGbxManualRefCalibration" xml:space="preserve">
<value>Manual Calibration REF to Weight-Scale</value>
<value>REF to Volume Calibration</value>
</data>
<data name="StrLblMeasuredRefPulses" xml:space="preserve">
<value>Measured REF [pulses]:</value>
<value>REF Captured Pulses:</value>
</data>
<data name="StrLblMeasuredWeightScaleVolume" xml:space="preserve">
<data name="StrLblMeasuredVolume" xml:space="preserve">
<value>Volume [liters]:</value>
</data>
<data name="StrGbxDutToRefRegulation" xml:space="preserve">
<value>DUT to REF Regulation</value>
</data>
<data name="StrLblActualMeasuredFlowRate" xml:space="preserve">
<data name="StrLblMeasuredFlowRate" xml:space="preserve">
<value>Flow Rate [m³/h]:</value>
</data>
<data name="StrLblActualMeasuredToleranceDutToRef" xml:space="preserve">
<data name="StrLblMeasuredDutToRefTolerance" xml:space="preserve">
<value>DUT/REF Tolerance [%]:</value>
</data>
<data name="StrChkUseDampedTolerance" xml:space="preserve">
@ -210,8 +210,8 @@
<data name="StrLblWaitingForMeterResponse" xml:space="preserve">
<value>WAITING FOR FM2014 RESPONSE</value>
</data>
<data name="StrLblProcessStatus" xml:space="preserve">
<value>Process status</value>
<data name="StrLblActualProcessStatus" xml:space="preserve">
<value>Actual Process:</value>
</data>
<data name="StrLblTime" xml:space="preserve">
<value>Time [min:s]:</value>
@ -223,7 +223,7 @@
<value>REF Frequency [Hz]:</value>
</data>
<data name="StrLblMeasuredDutPulses" xml:space="preserve">
<value>Measured DUT [pulses]:</value>
<value>DUT Captured Pulses: </value>
</data>
<data name="StrGbxDutToRefCalibration" xml:space="preserve">
<value>DUT to REF Calibration</value>
@ -232,7 +232,7 @@
<value>_Options</value>
</data>
<data name="StrLblComPort" xml:space="preserve">
<value>Serial Port</value>
<value>Serial Port:</value>
</data>
<data name="StrLblOptionsLogin" xml:space="preserve">
<value>_Login</value>
@ -252,4 +252,34 @@
<data name="StrLblSlotSelection" xml:space="preserve">
<value>Slot Selection:</value>
</data>
<data name="StrLblRequiredRefPulses" xml:space="preserve">
<value>REF Required Pulses:</value>
</data>
<data name="StrLblRemainingRefPulses" xml:space="preserve">
<value>REF Remaining Pulses:</value>
</data>
<data name="StrLblRequiredDutPulses" xml:space="preserve">
<value>DUT Required Pulses:</value>
</data>
<data name="StrLblRemainingDutPulses" xml:space="preserve">
<value>DUT Remaining Pulses:</value>
</data>
<data name="StrLblMeasuredRefTime" xml:space="preserve">
<value>REF Measured Time [s]:</value>
</data>
<data name="StrLblMeasuredDutTime" xml:space="preserve">
<value>DUT Measured Time [s]:</value>
</data>
<data name="StrLblDoublePulseDeadTime" xml:space="preserve">
<value>Double Pulses Deadtime:</value>
</data>
<data name="StrLblDutToRefToleranceMin" xml:space="preserve">
<value>DUT/REF Tolerance min [%]:</value>
</data>
<data name="StrLblDutToRefToleranceMax" xml:space="preserve">
<value>DUT/REF Tolerance max [%]:</value>
</data>
<data name="StrLblOverallProcessStatus" xml:space="preserve">
<value>Overall Process:</value>
</data>
</root>