/// /// Copyright (c) 2013-2015 Sensus Metering Systems /// using System; using log4net; namespace TBF.BenchControl.Elde { public class ControlComWrap : IControlCom { private static readonly ILog log = LogManager.GetLogger(typeof(ControlComWrap)); /// /// Properties /// public StatusP StatusP { get { return (StatusP)ctrlBrdComponent.StatusP; } } #if FUZHOU300 || PT200IL || TORINO50 || BADGER_MALA_TRAT /// /// In case of I11, I12 /// referenceFreq[0] = I11 + I12 /// referenceFreq[1] = I11 /// referenceFreq[2] = I12 /// otherwise /// referenceFreq[0] = I2 or I3 or I4 /// public float ReferenceFreq { get { return 1000.0f * ctrlBrdComponent.referenceFreq[0]; } } /// In [Hz] 0..2500, nom.=2000 #else public float ReferenceFreq { get { return 1000.0f * ctrlBrdComponent.referenceFreq; } } /// In [Hz] 0..2500, nom.=2000 #endif public int EtPulses(int wmNr0) { return (int)ctrlBrdComponent.etPulses[wmNr0]; } public int WMeterPulses(int wmNr0) { return (int)ctrlBrdComponent.wMeterPuls[wmNr0]; } public int WMeterReference(int wmNr0) { return (int)ctrlBrdComponent.wMeterReference[wmNr0]; } public uint RegulValveDAC { get { return ctrlBrdComponent.StavDA; } } public float Pressure(int prsNr0) { return ctrlBrdComponent.pressure[prsNr0]; } public float Temperature(int tmpNr0) { return ctrlBrdComponent.temperature[tmpNr0]; } public RegulValveState RegulValveState(int rvNr1) { return (RegulValveState)ctrlBrdComponent.rValveStatus[rvNr1 - 1]; } public ulong RRoute { get { return ctrlBrdComponent.rRoute; } } public uint DivTime { get { return ctrlBrdComponent.divTime; } } public float TTime { get { return ctrlBrdComponent.Ttime; } } #if FUZHOU300 || PT200IL || TORINO50 || BADGER_MALA_TRAT public uint FmState { get { return ctrlBrdComponent.fMState[0]; } } /// TODO: index #else public uint FmState { get { return ctrlBrdComponent.fMState; } } #endif public uint BeginState(int wmNr0) { return ctrlBrdComponent.beginSt[wmNr0]; } public float ReferenceFlow { get { return ctrlBrdComponent.referenceFlow; } } public float RValvePosition(int rvNr1) { //return ctrlBrdComponent.RValvePosition[rvNr1 - 1]; return ctrlBrdComponent.Analogy[rvNr1 - 1]; /// Fixes bug: RValvePosition returns 0 all the time } public float DivSamples(int ms) { return ctrlBrdComponent.DIVSamples[ms, 0]; } public int ScopeSamples(int i, int j, int k) { return ctrlBrdComponent.ScopeSamples[i, j, k]; } public uint DigitalInputs { get { return ctrlBrdComponent.Vstupy; } } public float AnalogInput(int adcNr0) { return ctrlBrdComponent.Analogy[adcNr0]; } public uint AnalogInputRaw(int adcNr0, int bank) { return ctrlBrdComponent.AnalogyRaw[adcNr0, bank]; } /// bank0=RV, bank1=Temp public float ReferenceVolume { get { return ctrlBrdComponent.ReferenceVolume; } } public float VyslExt(int wmNr0, int what) { return ctrlBrdComponent.VyslExt[wmNr0, what]; } public void SetWeight(int pos, float mass) { ctrlBrdComponent.Weight[pos] = mass; } /// /// Reference to the control board component /// #if DN100 private ControlCom2VB.ControlCom2panel ctrlBrdComponent; #elif MUNICH private ControlComponent3Munich.UserControl1 ctrlBrdComponent; #elif FUZHOU150 private ControlComponent3Munich.UserControl1 ctrlBrdComponent; #elif FUZHOU300 private ControlComponent3F300.UserControl1 ctrlBrdComponent; #elif PT200IL private ControlComponent_Izrael2014.UserControl1 ctrlBrdComponent; #elif TORINO50 private ControlComponent_Torino2015.UserControl1 ctrlBrdComponent; #elif BADGER_MALA_TRAT private ControlComponent_Torino2015.UserControl1 ctrlBrdComponent; #endif /// /// Constructor that initializes the control board component reference /// /// #if DN100 public ControlComWrap(ControlCom2VB.ControlCom2panel ctrlBrdComponent) #elif MUNICH public ControlComWrap(ControlComponent3Munich.UserControl1 ctrlBrdComponent) #elif FUZHOU150 public ControlComWrap(ControlComponent3Munich.UserControl1 ctrlBrdComponent) #elif FUZHOU300 public ControlComWrap(ControlComponent3F300.UserControl1 ctrlBrdComponent) #elif PT200IL public ControlComWrap(ControlComponent_Izrael2014.UserControl1 ctrlBrdComponent) #elif TORINO50 public ControlComWrap(ControlComponent_Torino2015.UserControl1 ctrlBrdComponent) #elif BADGER_MALA_TRAT public ControlComWrap(ControlComponent_Torino2015.UserControl1 ctrlBrdComponent) #endif { this.ctrlBrdComponent = ctrlBrdComponent; } /// /// Sends calibration and configuration data to the control board. /// /// Regulating valves calib.coefs, ix1 = valve nr. (1..5), ix2 = coef.nr. (0..1), values typ. c0 = 0, c1 = 0.2 /// Meret address, index = 0..1, value typ. 99 and 100 /// COM port number of the control board (typ. 1) /// Temp.calc.coefs, ix1 = temp.sens.nr. (0..7 ???), ix2 = coef.nr /// Etalon nominal values /// Percentages for switching of diverters, ix = diverter nr.(0,1), typ.value 50 (%) /// Balance range = volume of the tanks on the balaces (ix=0,1) public void SendCalibData(uint[,] rvCalib, byte[] meretA, int usedCom, float[,] tempCalib, float[] etCalib, uint[] divEdge, uint[] balanceRange) { if (Program.MainWnd.InvokeRequired) { /// When SendCalibData(...) called from the worker thread object[] args = new object[] { rvCalib, meretA, usedCom, tempCalib, etCalib, divEdge, balanceRange }; Program.MainWnd.Invoke((SendCalibDataDlgt)DoSendCalibData, args); /// Invoke required as component was created in UI thread } else { /// When SendCalibData(...) called from the UI thread DoSendCalibData(rvCalib, meretA, usedCom, tempCalib, etCalib, divEdge, balanceRange); } } /// delegate void SendCalibDataDlgt(uint[,] rvCalib, byte[] meretA, int usedCom, float[,] tempCalib, float[] etCalib, uint[] divEdge, uint[] balanceRange); /// private void DoSendCalibData(uint[,] rvCalib, byte[] meretA, int usedCom, float[,] tempCalib, float[] etCalib, uint[] divEdge, uint[] balanceRange) { //TBF.UiBridge.Bridge.OnLog(this, string.Format("{0} SendCalibData(COM{1}) rvCalib[0,0]={2} rvCalib[0,1]={3} rvCalib[1,0]={4} rvCalib[1,1]={5}\r\n", // DateTime.Now.ToLongTimeString(), usedCom, // rvCalib[0,0], rvCalib[0,1], rvCalib[1,0], rvCalib[1,1])); log.InfoFormat("SendCalibData(COM{0}) rvCalib[0,0]={1} rvCalib[0,1]={2} rvCalib[1,0]={3} rvCalib[1,1]={4}", usedCom, rvCalib[0,0], rvCalib[0,1], rvCalib[1,0], rvCalib[1,1]); //#if (DN100) ctrlBrdComponent.ExternalCom = true; //#endif ctrlBrdComponent.SendCalibData(rvCalib, meretA, (byte)usedCom, tempCalib, etCalib, divEdge, balanceRange); } /// /// Control of regulating valves. /// /// Regulating valve nr. (1..5) /// Valve regulation mode, see the enum /// Target position or target frequency or pulse duration /// Stabilization time when setting the flow: 0=200ms, step 50ms, max. 1.5 sec. public void ValveMove(int valveNo, RegulValveMode valveMode, float[] valveValue, int stableTime) { if (Program.MainWnd.InvokeRequired) { /// When ValveMove(...) called from the worker thread object[] args = new object[] { valveNo, valveMode, valveValue, stableTime }; Program.MainWnd.Invoke((ValveMoveDlgt)DoValveMove, args); /// When ValveMove called from a worker thread } else { /// When ValveMove(...) called from the UI thread DoValveMove(valveNo, valveMode, valveValue, stableTime); /// When ValveMove called from the UI thread } } /// delegate void ValveMoveDlgt(int valveNo, RegulValveMode valveMode, float[] valveValue, int stableTime); /// private void DoValveMove(int valveNo, RegulValveMode valveMode, float[] valveValue, int stableTime) { //TBF.UiBridge.Bridge.OnLog(this, string.Format("{0} ValveMove({1}, {2}, [{3}, {4}])\r\n", // DateTime.Now.ToLongTimeString(), // valveNo, // valveMode, // valveValue[0], // valveValue[1])); log.InfoFormat("ValveMove(#={0}, md={1}, [{2}, {3}])", valveNo, valveMode, valveValue[0], valveValue[1]); #if FUZHOU300 || PT200IL || TORINO50 || BADGER_MALA_TRAT ctrlBrdComponent.ValveMove((byte)valveNo, (byte)valveMode, valveValue, stableTime); #else ctrlBrdComponent.ValveMove((byte)valveNo, (byte)valveMode, valveValue); #endif } /// /// Sends a command to the control board. /// /// See ControlBoard.Command enum /// Reference flow meter number (1..5) /// Route: 64-bit installation specific number /// Test duration as a number of reference flow meter pulses /// See ControlBoard.TestMethods enum /// 0 = No filtering (0..255) /// Freq.inverter control (not applicable in DT100, Munich) /// Coefficient used to control the regulation valve (1..100) /// 0 = default value, 1 = spec. processing of very short pulses /// What to stop public void SendCommand(Command cmd, int refFlowMeterNr, ulong route, int totalRefPulses, TestMethods testMethods, float filterConstant, float[] fmFreq, int regConst, int shortImp, StopDevs stopDevs) { if (Program.MainWnd.InvokeRequired) { /// When SendCommand(...) called from the worker thread object[] args = new object[] { cmd, refFlowMeterNr, route, totalRefPulses, testMethods, filterConstant, fmFreq, regConst, shortImp, stopDevs }; Program.MainWnd.Invoke((SendCommandDlgt)DoSendCommand, args); /// Component was created in UI thread - use Invoke() } else { /// When SendCommand(...) called from the UI thread DoSendCommand(cmd, refFlowMeterNr, route, totalRefPulses, testMethods, filterConstant, fmFreq, regConst, shortImp, stopDevs); } } /// delegate void SendCommandDlgt(Command cmd, int refFlowmtrNr, ulong route, int totalRefPulses, TestMethods testMethods, float filterConstant, float[] fmFreq, int regConst, int shortImp, StopDevs stopDevs); /// private void DoSendCommand(Command cmd, int refFlowMeterNr, ulong route, int totalRefPulses, TestMethods testMethods, float filterConstant, float[] fmFreq, int regConst, int shortImp, StopDevs stopDevs) { //TBF.UiBridge.Bridge.OnLog(this, string.Format("{0} SendCommand({1}, {2}, {3}, {4}, {5}, {6}, [{7},{8}], {9}, {10}, {11})\r\n", // DateTime.Now.ToLongTimeString(), // cmd, // refFlowMeterNr, // route.ToString("X"), // totalRefPulses, // testMethods, // filterConstant, // fmFreq[0], // fmFreq[1], // regConst, // shortImp, // stopDevs)); log.InfoFormat("SendCommand(Cmd={0}, Ref={1}, rt={2} {3} {4} {5}, Total={6}, TM={7}, filt={8}, FM=[{9}{10}{11}{12}{13}{14}], Reg={15}, ShrtImp={16}, Stop={17})", cmd, refFlowMeterNr, ((route >> 48) & 0xFFFF).ToString("X4"), ((route >> 32) & 0xFFFF).ToString("X4"), ((route >> 16) & 0xFFFF).ToString("X4"), (route & 0xFFFF).ToString("X4"), totalRefPulses, testMethods, filterConstant, fmFreq[0].ToString(), (fmFreq.Length > 1) ? ("," + fmFreq[1].ToString()) : "", (fmFreq.Length > 2) ? ("," + fmFreq[2].ToString()) : "", (fmFreq.Length > 3) ? ("," + fmFreq[3].ToString()) : "", (fmFreq.Length > 4) ? ("," + fmFreq[4].ToString()) : "", (fmFreq.Length > 5) ? ("," + fmFreq[5].ToString()) : "", regConst, shortImp, stopDevs); #if (DN100 || MUNICH) ctrlBrdComponent.SendCommand((uint)cmd, (byte)refFlowMeterNr, (ulong)route, (uint)totalRefPulses, (uint)testMethods, filterConstant, fmFreq[0], (uint)regConst, (uint)shortImp, (uint)stopDevs); #else ctrlBrdComponent.SendCommand((uint)cmd, (byte)refFlowMeterNr, (ulong)route, (uint)totalRefPulses, (uint)testMethods, filterConstant, fmFreq, (uint)regConst, (uint)shortImp, (uint)stopDevs); #endif } enum CommType { Rx, /// Receive data only TxRx, /// Transmit and receive data } public void RunDeviceBefore() { object[] args = new object[] { CommType.Rx }; MakeCommDlgt dlgt = MakeComm; Program.MainWnd.Invoke(dlgt, args); /// Invoke MakeExtComm(.) in the UI thread } public void RunDeviceAfter() { object[] args = new object[] { CommType.TxRx }; MakeCommDlgt dlgt = MakeComm; Program.MainWnd.Invoke(dlgt, args); /// Invoke MakeExtComm(.) in the UI thread } /// /// A delegate to execute the SendCommand() in the UI thread /// delegate void MakeCommDlgt(CommType extComm); /// /// Executes the SendCommand(...) and MakeExtCom() in the UI thread /// void MakeComm(CommType commType) { if (ctrlBrdComponent.ExternalCom) { ctrlBrdComponent.MakeExtCom((commType == CommType.Rx) ? false : true); } } } }