From b060068a9584ed4520cc3fd2dd78e05e8e7e9e97 Mon Sep 17 00:00:00 2001 From: Milan Hanajik Date: Wed, 14 Nov 2018 15:49:43 +0100 Subject: [PATCH] (1) Nivotrack.ReadStableLevelOp implemented, (2) MettlerToledo.Standard.ReadStableMassOp bug fix, (3) UpdateWeights() clean-up, ver. 2.18.1065 --- TBF/BenchControl/Elde/ControlBoardDev.cs | 19 +-- TBF/BenchControl/Hart/Nivotrack/Nivotrack.cs | 150 ++++++++++++++---- .../Standard/ReadStableMassOp.cs | 17 +- TBF/Properties/AssemblyInfo.cs | 4 +- 4 files changed, 133 insertions(+), 57 deletions(-) diff --git a/TBF/BenchControl/Elde/ControlBoardDev.cs b/TBF/BenchControl/Elde/ControlBoardDev.cs index 65fc1e231..52e5e2878 100644 --- a/TBF/BenchControl/Elde/ControlBoardDev.cs +++ b/TBF/BenchControl/Elde/ControlBoardDev.cs @@ -222,34 +222,27 @@ namespace TBF.BenchControl.Elde } - static bool doMassesVolumesLog = true; - /// public void UpdateWeights() { + /// Mettler-Toledo scales for (int i = 0; i < MettlerToledo.Standard.BalanceDev.BalancesCount; i++) { - double mass = MettlerToledo.Standard.BalanceDev.Masses[i]; - controlCom.SetWeight(i, mass); - if (doMassesVolumesLog) log.DebugFormat("UpdateWeights() : ix={0} mass={1}", i, mass); + controlCom.SetWeight(i, MettlerToledo.Standard.BalanceDev.Masses[i]); } + /// Mettler-Toledo-multi scales (Badger Brno, ...) for (int i = 0; i < MettlerToledo.Multi.BalanceDev.BalancesCount; i++) { - double mass = MettlerToledo.Multi.BalanceDev.Masses[i]; - controlCom.SetWeight(i, mass); - if (doMassesVolumesLog) log.DebugFormat("UpdateWeights() : ix={0} mass={1}", i, mass); + controlCom.SetWeight(i, MettlerToledo.Multi.BalanceDev.Masses[i]); } + /// Tanks (CEVAK, ...) int firstTankIx = Math.Max(MettlerToledo.Standard.BalanceDev.BalancesCount, MettlerToledo.Multi.BalanceDev.BalancesCount); for (int i = 0; i < Various.TankWithLevelMsrmnt.Tank.TanksCount; i++) { - double volume = Various.TankWithLevelMsrmnt.Tank.Tanks[i].Volume; - controlCom.SetWeight(firstTankIx + i, volume); - if (doMassesVolumesLog) log.DebugFormat("UpdateWeights() : ix={0}, volume={1}", firstTankIx + i, volume); + controlCom.SetWeight(firstTankIx + i, Various.TankWithLevelMsrmnt.Tank.Tanks[i].Volume); } - - //doMassesVolumesLog = false; /// When this line is uncommented logging is done only once on startup } diff --git a/TBF/BenchControl/Hart/Nivotrack/Nivotrack.cs b/TBF/BenchControl/Hart/Nivotrack/Nivotrack.cs index daf8d738f..cdd72f98e 100644 --- a/TBF/BenchControl/Hart/Nivotrack/Nivotrack.cs +++ b/TBF/BenchControl/Hart/Nivotrack/Nivotrack.cs @@ -3,11 +3,6 @@ /// using System; using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO.Ports; -using System.Text; -using System.Threading; using Config.Entities; using log4net; using TBF.BenchControl.Generic; @@ -22,20 +17,30 @@ namespace TBF.BenchControl.Hart.Nivotrack /// public class Nivotrack : ComponentBase, IDevice, ILevelMeter, IOperation { + const int StableReadingsCount = 9; + private static readonly ILog log = LogManager.GetLogger(typeof(Nivotrack)); public override string ToString() { return string.Format("{0}({1})", Cfg.Name, Cfg.ToString(-1)); } - private readonly NivotrackCfg nivotrackCfg; - private readonly IHart hart; + readonly NivotrackCfg nivotrackCfg; + readonly IHart hart; - bool readingValid; - double rawLevel_mm; public double Level { get { return ReadLevel(); } } - DoubleBox levelBox; - double sdev; + double rawLevel_mm; + bool isRawLevelValid; - enum CurrentOp + /// For stable measurement calculation + double maxSDev; + double[] levelReadings; + double[] sortedLevelReadings; + int currentReadingsCount; + + bool measurementCompleted; /// stableMeasurementCompleted + + DoubleBox levelBox; + /// + enum CurrentOp { None, ReadLevel, @@ -60,6 +65,9 @@ namespace TBF.BenchControl.Hart.Nivotrack hart = (IHart)TbfComponents.FindComponent(cfg.ParentName, components); if (hart == null) throw new Exception("Cannot find " + Name + " parent"); + levelReadings = new double[StableReadingsCount]; + sortedLevelReadings = new double[StableReadingsCount]; + log.Debug(this.ToString()); } @@ -68,7 +76,7 @@ namespace TBF.BenchControl.Hart.Nivotrack if (nivotrackCfg.DebugLevel == DebugMode.Simulate) return; rawLevel_mm = 0; - readingValid = false; + isRawLevelValid = false; } @@ -122,11 +130,8 @@ namespace TBF.BenchControl.Hart.Nivotrack byte unitsID = data[6]; byte[] floatData = new byte[] { data[10], data[9], data[8], data[7] }; rawLevel_mm = System.BitConverter.ToSingle(floatData, 0); - readingValid = true; - - string msg = string.Format("{0} : Received water level = {1} mm, State = {2}", Name, rawLevel_mm, state.ToString("X4")); - Debug.WriteLine(msg); - log.Info(msg); + isRawLevelValid = true; + log.InfoFormat("{0} : Received water level = {1} mm, State = {2}", Name, rawLevel_mm, state.ToString("X4")); } else if ((data.Length == 7) && (data[0] == (byte)Mark.ShortFrameSlave2Master) && (data[2] == (byte)Cmd.ReadPrimaryVar) @@ -136,9 +141,8 @@ namespace TBF.BenchControl.Hart.Nivotrack /// A frame with a status only /// ushort state = (ushort)(256 * data[4] + data[5]); - string msg = string.Format("{0} : State = {1}", Name, state.ToString("X4")); - Debug.WriteLine(msg); - log.Info(msg); + isRawLevelValid = false; + log.InfoFormat("{0} : State = {1}", Name, state.ToString("X4")); } } } @@ -176,21 +180,31 @@ namespace TBF.BenchControl.Hart.Nivotrack } /// Reference to the operation - public IOperation ReadStableLevelOp(ref DoubleBox levelBox, double sdev) + public IOperation ReadStableLevelOp(ref DoubleBox levelBox, double maxSDev) { if (currentOp != CurrentOp.None) throw new Exception("Sequence error"); this.levelBox = levelBox; - this.sdev = sdev; + this.maxSDev = maxSDev; currentOp = CurrentOp.ReadStableLevel; + return this; } /// Start this operation public void Start() { - if (readingValid && (levelBox != null)) + if (currentOp == CurrentOp.ReadLevel) { - levelBox.Val = ReadLevel(); + if (isRawLevelValid && (levelBox != null)) levelBox.Val = ReadLevel(); + } + else if (currentOp == CurrentOp.ReadStableLevel) + { + currentReadingsCount = 0; + measurementCompleted = false; + if (isRawLevelValid) + { + levelReadings[currentReadingsCount++] = ReadLevel(); + } } } @@ -198,16 +212,82 @@ namespace TBF.BenchControl.Hart.Nivotrack /// Event.ResultsPrinted public Event Run() { - if (readingValid && (levelBox != null)) - { - levelBox.Val = ReadLevel(); - return Event.LevelDone; - } - else - { - return Event.Busy; - } - } + if (measurementCompleted) + { + if ((currentOp == CurrentOp.ReadLevel) && (levelBox != null)) levelBox.Val = ReadLevel(); + return Event.LevelDone; + } + + if ((currentOp == CurrentOp.ReadLevel) && isRawLevelValid) + { + if (levelBox != null) levelBox.Val = ReadLevel(); + measurementCompleted = true; + return Event.LevelDone; + } + else if ((currentOp == CurrentOp.ReadStableLevel) && isRawLevelValid) + { + /// + /// Read new level and put it into a FIFO buffer + /// + if (currentReadingsCount < StableReadingsCount) + { + levelReadings[currentReadingsCount++] = ReadLevel(); + } + else + { + /// Shift data in the (already full) buffer, save the mass into the last buffer item + for (int i = 1; i < StableReadingsCount; i++) + { + levelReadings[i - 1] = levelReadings[i]; + } + levelReadings[StableReadingsCount - 1] = ReadLevel(); + } + + /// + /// Evaluate reading stability + /// + if (currentReadingsCount >= StableReadingsCount) + { + Array.Copy(levelReadings, sortedLevelReadings, StableReadingsCount); + Array.Sort(sortedLevelReadings); + + if (true) + { + /// Spread of values (except of the largest and the smalles value) must be <= maxSDev + + if ((sortedLevelReadings[StableReadingsCount - 2] - sortedLevelReadings[1]) <= maxSDev) + { + double massSum = 0; + for (int i = 1; i < StableReadingsCount - 1; i++) massSum += sortedLevelReadings[i]; + double ave = massSum / (StableReadingsCount - 2); + if (levelBox != null) levelBox.Val = ave; + measurementCompleted = true; + log.InfoFormat("ReadStableLevelOp.Run() ... valid level={0} ... returning LevelDone", ave); + return Event.LevelDone; + } + } + else + { + /// Standard deviation (except of the largest and the smalles value) must be <= maxSDev + double massSum = 0; + for (int i = 1; i < StableReadingsCount - 1; i++) massSum += sortedLevelReadings[i]; + double ave = massSum / (StableReadingsCount - 2); + double sdev = 0; + for (int i = 1; i < StableReadingsCount - 1; i++) sdev += ((sortedLevelReadings[i] - ave) * (sortedLevelReadings[i] - ave)); + + if (Math.Sqrt(sdev / (StableReadingsCount - 2)) <= maxSDev) + { + if (levelBox != null) levelBox.Val = ave; + measurementCompleted = true; + log.InfoFormat("ReadStableMassOp.Run() ... valid mass={0} ... returning Event.BalanceDone", ave); + return Event.LevelDone; + } + } + } + } + + return Event.Busy; + } /// Stop this operation public void Stop() diff --git a/TBF/BenchControl/MettlerToledo/Standard/ReadStableMassOp.cs b/TBF/BenchControl/MettlerToledo/Standard/ReadStableMassOp.cs index 4ef0ef059..3383dc38a 100644 --- a/TBF/BenchControl/MettlerToledo/Standard/ReadStableMassOp.cs +++ b/TBF/BenchControl/MettlerToledo/Standard/ReadStableMassOp.cs @@ -23,7 +23,8 @@ namespace TBF.BenchControl.MettlerToledo.Standard DoubleBox result; /// Operation specific - double[] massReadings; + double[] massReadings; + double[] sortedMassReadings; int currentReadingsCount; bool measurementCompleted; @@ -48,7 +49,8 @@ namespace TBF.BenchControl.MettlerToledo.Standard this.result = result; massReadings = new double[totalReadingsCount]; - currentReadingsCount = 0; + sortedMassReadings = new double[totalReadingsCount]; + currentReadingsCount = 0; measurementCompleted = false; log.Debug(this.ToString()); @@ -114,17 +116,18 @@ namespace TBF.BenchControl.MettlerToledo.Standard if (currentReadingsCount >= totalReadingsCount) { - Array.Sort(massReadings); + Array.Copy(massReadings, sortedMassReadings, totalReadingsCount); + Array.Sort(sortedMassReadings); #if STABLE_MASS_EXTRAS if (method == Config.Entities.MassMethod.Spread) { /// Immediate mass measurement, end condition calculated below - if ((massReadings[totalReadingsCount - 2] - massReadings[1]) <= maxSpread) + if ((sortedMassReadings[totalReadingsCount - 2] - sortedMassReadings[1]) <= maxSpread) { double massSum = 0; - for (int i = 1; i < totalReadingsCount - 1; i++) massSum += massReadings[i]; + for (int i = 1; i < totalReadingsCount - 1; i++) massSum += sortedMassReadings[i]; result.Val = (massSum / (totalReadingsCount - 2)); log.InfoFormat("ReadStableMassOp.Run() ... valid mass={0} ... returning Event.BalanceDone", result.Val); @@ -137,10 +140,10 @@ namespace TBF.BenchControl.MettlerToledo.Standard /// Immediate mass measurement, end condition calculated below double massSum = 0; - for (int i = 1; i < totalReadingsCount - 1; i++) massSum += massReadings[i]; + for (int i = 1; i < totalReadingsCount - 1; i++) massSum += sortedMassReadings[i]; double ave = (massSum / (totalReadingsCount - 2)); double sdev = 0; - for (int i = 1; i < totalReadingsCount - 1; i++) sdev += ((massReadings[i] - ave) * (massReadings[i] - ave)); + for (int i = 1; i < totalReadingsCount - 1; i++) sdev += ((sortedMassReadings[i] - ave) * (sortedMassReadings[i] - ave)); if (Math.Sqrt(sdev / (totalReadingsCount - 2)) <= maxSpread) { diff --git a/TBF/Properties/AssemblyInfo.cs b/TBF/Properties/AssemblyInfo.cs index f4cc0eee7..8494572c3 100644 --- a/TBF/Properties/AssemblyInfo.cs +++ b/TBF/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("2.18.1064.0")] -[assembly: AssemblyFileVersion("2.18.1064.0")] +[assembly: AssemblyVersion("2.18.1065.0")] +[assembly: AssemblyFileVersion("2.18.1065.0")]