Fix - Handle scale underload condition

- Added Underload measurement state
- Detect underload responses from Mettler Toledo scales
- Automatically zero the scale after underload detection
- Restart mass measurement after successful zeroing
- Prevent zeroing response from being used as a valid measurement
- Preserve measurement stability by clearing buffered readings after underload
This commit is contained in:
Marek Frniak 2026-07-13 13:56:26 +02:00
parent 38d28599ad
commit 0075362f92
9 changed files with 109 additions and 19 deletions

View File

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// Build Number
// Revision
//
[assembly: AssemblyVersion("3.9.3069.1")]
[assembly: AssemblyFileVersion("3.9.3069.1")]
[assembly: AssemblyVersion("3.9.3069.8")]
[assembly: AssemblyFileVersion("3.9.3069.8")]

View File

@ -10,7 +10,8 @@ namespace TBF.Rig
{
Valid,
Overload,
Failed,
Underload,
Failed,
Busy,
Busy1, ///
Busy2, /// Used by Mettler-Toledo Multi to distinguish which scale was queried
@ -86,6 +87,7 @@ namespace TBF.Rig
AmbientDone,
ScaleDone,
ScaleUnderload,
ScaleOverload,
ScaleTimeout,
PressureDone,

View File

@ -34,12 +34,14 @@ namespace TBF.Rig.MettlerToledo.Standard
bool measurementCompleted;
int timeout;
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="scale">Balance device instance</param>
/// <param name="result">Reference to the measured mass in kg</param>
/// <param name="readingsCount">Required mass readings count (>= 4)</param>
bool zeroingAfterUnderload;
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="scale">Balance device instance</param>
/// <param name="result">Reference to the measured mass in kg</param>
/// <param name="readingsCount">Required mass readings count (>= 4)</param>
/// <param name="maxSpread">Maximum spread of measurements in kg (otherwise the measurement continues)</param>
/// <param name="method">Method: false = slow (precise), true = fast (immediate)</param>
public ReadStableMassOp(GenericDevices.IScale scale, ref DoubleBox result, int delayBefore, MassMethod method,
@ -89,6 +91,7 @@ namespace TBF.Rig.MettlerToledo.Standard
startTime = StateMachine.Time;
currentReadingsCount = 0;
measurementCompleted = false;
zeroingAfterUnderload = false;
if (delayBefore == 0 && scale.Activity == Activity.Idle)
{
@ -136,7 +139,34 @@ namespace TBF.Rig.MettlerToledo.Standard
return Event.None; /// Wait for a mass measurement
}
if (scale.MsrmntState == MsrmntState.Valid)
if (scale.MsrmntState == MsrmntState.Underload)
{
log.WarnFormat(
"ReadStableMassOp.Run() ... scale underload detected, zeroing scale");
currentReadingsCount = 0;
Array.Clear(massReadings, 0, massReadings.Length);
Array.Clear(sortedMassReadings, 0, sortedMassReadings.Length);
zeroingAfterUnderload = true;
scale.SendZeroWhenStableCmd();
scale.Activity = Activity.RunningOperation;
return Event.None;
}
if (zeroingAfterUnderload && scale.MsrmntState == MsrmntState.Valid)
{
log.InfoFormat(
"ReadStableMassOp.Run() ... scale zeroing after underload completed, restarting measurement");
zeroingAfterUnderload = false;
StartMeasurement();
return Event.None;
}
if (scale.MsrmntState == MsrmntState.Valid)
{
/// Save the measurement
if (currentReadingsCount < totalReadingsCount)

View File

@ -78,6 +78,13 @@ namespace TBF.Rig.MettlerToledo.Standard
return Event.ScaleOverload;
}
if (scale.MsrmntState == MsrmntState.Underload)
{
tara.Val = scale.Capacity;
done = true;
return Event.ScaleUnderload;
}
if (scale.MsrmntState == MsrmntState.Valid)
{
tara.Val = scale.Mass;

View File

@ -68,6 +68,12 @@ namespace TBF.Rig.MettlerToledo.Standard
if (scale.MsrmntState == MsrmntState.Busy) return Event.Busy;
if (scale.MsrmntState == MsrmntState.Underload)
{
done = true;
return Event.ScaleUnderload;
}
if (scale.MsrmntState == MsrmntState.Overload)
{
done = true;

View File

@ -68,6 +68,7 @@ namespace TBF.Rig.Scales.MettlerToledo
{
WaitingBeforeMeasurment,
MassMeasurement,
ZeroingAfterUnderload,
}
OpState opState;
@ -142,14 +143,45 @@ namespace TBF.Rig.Scales.MettlerToledo
return Event.ScaleDone;
}
if (scale.MsrmntState == MsrmntState.Busy)
{
/// Measurement is in progress - resend command if timeout occurs
if (scale.MsrmntTime >= timeout) StartMeasurement();
return Event.None; /// Wait for a mass measurement
}
if (scale.MsrmntState == MsrmntState.Busy)
{
/// The command is still being processed - resend it after timeout.
if (scale.MsrmntTime >= timeout)
{
if (opState == OpState.ZeroingAfterUnderload)
scale.SendZeroWhenStableCmd();
else
StartMeasurement();
}
if (scale.MsrmntState == MsrmntState.Valid)
return Event.None;
}
if (scale.MsrmntState == MsrmntState.Underload)
{
log.Warn("ReadStableMassOp.Run() ... scale underload detected, zeroing scale");
currentReadingsCount = 0;
Array.Clear(massReadings, 0, massReadings.Length);
Array.Clear(sortedMassReadings, 0, sortedMassReadings.Length);
opState = OpState.ZeroingAfterUnderload;
scale.SendZeroWhenStableCmd();
return Event.None;
}
if (opState == OpState.ZeroingAfterUnderload && scale.MsrmntState == MsrmntState.Valid)
{
log.Info("ReadStableMassOp.Run() ... scale zeroing completed, restarting mass measurement");
opState = OpState.MassMeasurement;
StartMeasurement();
return Event.None;
}
if (scale.MsrmntState == MsrmntState.Valid)
{
/// Save the measurement
if (currentReadingsCount < totalReadingsCount)
@ -167,7 +199,7 @@ namespace TBF.Rig.Scales.MettlerToledo
}
}
if (currentReadingsCount >= totalReadingsCount)
if (currentReadingsCount >= totalReadingsCount)
{
Array.Copy(massReadings, sortedMassReadings, totalReadingsCount);
Array.Sort(sortedMassReadings);

View File

@ -401,7 +401,7 @@ namespace TBF.Rig.Scales.MettlerToledo
{
/// Invalid value : Scale is in underload range
mass = 0;
msrmntState = MsrmntState.Failed;
msrmntState = MsrmntState.Underload;
}
else if ((proto == Protocol.ID1 && field.Length == 1 && field[0] == "SI+") ||
(proto == Protocol.SICS && field.Length == 2 && field[0] == "S" && field[1] == "+") ||

View File

@ -71,6 +71,13 @@ namespace TBF.Rig.Scales.MettlerToledo
if (scale.MsrmntState == MsrmntState.Busy) return Event.Busy;
if (scale.MsrmntState == MsrmntState.Underload)
{
tara.Val = scale.Capacity;
done = true;
return Event.ScaleUnderload;
}
if (scale.MsrmntState == MsrmntState.Overload)
{
tara.Val = scale.Capacity;

View File

@ -74,6 +74,12 @@ namespace TBF.Rig.Scales.MettlerToledo
return Event.ScaleOverload;
}
if (scale.MsrmntState == MsrmntState.Underload)
{
done = true;
return Event.ScaleUnderload;
}
if (scale.MsrmntState == MsrmntState.Valid)
{
done = true;