/// /// Copyright (c) 2013-2016 Sensus Metering Systems /// using System; using System.Collections.Generic; using log4net; using TBF.BenchControl.Generic; using TBF.Boxes; namespace TBF.BenchControl.Elde.RegulValve { public class RegulValve : ComponentBase, IDevice, GenericDevices.IRegulValve { private static readonly ILog log = LogManager.GetLogger(typeof(RegulValve)); public override string ToString() { return string.Format("RegulValve({0})", Cfg.ToString(1)); } const int COAX_IDX = 7; /// COAX has always Idx1 = 7 public readonly RegulValveCfg RegulValveCfg; IDictionary dict; public IDictionary Dict { get { return dict; } } public readonly ControlBoardDev ControlBoard; public ValveCategory Category { get { return RegulValveCfg.Category; } } public int Idx1 { get { return RegulValveCfg.Idx1; } } /// 1..7 public int DacValueClosed { get { return RegulValveCfg.AdcValueClosed; } } /// 0..1023 public int DacValueOpen { get { return RegulValveCfg.AdcValueOpen; } } /// 0..1023 public int StableTime { get { return RegulValveCfg.StableTime; } } /// 0=200ms, step=50ms, max. 1500ms (max.26) public int FlowStableSec { get { return RegulValveCfg.FlowStableSec; } } /// 0..60 sec /// public bool IsCoax { get { return (Idx1 == COAX_IDX); } } /// public float Position { get { return ControlBoard.RValvePosition(Idx1); } } #region Configuration Change Handling public static void OnCfgChange(object sender, CfgChangeArgs args) { if (CfgChangeHandler == null) return; try { CfgChangeHandler(sender, args); } catch (Exception e) { log.Error("CfgChangeHandler(...) failed", e); } } public static event EventHandler CfgChangeHandler; public override void StartChangeHandler() { CfgChangeHandler += delegate(object sender, CfgChangeArgs args) { RegulValveCfg tmpcfg = args.Cfg as RegulValveCfg; if (tmpcfg != null && tmpcfg.Name.Equals(Name)) { if (args.Command == CfgChangeCmd.CfgChange) { RegulValveCfg.StableTimeMs = tmpcfg.StableTimeMs; RegulValveCfg.FlowStableSec = tmpcfg.FlowStableSec; } else if (args.Command == CfgChangeCmd.RVOpenStep) { ControlBoard.ValveMove(Idx1, RegulValveMode.PulseWidth, new float[2] { 2.0f, 2.0f }, StableTime); // TODO: avoid conflicts // TOTEST } else if (args.Command == CfgChangeCmd.RVCloseStep) { ControlBoard.ValveMove(Idx1, RegulValveMode.PulseWidth, new float[2] { -2.0f, -2.0f }, StableTime); // TODO: avoid conflicts // TOTEST } else if (args.Command == CfgChangeCmd.GetAdc1 || args.Command == CfgChangeCmd.GetAdc2) { int adc = (int)ControlBoard.AnalogInputRaw(Idx1 - 1, 0); RegulValveCfgCtrl.OnCmdResponse(this, new CmdResponseArgs(args.Command, Idx1, adc)); } } }; } #endregion Configuration Change Handling public RegulValve() { } public RegulValve(Generic.IComponentCfg cfg, IList components) : base(cfg) { RegulValveCfg = cfg as RegulValveCfg; ControlBoard = (ControlBoardDev)TbfComponents.FindComponent(cfg.ParentName, components); if (ControlBoard == null) throw new Exception("Cannot find " + Name + " parent"); this.dict = new Dictionary(); if (Idx1 != COAX_IDX) { this.ControlBoard.RegValveCalib[Idx1 - 1, 0] = (uint)DacValueClosed; this.ControlBoard.RegValveCalib[Idx1 - 1, 1] = (uint)DacValueOpen; } log.Debug(this.ToString()); } public void Initialize() { } public void RunDeviceBefore() { int adc = (int)ControlBoard.AnalogInputRaw(Idx1 - 1, 0); Handlers.OnAdcChanged(this, new CmdResponseArgs(CfgChangeCmd.GetAdc, Idx1, adc)); } public void RunDeviceAfter() { } public void StopDevice() { } /// /// Operation to set the water flow within tolerances /// Events: Event.None, Event.FlowReached, Event.FlowTimeOut /// /// Flowmeter component /// Lower limit of the required flow [m3/h] /// Higher limit of the required flow [m3/h] /// PID coefficient (float) /// Measured flow [m3/h] /// Timeout in [s] /// SetFlowOp instance public IOperation SetFlowOp(GenericDevices.IFlowMeter flowMeter, float requiredFlowLo, float requiredFlowHi, float pidCoef, DoubleBox measuredFlow, int timeout) { return new SetFlowOp(ControlBoard, this, flowMeter, requiredFlowLo, requiredFlowHi, pidCoef, measuredFlow, timeout); } /// /// Operation to set the water flow within tolerances. Leave the measurement running. /// Events: Event.None, Event.FlowReached, Event.FlowTimeOut /// /// Flowmeter component /// Lower limit of the required flow [m3/h] /// Higher limit of the required flow [m3/h] /// Measured flow [m3/h] /// Timeout in [s] /// SetFlowOp instance public IOperation SetFlowAndMeasureOp(GenericDevices.IFlowMeter flowMeter, float requiredFlowLo, float requiredFlowHi, float pidCoef, DoubleBox measuredFlow, int timeout, float filterConstant) { return new SetFlowOp(ControlBoard, this, flowMeter, requiredFlowLo, requiredFlowHi, pidCoef, measuredFlow, timeout, true); } /// /// Operation to set the regulation valve to a required position /// Events: Event.None /// /// Lower limit of the required valve position in [%] /// Higher limit of the required valve position in [%] /// SetPositionOp instance public IOperation SetRegulValvePositionOp(float pctLo, float pctHi, int timeoutMs) { return new SetRegulValvePositionOp(ControlBoard, this, pctLo, pctHi, timeoutMs); } public IOperation ChangeRegulValvePositionOp(float timePulseSec) { return new ChangeRegulValvePositionOp(ControlBoard, this, timePulseSec); } } }