From 2ca36374e64de3e80f5f217d407bfa7e9115aba2 Mon Sep 17 00:00:00 2001 From: Milan Hanajik Date: Mon, 16 Feb 2015 21:01:37 +0100 Subject: [PATCH] Danfoss-VLT2800-Pump functions OK, TODO: control the valve of the pump --- .../BenchControl/Danfoss/VLT2800/Pump.cs | 400 ++++++++++++------ .../BenchControl/Danfoss/VLT2800/PumpCfg.cs | 20 +- .../Danfoss/VLT2800/PumpCfgCtrl.cs | 25 +- .../Danfoss/VLT2800/PumpCfgCtrl.designer.cs | 106 +++-- TestBenchFramework/Utils.cs | 80 +++- 5 files changed, 438 insertions(+), 193 deletions(-) diff --git a/TestBenchFramework/BenchControl/Danfoss/VLT2800/Pump.cs b/TestBenchFramework/BenchControl/Danfoss/VLT2800/Pump.cs index c42353538..f3623959e 100644 --- a/TestBenchFramework/BenchControl/Danfoss/VLT2800/Pump.cs +++ b/TestBenchFramework/BenchControl/Danfoss/VLT2800/Pump.cs @@ -9,177 +9,311 @@ using TBF.Boxes; namespace TBF.BenchControl.Danfoss.VLT2800 { + /// + /// See page 20 of MG10S202 Operational Instructions Modbus RTU + /// + public enum CW : ushort + { + PresetRefLsb = (1 << 0), + PresetRefMsb = (1 << 1), + Not_DcBraking = (1 << 2), + Not_CoastingStop = (1 << 3), + Not_QuickStop = (1 << 4), + Not_FreezeFreq = (1 << 5), + Start_NotRampStop = (1 << 6), + Reset = (1 << 7), + Jog = (1 << 8), + Ramp2_NotRamp1 = (1 << 9), + DataValid = (1 << 10), + Relay01Activ = (1 << 11), + DOut46Activ = (1 << 12), + SelectSetupLsb = (1 << 13), + SelectSetupMsb = (1 << 14), + Reversing = (1 << 15), + } + + /// + /// See page 22 of MG10S202 Operational Instructions Modbus RTU + /// + public enum SW : ushort + { + ControlReady = (1 << 0), + DriveReady = (1 << 1), + CoastingStop = (1 << 2), + Trip = (1 << 3), + TripLock = (1 << 6), + Warning = (1 << 7), + SpeedEqRef = (1 << 8), + RemoteCtrl = (1 << 9), + FreqLimitOK = (1 << 10), + MotorRunning = (1 << 11), + VoltageWarn = (1 << 13), + CurrentLimit = (1 << 14), + ThermalWarn = (1 << 15), + } + + public enum Function : byte + { + ReadCoilStatus = 0x01, + ForceSingleCoil = 0x05, + ForceMultipleCoils = 0x0F, + ReadHoldingRegisters = 0x03, + PresetSingleRegister = 0x06, + PresetMultipleRegisters = 0x10, + } /// /// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232) /// Connection settings: 19200 Bd 8-bits No-parity 1-stop-bit Flow control: none or hardware. /// - public class Pump : ComponentBase, IDevice, IOperation, GenericDevices.IAmbient - { + public class Pump : ComponentBase, IDevice, IOperation, GenericDevices.IPumpFM, GenericDevices.IValve + { private static readonly ILog log = LogManager.GetLogger(typeof(Pump)); public override string ToString() { return string.Format("Pump-Danfoss-VLT2800({0})", Cfg.ToString(1)); } - private readonly PumpCfg ambientCfg; + private readonly PumpCfg pumpCfg; + + public int Delay { get { return pumpCfg.Delay; } } + public ValveCategory Category { get { return ValveCategory.Feeding; } } /// Pump category is Feeding + public GenericDevices.IValve CoupledTo { get { return null; } } + public bool InvertCouple { get { return false; } } + public int LagOpening { get { return 0; } } + public int LagClosing { get { return 0; } } + + readonly Elde.ControlBoardDev controlBoard; + readonly int bitPosition; /// 0 .. 63 + + public readonly ulong Mask; /// derived from bitPosition in the constructor + + public bool State + { + get { return (controlBoard.Route & Mask) != 0; } + } /// Private fields SerialPort serialPort; - StringBuilder measurementBuilder; + bool dataToSendReady; + byte[] dataToSend; + StringBuilder responseBuilder; - /// The state of the measurement - MsrmntState msrmntState; - - /// Measured temperature when MsrmntState == MsrmntState.Valid - float temperature; - - /// Measured humidity when MsrmntState == MsrmntState.Valid - float humidity; - - /// Measured pressure when MsrmntState == MsrmntState.Valid - float pressure; - - /// Measurement time stamp when MsrmntState == MsrmntState.Valid - int msrmntTimeStamp; /// /// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232) /// Connection settings: 19200 Bd 8-bits No-parity 1-stop-bit Flow control: none or hardware. /// public Pump(PumpCfg cfg, IList components) - : base(cfg) - { - ambientCfg = cfg; + : base(cfg) + { + pumpCfg = cfg; + + controlBoard = (Elde.ControlBoardDev)TbfComponents.FindComponent("CB", components); /// TODO: replace "CB" + if (controlBoard == null) throw new Exception("Cannot find " + Name + " parent"); + + //bitPosition = pumpCfg.BitPosition; + bitPosition = 55; /// TODO: replace 55 + Mask = (((ulong)1) << bitPosition); + log.Debug(this.ToString()); } public void Initialize() { - if (ambientCfg.DebugLevel == Entities.DebugMode.Simulate) + if (pumpCfg.DebugLevel == Entities.DebugMode.Simulate) { - temperature = 20.0f; - humidity = 40.0f; - pressure = 1.0f; - msrmntTimeStamp = StateMachine.Time; - msrmntState = MsrmntState.Valid; return; } - string comPortName = "COM" + ambientCfg.ComPortNr.ToString(); - serialPort = new SerialPort(comPortName, ambientCfg.BaudRate, ambientCfg.Parity, ambientCfg.DataBits, ambientCfg.StopBits); - serialPort.Handshake = ambientCfg.Handshake; + string comPortName = "COM" + pumpCfg.ComPortNr.ToString(); + serialPort = new SerialPort(comPortName, pumpCfg.BaudRate, pumpCfg.Parity, pumpCfg.DataBits, pumpCfg.StopBits); + serialPort.Handshake = Handshake.None; serialPort.Open(); - measurementBuilder = new StringBuilder(40); - msrmntState = MsrmntState.Busy; + responseBuilder = new StringBuilder(40); - log.FatalFormat("Successfully initialized device {0}", ToString()); - } + log.FatalFormat("Successfully initialized device {0}", ToString()); + } - /// Run this device - public void RunDeviceBefore() - { - if (ambientCfg.DebugLevel == Entities.DebugMode.Simulate) - { - msrmntTimeStamp = StateMachine.Time; - return; - } - - measurementBuilder.Append(serialPort.ReadExisting()); - int len = measurementBuilder.Length; - - /// - /// Device sends each 20 sec one line of ASCII text with data in the following format: - /// (temp) 6 characters, two decimal digits, with leading spaces - /// TAB 1 character - /// (humi) 6 characters, two decimal digits, with leading spaces - /// TAB 1 character - /// (pressure) 6 characters, one decimal digits, with leading spaces is LT 1000 - /// CR + LF 2 characters - /// Example: - /// 23.42 38.08 1061.1 - /// 23.39 38.04 1060.8 - /// 23.39 38.08 1061.4 - /// - if (len >= 22) - { - string measurement = measurementBuilder.ToString(); - measurementBuilder.Clear(); - - float t = 0; - float h = 0; - float p = 0; - if (float.TryParse(measurement.Substring(len - 22, 6), NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingWhite, - CultureInfo.InvariantCulture, out t) && - measurement[len - 16] == '\t' && - float.TryParse(measurement.Substring(len - 15, 6), NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingWhite, - CultureInfo.InvariantCulture, out h) && - measurement[len - 9] == '\t' && - float.TryParse(measurement.Substring(len - 8, 6), NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingWhite, - CultureInfo.InvariantCulture, out p) && - measurement[len - 2] == '\r' && - measurement[len - 1] == '\n') - { - temperature = t; - humidity = h; - pressure = p; - msrmntTimeStamp = StateMachine.Time; - msrmntState = MsrmntState.Valid; - - log.InfoFormat("Msrmnt OK: time = {0}, temp={1}, humi={2}, pres={3}", msrmntTimeStamp, t, h, p); - } - else - { - log.Warn("Invalid string received: " + measurement); - } - } - } - - /// Run this device - public void RunDeviceAfter() - { - } - - /// Stop this device - public void StopDevice() - { - if (serialPort != null) serialPort.Close(); - } - - /// - /// Boxes for the operation result - /// - FloatBox tempBox; - FloatBox pressureBox; - FloatBox humiBox; - - public IOperation ReadAmbientOp(FloatBox temperature, FloatBox pressure, FloatBox humidity) + /// Run this device + public void RunDeviceBefore() { - this.tempBox = temperature; - this.pressureBox = pressure; - this.humiBox = humidity; + if (pumpCfg.DebugLevel == Entities.DebugMode.Simulate) return; + + responseBuilder.Append(serialPort.ReadExisting()); + + /// Check if the response is complete + if (responseBuilder.Length >= 8) + { + string response = responseBuilder.ToString(); + responseBuilder.Clear(); + + log.Info(Utils.LogMessage("Received ", response)); + } + } + + /// + /// Prepares data to be sent in RunDeviceAfter() function + /// + bool SendData(byte[] data) + { + if (dataToSendReady) return false; + dataToSend = data; + dataToSendReady = true; + + log.Info(Utils.LogMessage("Sending ", data)); + + return true; + } + + /// Run this device + public void RunDeviceAfter() + { + if (dataToSendReady) + { + if (pumpCfg.DebugLevel != Entities.DebugMode.Simulate) + { + serialPort.Write(dataToSend, 0, dataToSend.Length); + } + dataToSendReady = false; + } + } + + /// Stop this device + public void StopDevice() + { + if (serialPort != null) serialPort.Close(); + } + + + /// + /// Turn the pmp on using Modbus commad, use the variable frequency + /// + /// Frequency in percent (-200.0 .. 200.0) + public void TurnOn(float powerArg) + { + log.DebugFormat("{0}.TurnOn({1})", Name, powerArg); + + //UInt16 controlWord = 0x047C; + UInt16 controlWord = (UInt16)(CW.Not_DcBraking | + CW.Not_CoastingStop | + CW.Not_QuickStop | + CW.Not_FreezeFreq | + CW.Start_NotRampStop | + CW.DataValid); + + UInt16 serialComReference = (UInt16)(Int16)((float)0x4000 * powerArg / 100.0f + 0.5f); + + byte[] msg = new byte[13]; + msg[0] = (byte)pumpCfg.ModbusAddress; + msg[1] = (byte)Function.ForceMultipleCoils; + msg[2] = 0; /// Data Hi + msg[3] = 0; /// Data Lo + msg[4] = 0; /// Nr. of coils Hi + msg[5] = 0x20; /// Nr. of coils Lo + msg[6] = 4; /// Byte count + msg[7] = (byte)(controlWord & 0xFF); /// Control Word Lo + msg[8] = (byte)(controlWord >> 8); /// Control Word Hi + msg[9] = (byte)(serialComReference & 0xFF); /// Serial Com Reference Lo + msg[10] = (byte)(serialComReference >> 8); /// Serial Com Reference Hi + + Utils.CalculateCRC(msg); + + SendData(msg); + } + + + /// + /// Turn the pmp off using Modbus command + /// + public void TurnOff() + { + log.DebugFormat("{0}.TurnOff()", Name); + + UInt16 controlWord = (UInt16)(CW.Not_DcBraking | + CW.Not_CoastingStop | + CW.Not_QuickStop | + CW.Not_FreezeFreq | + //CW.Start_NotRampStop | + CW.DataValid); + + UInt16 serialComReference = 0; + + byte[] msg = new byte[13]; + msg[0] = (byte)pumpCfg.ModbusAddress; + msg[1] = (byte)Function.ForceMultipleCoils; + msg[2] = 0; /// Data Hi + msg[3] = 0; /// Data Lo + msg[4] = 0; /// Nr. of coils Hi + msg[5] = 0x20; /// Nr. of coils Lo + msg[6] = 4; /// Byte count + msg[7] = (byte)(controlWord & 0xFF); /// Control Word Lo + msg[8] = (byte)(controlWord >> 8); /// Control Word Hi + msg[9] = (byte)(serialComReference & 0xFF); /// Serial Com Reference Lo + msg[10] = (byte)(serialComReference >> 8); /// Serial Com Reference Hi + + Utils.CalculateCRC(msg); + + SendData(msg); + } + + + /// + /// The currently running operation. + /// + public enum CurrentOp + { + None, + TurnOn, + TurnOff, + } + /// + CurrentOp currentOp; + + float powerForOp; + + /// + /// Turn the pump frequency inverter on. + /// + public IOperation TurnOnOp(float powerArg) + { + if (currentOp != CurrentOp.None) throw new Exception("Sequence error"); + currentOp = CurrentOp.TurnOn; + powerForOp = powerArg; return this; } - /// Start this operation - public void Start() + /// + /// Turn the pump frequency inverter on. + /// + public IOperation TurnOffOp() { - if (tempBox != null) tempBox.Val = temperature; - if (pressureBox != null) pressureBox.Val = pressure; - if (humiBox != null) humiBox.Val = humidity; - } - - /// Run this operation - /// - /// Event.FlowInDone or Event.FlowOutDone - /// - public Event Run() - { - if (tempBox != null) tempBox.Val = temperature; - if (pressureBox != null) pressureBox.Val = pressure; - if (humiBox != null) humiBox.Val = humidity; - return Event.AmbientDone; + if (currentOp != CurrentOp.None) throw new Exception("Sequence error"); + currentOp = CurrentOp.TurnOff; + return this; } - /// Stop this operation + /// Start the operation + public void Start() + { + switch (currentOp) + { + case CurrentOp.TurnOn: + TurnOn(powerForOp); + return; + case CurrentOp.TurnOff: + default: + TurnOff(); + return; + } + } + + /// Run the operation + public Event Run() + { + return Event.TurnPumpOnOffDone; + } + + /// Stop the operation public void Stop() { + currentOp = CurrentOp.None; } } } diff --git a/TestBenchFramework/BenchControl/Danfoss/VLT2800/PumpCfg.cs b/TestBenchFramework/BenchControl/Danfoss/VLT2800/PumpCfg.cs index 63aeae482..8f9efbf81 100644 --- a/TestBenchFramework/BenchControl/Danfoss/VLT2800/PumpCfg.cs +++ b/TestBenchFramework/BenchControl/Danfoss/VLT2800/PumpCfg.cs @@ -14,24 +14,26 @@ namespace TBF.BenchControl.Danfoss.VLT2800 /// /// Serialized parameters /// + public int Delay; // Delay of the pump function in [s] (affects the duration of transition sequence steps) + public int ModbusAddress; // Modbus address in range 1..247 public int ComPortNr; public int BaudRate; public Parity Parity; public int DataBits; public StopBits StopBits; - public Handshake Handshake; - + /// Private parameterless constructor invoked by all other (public) constructors PumpCfg() { Name = "Ambient"; + Delay = 1; + ModbusAddress = 1; ParentName = string.Empty; - ComPortNr = 6; - BaudRate = 19200; - Parity = System.IO.Ports.Parity.None; - DataBits = 8; + ComPortNr = 5; + BaudRate = 9600; + DataBits = 8; + Parity = System.IO.Ports.Parity.None; StopBits = System.IO.Ports.StopBits.One; - Handshake = System.IO.Ports.Handshake.None; } public PumpCfg(IComponentFactory factory) @@ -42,8 +44,8 @@ namespace TBF.BenchControl.Danfoss.VLT2800 public string ToString(int i) { - return string.Format("Name={0}, Com{1}, {2}Bd, {3}-bits, parity={4}, stopBits={5}, {6}", - Name, ComPortNr, BaudRate, DataBits, Parity, StopBits, Handshake); + return string.Format("Name={0}, Delay={1}s, ModbusAddress={2}, Com{3}, {4}Bd, {5}-bits, parity={6}, stopBits={7}", + Name, Delay, ModbusAddress, ComPortNr, BaudRate, DataBits, Parity, StopBits); } } } diff --git a/TestBenchFramework/BenchControl/Danfoss/VLT2800/PumpCfgCtrl.cs b/TestBenchFramework/BenchControl/Danfoss/VLT2800/PumpCfgCtrl.cs index 485de2783..a3cec6c40 100644 --- a/TestBenchFramework/BenchControl/Danfoss/VLT2800/PumpCfgCtrl.cs +++ b/TestBenchFramework/BenchControl/Danfoss/VLT2800/PumpCfgCtrl.cs @@ -35,10 +35,6 @@ namespace TBF.BenchControl.Danfoss.VLT2800 stopBitsComboBox.Items.Add(StopBits.One.ToString()); stopBitsComboBox.Items.Add(StopBits.OnePointFive.ToString()); stopBitsComboBox.Items.Add(StopBits.Two.ToString()); - - handshakeComboBox.Items.Add(Handshake.None.ToString()); - handshakeComboBox.Items.Add(Handshake.RequestToSend.ToString()); - handshakeComboBox.Items.Add(Handshake.XOnXOff.ToString()); } int GetParityIx(Parity par) @@ -103,23 +99,25 @@ namespace TBF.BenchControl.Danfoss.VLT2800 classNameLabel.Text = config.Factory.ClassName; nameTextBox.Text = config.Name; + delayTextBox.Text = config.Delay.ToString(); + modbusAddressTextBox.Text = config.ModbusAddress.ToString(); comPortNrTextBox.Text = config.ComPortNr.ToString(); baudRateTextBox.Text = config.BaudRate.ToString(); parityComboBox.Text = config.Parity.ToString(); dataBitsTextBox.Text = config.DataBits.ToString(); stopBitsComboBox.Text = config.StopBits.ToString(); - handshakeComboBox.Text = config.Handshake.ToString(); } public void Unlock() { nameTextBox.Enabled = true; + delayTextBox.Enabled = true; + modbusAddressTextBox.Enabled = true; comPortNrTextBox.Enabled = true; baudRateTextBox.Enabled = true; parityComboBox.Enabled = true; dataBitsTextBox.Enabled = true; stopBitsComboBox.Enabled = true; - handshakeComboBox.Enabled = true; } public CfgUpdateFlags UpdateCfg() @@ -129,12 +127,13 @@ namespace TBF.BenchControl.Danfoss.VLT2800 if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed config.Name = nameTextBox.Text; + config.Delay = int.Parse(delayTextBox.Text); + config.ModbusAddress = int.Parse(modbusAddressTextBox.Text); config.ComPortNr = int.Parse(comPortNrTextBox.Text); config.BaudRate = int.Parse(baudRateTextBox.Text); config.Parity = GetParity(parityComboBox.SelectedItem.ToString()); config.DataBits = int.Parse(dataBitsTextBox.Text); config.StopBits = GetStopBits(stopBitsComboBox.SelectedItem.ToString()); - config.Handshake = GetHandshake(handshakeComboBox.SelectedItem.ToString()); return flags; } @@ -144,6 +143,18 @@ namespace TBF.BenchControl.Danfoss.VLT2800 CfgUpdateFlags flags = CfgUpdateFlags.None; int dummy; + if (!int.TryParse(delayTextBox.Text, out dummy) || dummy < 0 || dummy > 300) + { + flags |= CfgUpdateFlags.Error; + message += Environment.NewLine + "'Delay' is not valid"; + } + + if (!int.TryParse(modbusAddressTextBox.Text, out dummy) || dummy < 1 || dummy > 247) + { + flags |= CfgUpdateFlags.Error; + message += Environment.NewLine + "'Modbus Address' should be in range 1..247"; + } + if (!int.TryParse(comPortNrTextBox.Text, out dummy) || dummy < 1 || dummy > 999) { flags |= CfgUpdateFlags.Error; diff --git a/TestBenchFramework/BenchControl/Danfoss/VLT2800/PumpCfgCtrl.designer.cs b/TestBenchFramework/BenchControl/Danfoss/VLT2800/PumpCfgCtrl.designer.cs index 0a66c86f9..c447b55cf 100644 --- a/TestBenchFramework/BenchControl/Danfoss/VLT2800/PumpCfgCtrl.designer.cs +++ b/TestBenchFramework/BenchControl/Danfoss/VLT2800/PumpCfgCtrl.designer.cs @@ -36,92 +36,94 @@ this.dataBitsLabel = new System.Windows.Forms.Label(); this.dataBitsTextBox = new System.Windows.Forms.TextBox(); this.stopBitsLabel = new System.Windows.Forms.Label(); - this.handshakeLabel = new System.Windows.Forms.Label(); + this.modbusAddressLabel = new System.Windows.Forms.Label(); this.nameTextBox = new System.Windows.Forms.TextBox(); this.nameLabel = new System.Windows.Forms.Label(); this.classNameLabel = new System.Windows.Forms.Label(); this.parityComboBox = new System.Windows.Forms.ComboBox(); this.stopBitsComboBox = new System.Windows.Forms.ComboBox(); - this.handshakeComboBox = new System.Windows.Forms.ComboBox(); + this.modbusAddressTextBox = new System.Windows.Forms.TextBox(); + this.delayTextBox = new System.Windows.Forms.TextBox(); + this.delayLabel = new System.Windows.Forms.Label(); this.SuspendLayout(); // // comPortNrTextBox // this.comPortNrTextBox.Enabled = false; - this.comPortNrTextBox.Location = new System.Drawing.Point(140, 52); + this.comPortNrTextBox.Location = new System.Drawing.Point(140, 107); this.comPortNrTextBox.Name = "comPortNrTextBox"; this.comPortNrTextBox.Size = new System.Drawing.Size(34, 20); - this.comPortNrTextBox.TabIndex = 4; + this.comPortNrTextBox.TabIndex = 6; // // label1 // this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(29, 55); + this.label1.Location = new System.Drawing.Point(29, 110); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(98, 13); - this.label1.TabIndex = 3; + this.label1.TabIndex = 5; this.label1.Text = "Serial Port Number:"; // // baudRateLabel // this.baudRateLabel.AutoSize = true; - this.baudRateLabel.Location = new System.Drawing.Point(29, 79); + this.baudRateLabel.Location = new System.Drawing.Point(29, 134); this.baudRateLabel.Name = "baudRateLabel"; this.baudRateLabel.Size = new System.Drawing.Size(58, 13); - this.baudRateLabel.TabIndex = 5; + this.baudRateLabel.TabIndex = 7; this.baudRateLabel.Text = "Baud Rate"; // // baudRateTextBox // this.baudRateTextBox.Enabled = false; - this.baudRateTextBox.Location = new System.Drawing.Point(140, 76); + this.baudRateTextBox.Location = new System.Drawing.Point(140, 131); this.baudRateTextBox.Name = "baudRateTextBox"; this.baudRateTextBox.Size = new System.Drawing.Size(130, 20); - this.baudRateTextBox.TabIndex = 6; + this.baudRateTextBox.TabIndex = 8; // // partityLabel // this.partityLabel.AutoSize = true; - this.partityLabel.Location = new System.Drawing.Point(29, 103); + this.partityLabel.Location = new System.Drawing.Point(29, 158); this.partityLabel.Name = "partityLabel"; this.partityLabel.Size = new System.Drawing.Size(33, 13); - this.partityLabel.TabIndex = 7; + this.partityLabel.TabIndex = 9; this.partityLabel.Text = "Parity"; // // dataBitsLabel // this.dataBitsLabel.AutoSize = true; - this.dataBitsLabel.Location = new System.Drawing.Point(29, 127); + this.dataBitsLabel.Location = new System.Drawing.Point(29, 182); this.dataBitsLabel.Name = "dataBitsLabel"; this.dataBitsLabel.Size = new System.Drawing.Size(50, 13); - this.dataBitsLabel.TabIndex = 9; + this.dataBitsLabel.TabIndex = 11; this.dataBitsLabel.Text = "Data Bits"; // // dataBitsTextBox // this.dataBitsTextBox.Enabled = false; - this.dataBitsTextBox.Location = new System.Drawing.Point(140, 124); + this.dataBitsTextBox.Location = new System.Drawing.Point(140, 179); this.dataBitsTextBox.Name = "dataBitsTextBox"; this.dataBitsTextBox.Size = new System.Drawing.Size(34, 20); - this.dataBitsTextBox.TabIndex = 10; + this.dataBitsTextBox.TabIndex = 12; // // stopBitsLabel // this.stopBitsLabel.AutoSize = true; - this.stopBitsLabel.Location = new System.Drawing.Point(29, 151); + this.stopBitsLabel.Location = new System.Drawing.Point(29, 206); this.stopBitsLabel.Name = "stopBitsLabel"; this.stopBitsLabel.Size = new System.Drawing.Size(49, 13); - this.stopBitsLabel.TabIndex = 11; + this.stopBitsLabel.TabIndex = 13; this.stopBitsLabel.Text = "Stop Bits"; // - // handshakeLabel + // modbusAddressLabel // - this.handshakeLabel.AutoSize = true; - this.handshakeLabel.Location = new System.Drawing.Point(29, 175); - this.handshakeLabel.Name = "handshakeLabel"; - this.handshakeLabel.Size = new System.Drawing.Size(62, 13); - this.handshakeLabel.TabIndex = 13; - this.handshakeLabel.Text = "Handshake"; + this.modbusAddressLabel.AutoSize = true; + this.modbusAddressLabel.Location = new System.Drawing.Point(29, 79); + this.modbusAddressLabel.Name = "modbusAddressLabel"; + this.modbusAddressLabel.Size = new System.Drawing.Size(86, 13); + this.modbusAddressLabel.TabIndex = 3; + this.modbusAddressLabel.Text = "Modbus Address"; // // nameTextBox // @@ -153,41 +155,59 @@ // this.parityComboBox.Enabled = false; this.parityComboBox.FormattingEnabled = true; - this.parityComboBox.Location = new System.Drawing.Point(140, 100); + this.parityComboBox.Location = new System.Drawing.Point(140, 155); this.parityComboBox.Name = "parityComboBox"; this.parityComboBox.Size = new System.Drawing.Size(130, 21); - this.parityComboBox.TabIndex = 8; + this.parityComboBox.TabIndex = 10; // // stopBitsComboBox // this.stopBitsComboBox.Enabled = false; this.stopBitsComboBox.FormattingEnabled = true; - this.stopBitsComboBox.Location = new System.Drawing.Point(140, 148); + this.stopBitsComboBox.Location = new System.Drawing.Point(140, 203); this.stopBitsComboBox.Name = "stopBitsComboBox"; this.stopBitsComboBox.Size = new System.Drawing.Size(130, 21); - this.stopBitsComboBox.TabIndex = 12; + this.stopBitsComboBox.TabIndex = 14; // - // handshakeComboBox + // modbusAddressTextBox // - this.handshakeComboBox.Enabled = false; - this.handshakeComboBox.FormattingEnabled = true; - this.handshakeComboBox.Location = new System.Drawing.Point(140, 172); - this.handshakeComboBox.Name = "handshakeComboBox"; - this.handshakeComboBox.Size = new System.Drawing.Size(130, 21); - this.handshakeComboBox.TabIndex = 14; + this.modbusAddressTextBox.Enabled = false; + this.modbusAddressTextBox.Location = new System.Drawing.Point(140, 77); + this.modbusAddressTextBox.Name = "modbusAddressTextBox"; + this.modbusAddressTextBox.Size = new System.Drawing.Size(34, 20); + this.modbusAddressTextBox.TabIndex = 4; // - // AmbientCfgCtrl + // delayTextBox + // + this.delayTextBox.Enabled = false; + this.delayTextBox.Location = new System.Drawing.Point(140, 53); + this.delayTextBox.Name = "delayTextBox"; + this.delayTextBox.Size = new System.Drawing.Size(34, 20); + this.delayTextBox.TabIndex = 16; + // + // delayLabel + // + this.delayLabel.AutoSize = true; + this.delayLabel.Location = new System.Drawing.Point(29, 55); + this.delayLabel.Name = "delayLabel"; + this.delayLabel.Size = new System.Drawing.Size(45, 13); + this.delayLabel.TabIndex = 15; + this.delayLabel.Text = "Delay[s]"; + // + // PumpCfgCtrl // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.BackColor = System.Drawing.SystemColors.Control; - this.Controls.Add(this.handshakeComboBox); + this.Controls.Add(this.delayTextBox); + this.Controls.Add(this.delayLabel); + this.Controls.Add(this.modbusAddressTextBox); this.Controls.Add(this.stopBitsComboBox); this.Controls.Add(this.parityComboBox); this.Controls.Add(this.nameTextBox); this.Controls.Add(this.nameLabel); this.Controls.Add(this.classNameLabel); - this.Controls.Add(this.handshakeLabel); + this.Controls.Add(this.modbusAddressLabel); this.Controls.Add(this.stopBitsLabel); this.Controls.Add(this.dataBitsTextBox); this.Controls.Add(this.dataBitsLabel); @@ -196,7 +216,7 @@ this.Controls.Add(this.baudRateLabel); this.Controls.Add(this.comPortNrTextBox); this.Controls.Add(this.label1); - this.Name = "AmbientCfgCtrl"; + this.Name = "PumpCfgCtrl"; this.Size = new System.Drawing.Size(300, 240); this.Load += new System.EventHandler(this.AbbientCfgCtrl_Load); this.ResumeLayout(false); @@ -214,13 +234,15 @@ private System.Windows.Forms.Label dataBitsLabel; private System.Windows.Forms.TextBox dataBitsTextBox; private System.Windows.Forms.Label stopBitsLabel; - private System.Windows.Forms.Label handshakeLabel; + private System.Windows.Forms.Label modbusAddressLabel; private System.Windows.Forms.TextBox nameTextBox; private System.Windows.Forms.Label nameLabel; private System.Windows.Forms.Label classNameLabel; private System.Windows.Forms.ComboBox parityComboBox; private System.Windows.Forms.ComboBox stopBitsComboBox; - private System.Windows.Forms.ComboBox handshakeComboBox; + private System.Windows.Forms.TextBox modbusAddressTextBox; + private System.Windows.Forms.TextBox delayTextBox; + private System.Windows.Forms.Label delayLabel; } } diff --git a/TestBenchFramework/Utils.cs b/TestBenchFramework/Utils.cs index 961b10212..bddc061d3 100644 --- a/TestBenchFramework/Utils.cs +++ b/TestBenchFramework/Utils.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Globalization; namespace TBF @@ -249,5 +250,80 @@ namespace TBF } else return value.ToString(); } - } + + + public static string LogMessage(string intro, byte[] data) + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(80); + + sb.Append(intro); + sb.Append(data.Length.ToString()); + sb.Append(" bytes:"); + foreach (var d in data) + { + sb.Append(" "); + sb.Append(((int)d).ToString("X2")); + } + + return sb.ToString(); + } + + public static string LogMessage(string intro, string data) + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(80); + + sb.Append(intro); + sb.Append(data.Length.ToString()); + sb.Append(" bytes:"); + foreach (var d in data) + { + sb.Append(" "); + sb.Append(((int)d).ToString("X2")); + } + + return sb.ToString(); + } + + + const UInt16 crcSeed = 0xFFFF; // Initial crc value + const UInt16 crcGP = 0xA001; // Generating polynomial + + /// + /// For standard CRC16 (remainder of division) + /// to start a new crc, set CRC16 = SEED + /// then for each byte call UpdateCRC(byte, &CRC16); + /// CRC16 will contain the result + /// (if you calculate all of the incoming data + /// INCLUDING the crc, the result should be 0x0000 + /// and if you are sending the crc be sure to + /// send the bytes in the correct order) + /// + static void UpdateCRC(byte b, ref UInt16 crc) + { + crc ^= (UInt16)b; + for (int i = 0; i < 8; i++) + { + bool carry = (crc & 0x0001) != 0; + crc >>= 1; + if (carry) crc ^= crcGP; + } + } + + /// + /// This function modifies the last 2 bytes in the message buffer + /// by the crc calculated from the remainin first (Lenght - 2) bytes. + /// + /// + public static void CalculateCRC(byte[] data) + { + int len = data.Length; + + if (len < 2) return; + + UInt16 crc = crcSeed; + for (int i = 0; i < len - 2; i++) UpdateCRC(data[i], ref crc); + data[len - 2] = (byte)(crc & 0xFF); + data[len - 1] = (byte)(crc >> 8); + } + } }