/// /// Copyright (c) 2013-2015 Sensus Metering Systems /// Author: Milan Hanajik /// using System; using log4net; using TBF.Boxes; namespace TBF.BenchControl.MettlerToledo.Standard { /// /// Operation to read more mass values and average them to obtain a more accurate result. /// public class ReadStableMassOp : IOperation { private static readonly ILog log = LogManager.GetLogger(typeof(ReadStableMassOp)); public override string ToString() { return string.Format("ReadStableMassOp(.,{0},.)", totalReadingsCount); } /// Operation specific float[] massReadings; int currentReadingsCount; /// Set by the constructor BalanceDev balanceDev; int totalReadingsCount; float maxSpread; /// Maximum spread of measurements in kg (otherwise the measurement continues) bool method; /// false = slow (precise), true = fast (immediate) FloatBox result; /// /// Events: BalanceDone, Error /// /// Balance device instance /// Reference to the measured mass in kg /// Required mass readings count (>= 3) /// Maximum spread of measurements in kg (otherwise the measurement continues) /// Method: false = slow (precise), true = fast (immediate) public ReadStableMassOp(BalanceDev balanceDev, ref FloatBox result, int readingsCount, float maxSpread, bool method) { if (balanceDev == null) throw new ArgumentNullException("balanceDev"); this.balanceDev = balanceDev; if (readingsCount == 0) this.totalReadingsCount = 5; else if (readingsCount < 3) this.totalReadingsCount = 3; else this.totalReadingsCount = readingsCount; if (maxSpread == 0) this.maxSpread = balanceDev.Capacity / 20000; else this.maxSpread = maxSpread; this.method = method; this.result = result; log.Debug(this.ToString()); } /// Start this operation public void Start() { currentReadingsCount = 0; massReadings = new float[totalReadingsCount]; if (method) balanceDev.GetImmediateMassMeasurement(); else balanceDev.GetStableMassMeasurement(); } /// Run this operation /// /// Event.None /// Event.BalanceDone /// Event.Error . . . . . Current.Tick == null /// public Event Run() { if (currentReadingsCount >= totalReadingsCount) return Event.BalanceDone; /// Mass has already been calculated if (balanceDev.MsrmntState == MsrmntState.Busy) return Event.None; if (balanceDev.MsrmntState == MsrmntState.Valid) { massReadings[currentReadingsCount++] = balanceDev.Mass; if (currentReadingsCount == totalReadingsCount) { #if OLD_WAY_OF_MASS_CALCULATION /// Exclude min. and max. value, calculate average Array.Sort(massReadings); float calcMass = 0; for (int i = 1; i < totalReadingsCount - 1; i++) { calcMass += massReadings[i]; } calcMass = (calcMass / (totalReadingsCount - 2)); log.InfoFormat("ReadStableMassOp.Run() ... valid mass={0} ... returning Event.BalanceDone", calcMass); result.Val = calcMass; return Event.BalanceDone; /// Mass has just been calculated #else float minimum = float.MaxValue; float maximum = float.MinValue; foreach (float val in massReadings) { if (val < minimum) minimum = val; if (val > maximum) maximum = val; } if ((maximum - minimum) <= maxSpread) { float calcMass = 0; for (int i = 0; i < totalReadingsCount; i++) { calcMass += massReadings[i]; } calcMass = (calcMass / totalReadingsCount); log.InfoFormat("ReadStableMassOp.Run() ... valid mass={0} ... returning Event.BalanceDone", calcMass); result.Val = calcMass; return Event.BalanceDone; /// Mass has just been calculated } else { /// Shift data and decrement 'currentReadingsCount' for (int i = 0; i < totalReadingsCount - 1; i++) { massReadings[i] = massReadings[i + 1]; } currentReadingsCount--; } #endif } } if (method) balanceDev.GetImmediateMassMeasurement(); else balanceDev.GetStableMassMeasurement(); return Event.None; } /// Stop this operation public void Stop() { } } }