using System;
using System.Text;
using System.IO.Ports;
using System.Collections.Generic;
using TBF.BenchControl.Generic;
using TBF.BenchControl.GenericDevices;
using log4net;
namespace TBF.BenchControl.Elde
{
public class ControlBoardDev : IComponent, IDevice, IValveControl
{
///
/// Info:
/// Warn:
/// Error:
///
private static readonly ILog log = LogManager.GetLogger(typeof(ControlBoardDev));
public override string ToString() { return string.Format("ControlBoardDev on com{0}", controlBoardCfg.ComPortNr); }
public static void ResetStaticProperties() { }
ControlBoardCfg controlBoardCfg;
public Generic.IComponentCfg Cfg { get { return controlBoardCfg; } }
public string Name { get { return controlBoardCfg.Name; } }
///
/// Reference to the control board component
///
IControlCom controlCom;
///
/// Emergency stop signal state updated by RunDevice().
/// 'modelessDlg' is notified about the changes and uses this information to change its visibility.
///
//UiBridge.EmergencyStopEventArgs.State emergencyStopState;
///
/// Public read only wrappers for Elde software component fields
///
/// rvNr1 = 1 .. nrRegulValves (one based)
/// wmNr0 = 0 .. nrWaterMeters-1 (zero based)
/// tmpNr0 = 0 .. nrTempMeters-1 (zero based)
/// prsNr0 = 0 .. nrPressureMeters-1 (zero based)
///
public StatusP StatusP { get { return controlCom.StatusP; } }
public float ReferenceFreq { get { return controlCom.ReferenceFreq; } } /// In [Hz] 0..2500, nom.=2000
public int EtPulses(int wmNr0) { return controlCom.EtPulses(wmNr0); }
public int WMeterPulses(int wmNr0) { return controlCom.WMeterPulses(wmNr0); }
public int WMeterReference(int wmNr0) { return controlCom.WMeterReference(wmNr0); }
public uint RegulValveDAC { get { return controlCom.RegulValveDAC; } }
public float Pressure(int prsNr0) { return controlCom.Pressure(prsNr0); }
public float Temperature(int tmpNr0) { return controlCom.Temperature(tmpNr0); }
public RegulValveState RegulValveState(int rvNr1) { return (RegulValveState)controlCom.RegulValveState(rvNr1); }
public ulong RRoute { get { return controlCom.RRoute; } }
public uint DivTime { get { return controlCom.DivTime; } }
public float TTime { get { return controlCom.TTime; } }
public uint FmState { get { return controlCom.FmState; } }
public uint BeginState(int wmNr0) { return controlCom.BeginState(wmNr0); }
public float ReferenceFlow { get { return controlCom.ReferenceFlow; } }
public float RValvePosition(int rvNr1) { return controlCom.RValvePosition(rvNr1); }
public float DivSamples(int ms) { return controlCom.DivSamples(ms); }
public int ScopeSamples(int i, int j, int k) { return controlCom.ScopeSamples(i, j, k); }
public uint DigitalInputs { get { return controlCom.DigitalInputs; } }
public float AnalogInput(int adcNr0) { return controlCom.AnalogInput(adcNr0); }
public uint AnalogInputRaw(int adcNr0, int bank) { return controlCom.AnalogInputRaw(adcNr0, bank); } /// bank0=RV, bank1=Temp
public float ReferenceVolume { get { return controlCom.ReferenceVolume; } }
public float VyslExt(int wmNr0, int what) { return controlCom.VyslExt(wmNr0, what); }
/// Extracted from the StatusP in RunDeviceBefore
public bool EmergencyStop { get { return emergencyStop; } }
bool emergencyStop;
bool previousEmergencyStop;
/// State of valves sent out - buffered by the last SendCommand()
public ulong Route { get { return route; } }
///
/// Initialization data updated by constructors of children components
/// and sent to 'controlCom2panel' by SendCalibData() method.
///
public uint[,] RegValveCalib = new uint[8, 2];
public byte[] MeretRS485Address = new byte[4];
public float[,] TempCalibData = new float[8, 5];
// Array length is the reference flowmeters count plus one
#if DN100
public float[] EtCalib = new float[6] { 1, 1, 1, 1, 1, 1 };
#elif MUNICH
public float[] EtCalib = new float[5] { 1, 1, 1, 1, 1 };
#elif FUZHOU150
public float[] EtCalib = new float[6] { 1, 1, 1, 1, 1, 1 };
#elif FUZHOU300
public float[] EtCalib = new float[6] { 1, 1, 1, 1, 1, 1 };
#endif
public uint[] DiverterEdge = new uint[2] { 50, 50 };
public uint[] BalanceRange = new uint[2];
///
/// Private values sent by the last SendCommand()
///
bool sendCommandFlag;
Command cmd;
int refNr;
ulong route;
int refPulses;
TestMethods testMethods;
float filterConstant;
float[] FMFreq;
int regConst;
int shortImp;
StopDevs stopDevs;
public void SetFMFreq(int index, float power)
{
if (index == 0) FMFreq = new float[2] { power, 0 };
else if (index == 1) FMFreq = new float[2] { 0, power };
else FMFreq = new float[2] { 0, 0 };
}
public void UpdateWeights()
{
for (int i = 0; i < MettlerToledo.BalanceDev.BalancesCount; i++)
{
controlCom.SetWeight(i, MettlerToledo.BalanceDev.Masses[i]);
}
}
///
/// Constructor
///
public ControlBoardDev(ControlBoardCfg cfg, IList components)
{
if (cfg == null) throw new ArgumentNullException("cfg");
this.controlBoardCfg = cfg;
FMFreq = new float[2] { 0, 0 };
emergencyStop = false;
previousEmergencyStop = false;
}
///
/// Specific pre-initialization for control board only
///
///
public void InitializeComponent(
#if DN100
ControlCom2VB.ControlCom2panel ctrlBrdComponent,
#elif MUNICH
ControlComponent3Munich.UserControl1 ctrlBrdComponent,
#elif FUZHOU150
ControlComponent3Munich.UserControl1 ctrlBrdComponent,
#elif FUZHOU300
ControlComponent3Munich.UserControl1 ctrlBrdComponent,
#endif
float[] tankCapacities)
{
if (controlBoardCfg.DebugLevel == Entities.DebugMode.Simulate)
{
controlCom = new ControlComSim();
}
else
{
int cnt = Math.Min(BalanceRange.Length, tankCapacities.Length);
for (int i = 0; i < cnt; i++) BalanceRange[i] = (uint)tankCapacities[i];
controlCom = new ControlComWrap(ctrlBrdComponent);
}
}
/// Initialize this device
public void Initialize()
{
controlCom.SendCalibData(RegValveCalib,
MeretRS485Address,
controlBoardCfg.ComPortNr,
TempCalibData,
EtCalib,
DiverterEdge,
BalanceRange);
}
/// Run this device
public void RunDeviceBefore()
{
controlCom.RunDeviceBefore();
previousEmergencyStop = emergencyStop;
emergencyStop = (controlCom.StatusP & StatusP.EmgcyStopActive) != 0;
if (emergencyStop && !previousEmergencyStop)
{
Program.MainWnd.Invoke(new ShowEmergencyStopFormDlgt(ShowEmergencyStopForm));
}
else if (!emergencyStop && previousEmergencyStop)
{
UiBridge.Bridge.OnEmergencyStopChanged(this,UiBridge.EmergencyStopEventArgs.State.CloseForm);
}
if (emergencyStop)
{
/// SendCommand() arguments to clear the emergency stop state
sendCommandFlag = true;
this.cmd = Command.Stop;
this.stopDevs = StopDevs.All;
}
else
{
/// Reset all SendCommand() arguments
sendCommandFlag = false;
this.cmd = Command.None;
this.stopDevs = 0;
}
this.refNr = 0;
this.refPulses = 0;
this.testMethods = 0;
this.filterConstant = 0;
this.regConst = 0;
this.shortImp = 0;
}
/// Run this device
public void RunDeviceAfter()
{
if (sendCommandFlag)
{
controlCom.SendCommand(cmd, refNr, route, refPulses, testMethods,
filterConstant, FMFreq, regConst, shortImp, stopDevs);
}
controlCom.RunDeviceAfter();
}
/// Stop this device
public void StopDevice()
{
}
delegate void ShowEmergencyStopFormDlgt();
///
void ShowEmergencyStopForm()
{
(new TBF.Forms.EmergencyStopForm()).Show();
}
///
/// Sends a command to the control board.
///
/// See ControlBoard.Command enum
/// Number of the etalon/reference (1..5)
/// Route: 64-bit installation specific number
/// kolko impulzov ma trvat skuska
/// See ControlBoard.TestMethods enum
/// 0 = No filtering (0..255)
/// Coefficient used to control reg. valves (1..100)
/// 0 = default value, 1 = spec. processing of very short pulses
/// What to stop
public void SendCommand(Command cmd, int refFlowmtrNr, ulong route, int totalRefPulses, TestMethods testMethods,
float filterConstant, int regConst, int shortImp, StopDevs stopDevs)
{
this.cmd = cmd;
this.refNr = refFlowmtrNr;
this.route = route;
this.refPulses = totalRefPulses;
this.testMethods = testMethods;
this.filterConstant = filterConstant;
this.regConst = regConst;
this.shortImp = shortImp;
this.stopDevs = stopDevs;
sendCommandFlag = true;
}
public void SetValves(ulong valvesToOpen, ulong valvesToClose)
{
route = (route | valvesToOpen) & (~valvesToClose);
sendCommandFlag = true;
}
///
/// Regulation valves control.
///
/// Regulation valve nr. (1..5)
/// Valve regulation mode, see the enum
/// Target position or target frequency or pulse duration
public void ValveMove(int valveNo, RegulValveMode valveMode, float[] valveValue)
{
controlCom.ValveMove(valveNo, valveMode, valveValue);
}
///
/// Open one valve and/or close one valve.
/// Events: ValvesSet
///
/// Valve to be opened
/// Valve to be closed
/// Created operation
public IOperation SetValvesOp(IValve valveOpen, IValve valveClose)
{
return new Valve.SetValvesOp(this, valveOpen, valveClose);
}
///
/// Open and/or close multiple valves.
/// Events: ValvesSet
///
/// A list of valves to be opened
/// A list of valves to be closed
/// Created operation
public IOperation SetValvesOp(IList valvesOpen, IList valvesClose)
{
return new Valve.SetValvesOp(this, valvesOpen, valvesClose);
}
///
/// Starts the measurement.
/// Events: MeasurementStarted
///
/// Flow meter
/// An array of register readers
/// Number of reference pulses to complete the test
/// Created operation
public IOperation StartMeasurementOp(IFlowMeter flowMeter, int refPulses, TestMethods method, float filterConstant)
{
return new StartMeasurementOp(this, flowMeter, refPulses, method, filterConstant);
}
///
/// Queries th econtrol board whether the measurement was completed.
/// Events: MeasurementCompleted or None
///
/// Created operation
public IOperation QueryMeasurementEndOp()
{
return new QueryMeasurementEndOp(this);
}
///
/// Stop the previous control board operation (diverter, gate, etc.)
/// Events: PreviousStopped
///
/// Created operation
public IOperation StopPreviousOp()
{
return new StopPreviousOp(this);
}
///
/// Updates the tank drawing and weight value in Elde software component.
///
/// Current mass in [kg] or approx. volume in [l]
/// Created operation
public IOperation UpdateTankWeightOp()
{
return new UpdateTankWeightOp(this);
}
}
}