/// /// Copyright (c) 2021 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; using log4net; using SchematicDrawing; using TBF.Boxes; using TBF.Rig.ControlBoard.Uni; using TBF.Rig.GenericDevices; namespace TBF.Rig.Uni.FlowMetersInParallel { public class FlowMeter : ComponentBase, IFlowMeter, IDrawingItCmpntWithMeasuredVal { private static readonly ILog log = LogManager.GetLogger(typeof(FlowMeter)); public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); } readonly FlowMeterCfg flowMeterCfg; readonly UniCB uniCB; readonly IFlowMeter flowMeter1; readonly IFlowMeter flowMeter2; readonly IFlowMeter flowMeter3; double nominalFlow; double nominalFreq; double ltrPerPulse; int flowMetersCount; int flowMetersBitfield; public int Idx1 { get { return flowMetersBitfield; } } public double NominalFlow { get { return nominalFlow; } } public double NominalFreq { get { return nominalFreq; } } public double LtrPerPulse { get { return ltrPerPulse; } } public SchematicDrawing.IDrawingItem DrawingItem { get { return flowMeterCfg as SchematicDrawing.IDrawingItem; } } public double MsrdValLimLo { get { return flowMeterCfg.MsrdValLimLo; } set { flowMeterCfg.MsrdValLimLo = value; } } public double MsrdValLimHi { get { return flowMeterCfg.MsrdValLimHi; } set { flowMeterCfg.MsrdValLimHi = value; } } double[] refFreq; /// 0..sum, 1..I11, 2..I12, 3..I13 int[] refPulses; public double LtrPerPulseCorrected(double flow, int rangeIx) { log.DebugFormat("LtrPerPulseCorrected({0}, {1}) started", flow, rangeIx); refFreq[0] = uniCB.RefFrequency; refFreq[1] = uniCB.RefFrequency1; refFreq[2] = uniCB.RefFrequency2; refFreq[3] = uniCB.RefFrequency3; log.DebugFormat("refFreq[] = ({0}, {1}, {2}, {3})", refFreq[0], refFreq[1], refFreq[2], refFreq[3]); refPulses[0] = uniCB.RefPulses; refPulses[1] = uniCB.RefPulses1; refPulses[2] = uniCB.RefPulses2; refPulses[3] = uniCB.RefPulses3; log.DebugFormat("refPulses[] = ({0}, {1}, {2}, {3})", refPulses[0], refPulses[1], refPulses[2], refPulses[3]); double flow1, flow2, flow3; double contribution1, contribution2, contribution3; if (refPulses[0] != 0) { /// Division by zero prevented inside this 'if' double ltrPerPulseCorrected = 0; if (flowMeter1 != null) { double ratio = (double)refPulses[flowMeter1.Idx1] / (double)refPulses[0]; flow1 = flow * ratio; contribution1 = flowMeter1.LtrPerPulseCorrected(flow1, rangeIx) * ratio; ltrPerPulseCorrected += contribution1; log.DebugFormat("flowmeter1 = {0}, flow1 = {1}, contribution1 = {2}", flowMeter1.Name, flow1, contribution1); } if (flowMeter2 != null) { double ratio = (double)refPulses[flowMeter2.Idx1] / (double)refPulses[0]; flow2 = flow * ratio; contribution2 = flowMeter2.LtrPerPulseCorrected(flow2, rangeIx) * ratio; ltrPerPulseCorrected += contribution2; log.DebugFormat("flowmeter2 = {0}, flow2 = {1}, contribution2 = {2}", flowMeter2.Name, flow2, contribution2); } if (flowMeter3 != null) { double ratio = (double)refPulses[flowMeter3.Idx1] / (double)refPulses[0]; flow3 = flow * ratio; contribution3 = flowMeter3.LtrPerPulseCorrected(flow3, rangeIx) * ratio; ltrPerPulseCorrected += contribution3; log.DebugFormat("flowmeter3 = {0}, flow3 = {1}, contribution3 = {2}", flowMeter3.Name, flow3, contribution3); } log.DebugFormat("LtrPerPulseCorrected() returns {0}", ltrPerPulseCorrected); return ltrPerPulseCorrected; } else { log.DebugFormat("LtrPerPulseCorrected() returns 1"); return 1; } } public bool MsrmntAvailable { get { return true; } } public double MeasuredVal { get { return ReadFlow(); } } public string AltString { get { return "Invalid format"; } } public FlowMeter() { refFreq = new double[4]; refPulses = new int[4]; } public FlowMeter(Generic.IComponentCfg cfg, IList components) : base(cfg) { flowMeterCfg = cfg as FlowMeterCfg; uniCB = TbfComponents.FindComponent(cfg.ParentName, components) as UniCB; if (uniCB == null) throw new Exception("Cannot find " + Name + " parent"); if (!string.IsNullOrEmpty(flowMeterCfg.Flowmeter1)) flowMeter1 = TbfComponents.FindComponent(flowMeterCfg.Flowmeter1, components) as IFlowMeter; if (!string.IsNullOrEmpty(flowMeterCfg.Flowmeter2)) flowMeter2 = TbfComponents.FindComponent(flowMeterCfg.Flowmeter2, components) as IFlowMeter; if (!string.IsNullOrEmpty(flowMeterCfg.Flowmeter3)) flowMeter3 = TbfComponents.FindComponent(flowMeterCfg.Flowmeter3, components) as IFlowMeter; log.Warn(this.ToString()); } public override void Initialize() { nominalFlow = 0; flowMetersCount = 0; flowMetersBitfield = 0; if (flowMeter1 != null) { nominalFlow += flowMeter1.NominalFlow; nominalFreq += flowMeter1.NominalFreq; flowMetersBitfield |= (4 << flowMeter1.Idx1); flowMetersCount++; } if (flowMeter2 != null) { nominalFlow += flowMeter2.NominalFlow; nominalFreq += flowMeter2.NominalFreq; flowMetersBitfield |= (4 << flowMeter2.Idx1); flowMetersCount++; } if (flowMeter3 != null) { nominalFlow += flowMeter3.NominalFlow; nominalFreq += flowMeter3.NominalFreq; flowMetersBitfield |= (4 << flowMeter3.Idx1); flowMetersCount++; } if (flowMetersCount == 0) throw new Exception("Missing flowmeters"); MsrdValLimHi = nominalFlow; ltrPerPulse = nominalFlow / (3.6 * nominalFreq); /// Nominal freq. is sum of particular nominal frquencies refFreq = new double[4]; refPulses = new int[4]; } public double ReadFlow() { return nominalFlow * ReadFrequency() / (3.6 * nominalFreq); } public double ReadFrequency() { return uniCB.RefFrequency; } /// /// Events: FlowDone, Error /// /// Reference to a variable for the flow in Bar /// ReadFlowOp instance reference casted to IOperaton public IOperation ReadFlowOp(ref DoubleBox flow) { return new ReadFlowOp(this, ref flow); } /// /// Events: flowDone, Error /// /// Reference to a variable for the flow in Bar /// Event returned when measurement done /// ReadFlowOp instance reference casted to IOperaton public IOperation ReadFlowOp(ref DoubleBox flow, Event flowDone) { return new ReadFlowOp(this, ref flow, flowDone); } } }