Modbus modified, UniCB Init. modified, RunDeviceAfter() called in reversed order, ver. 3.1.1597

This commit is contained in:
Milan Hanajik 2021-03-17 21:27:40 +01:00
parent ff70a11cad
commit d7e65ff04b
14 changed files with 293 additions and 157 deletions

View File

@ -47,6 +47,21 @@ namespace Common
return crc;
}
/// <summary>
/// Calculates the CRC from a data telegram (an array of bytes).
/// A complete telegram including two bytes reserved for the CRC
/// must be supplied as an argument.
/// </summary>
/// <param name="data">Data telegram</param>
/// <returns>Calculated CRC</returns>
public static UInt16 CalculateTelegramCRC(int offset, byte[] data, int enforcedLen = 0)
{
int len = (enforcedLen != 0) ? Math.Min(enforcedLen, data.Length - offset) : data.Length - offset;
UInt16 crc = crcSeed;
for (int i = 0; i < len - 2; i++) UpdateCRC(data[offset + i], ref crc);
return crc;
}
/// <summary>
/// This function modifies the last 2 bytes in the message buffer
/// by the CRC calculated from the remaining first (Lenght - 2) bytes.
@ -85,6 +100,26 @@ namespace Common
return (data[len - 2] == (byte)(crc & 0xFF)) && (data[len - 1] == (byte)(crc >> 8));
}
/// <summary>
/// This function compares the last 2 bytes in the message buffer
/// with the CRC calculated from the remaining first (Lenght - 2) bytes.
/// A complete telegram including two bytes reserved for the CRC
/// must be supplied as an argument.
/// </summary>
/// <param name="data">Data telegram</param>
/// <returns>true if the CRC in the telegram is correct</returns>
public static bool VerifyTelegramCRC(int offset, byte[] data, int enforcedLen = 0)
{
if (data == null || data.Length == 0 || enforcedLen > data.Length - offset) return false;
int len = (enforcedLen != 0) ? enforcedLen : data.Length - offset;
if (len < 2) return false;
UInt16 crc = CalculateTelegramCRC(offset, data, len);
return (data[offset + len - 2] == (byte)(crc & 0xFF)) && (data[offset + len - 1] == (byte)(crc >> 8));
}
/// <summary>

View File

@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
// Build Number
// Revision
//
[assembly: AssemblyVersion("3.1.1643.0")]
[assembly: AssemblyFileVersion("3.1.1643.0")]
[assembly: AssemblyVersion("3.1.1597.0")]
[assembly: AssemblyFileVersion("3.1.1597.0")]

View File

@ -179,12 +179,6 @@ namespace TBF.Rig.ControlBoard.Uni
scopeAnalyzerData = null;
switchCounterData = null;
serialPort = null;
buffer = new byte[BUFFER_SIZE];
rcvdData = new byte[BUFFER_SIZE];
cumulativeSums = new int[BUFFER_SIZE];
rcvdBytesCount = 0;
routeMask = 0;
for (int i = 0; i < 128; i++)
{
@ -194,19 +188,6 @@ namespace TBF.Rig.ControlBoard.Uni
}
}
TBF.UiBridge.Bridge.RouteChangeHandler += delegate(object sndr, TBF.UiBridge.RouteChangeArgs args)
{
UInt128 mask = ((UInt128)1) << args.BitNr;
if ((benchModelRoute & mask) == 0)
{
benchModelRoute |= mask;
}
else
{
benchModelRoute &= (~mask);
}
};
log.Warn(this.ToString());
}
@ -233,12 +214,30 @@ namespace TBF.Rig.ControlBoard.Uni
return;
}
buffer = new byte[BUFFER_SIZE];
rcvdData = new byte[BUFFER_SIZE];
cumulativeSums = new int[BUFFER_SIZE];
rcvdBytesCount = 0;
serialPort = new SerialPort(comPort, 9600, Parity.None, 8, StopBits.One);
serialPort.DtrEnable = true;
serialPort.WriteTimeout = 4000;
serialPort.ParityReplace = 0xFF;
serialPort.Open();
TBF.UiBridge.Bridge.RouteChangeHandler += delegate(object sndr, TBF.UiBridge.RouteChangeArgs args)
{
UInt128 mask = ((UInt128)1) << args.BitNr;
if ((benchModelRoute & mask) == 0)
{
benchModelRoute |= mask;
}
else
{
benchModelRoute &= (~mask);
}
};
log.FatalFormat("{0} - Device successfully initialized", Name);
}

View File

@ -27,5 +27,18 @@ namespace TBF.Rig.GenericDevices
void SendMessage(byte modbusAddress, byte function, ushort dataAddress, ushort dataCount);
Queue<byte[]>[] ReceivedTelegrams { get; }
/// <summary>
/// Registers a modbus device for scheduled polling
/// </summary>
/// <returns>Ticket numeber to be used as IsMyTurn() argumenr</returns>
int RegisterForPolling();
/// <summary>
/// Determines whether the registered device should do polling now
/// </summary>
/// <param name="ticketNr">Ticket number in range 1 .. registered devs.count returned by RegisterForPolling()</param>
/// <returns>true when yes</returns>
bool IsMyTurn(int ticketNr);
}
}

View File

@ -74,9 +74,10 @@ namespace TBF.Rig.Modbus.Ambient.Comet
/// <summary>Measurement time stamp when MsrmntState == MsrmntState.Valid</summary>
int msrmntTimeStamp;
public Ambient()
{
}
int ticketNumber; /// 1 .. number of devices registered for regular polling
public Ambient() { }
/// <summary>
/// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232)
@ -106,6 +107,7 @@ namespace TBF.Rig.Modbus.Ambient.Comet
}
msrmntState = MsrmntState.Busy;
ticketNumber = modbus.RegisterForPolling();
log.FatalFormat("Successfully initialized device {0}", ToString());
}
@ -143,8 +145,13 @@ namespace TBF.Rig.Modbus.Ambient.Comet
log.InfoFormat("Ambient: temperature = {0:F1} C, humidity = {1:F1} %, pressure = {2:F0} mbar", temperature, humidity, 1000 * pressure);
}
}
}
if ((StateMachine.Time % 10) == (ambientCfg.ModbusAddress % 10)) /// Each 10 seconds
public void RunDeviceAfter()
{
if (ambientCfg.DebugLevel != Config.Entities.DebugMode.Simulate &&
ambientCfg.DebugLevel != Config.Entities.DebugMode.FailureDuringOperation &&
modbus.IsMyTurn(ticketNumber))
{
/// Read four registers: 0x31, 0x32, 0x33, 0x34
UInt16 regAddr = 0x0030; /// register addr. = 0x31 (Modbus!)
@ -163,7 +170,6 @@ namespace TBF.Rig.Modbus.Ambient.Comet
}
}
public void RunDeviceAfter() { }
public void StopDevice() { }
public void StopDevice2() { }

View File

@ -27,10 +27,14 @@ namespace TBF.Rig.Modbus.Common
const int MinTelegramLen = 4;
private readonly ModbusCfg modbusCommonCfg;
private readonly ModbusCfg modbusCfg;
/// Private fields
SerialPort serialPort;
const int BUFFER_SIZE = 1000; /// Size of input buffers
byte[] buffer; /// Buffer for data received in one attempt in RunDeviceBefore()
byte[] rcvdData; /// Buffer for all recevied but nut processed data. May contain data from several read attempts
int rcvdBytesCount; /// Count of valid bytes in rcvdData buffer
DateTime lastSerialPortWrite;
bool initialRunDeviceCommComplete;
@ -42,9 +46,10 @@ namespace TBF.Rig.Modbus.Common
Queue<byte[]> telegramsToSend;
public Modbus()
{
}
int registeredDevicesCount; /// Number of devices registered for poling
public Modbus() { }
/// <summary>
/// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232)
@ -53,36 +58,37 @@ namespace TBF.Rig.Modbus.Common
public Modbus(Generic.IComponentCfg cfg)
: base(cfg)
{
receivedTelegrams = new Queue<byte[]>[256];
for (int i = 0; i < receivedTelegrams.Length; i++)
{
receivedTelegrams[i] = new Queue<byte[]>();
}
telegramsToSend = new Queue<byte[]>();
serialPort = null;
modbusCommonCfg = cfg as ModbusCfg;
modbusCfg = cfg as ModbusCfg;
log.Warn(this.ToString());
}
~Modbus()
{
}
public void Initialize()
{
if (modbusCommonCfg.DebugLevel == DebugMode.Simulate)
receivedTelegrams = new Queue<byte[]>[256];
for (int i = 0; i < receivedTelegrams.Length; i++)
{
receivedTelegrams[i] = new Queue<byte[]>();
}
telegramsToSend = new Queue<byte[]>();
if (modbusCfg.DebugLevel == DebugMode.Simulate)
{
serialPort = null;
log.FatalFormat("{0} - Device simulated", Name);
return;
}
string comPortName = "COM" + modbusCommonCfg.ComPortNr.ToString();
serialPort = new SerialPort(comPortName, modbusCommonCfg.BaudRate, modbusCommonCfg.Parity, modbusCommonCfg.DataBits, modbusCommonCfg.StopBits);
serialPort.Handshake = modbusCommonCfg.Handshake;
buffer = new byte[BUFFER_SIZE];
rcvdData = new byte[BUFFER_SIZE];
rcvdBytesCount = 0;
string comPortName = "COM" + modbusCfg.ComPortNr.ToString();
serialPort = new SerialPort(comPortName, modbusCfg.BaudRate, modbusCfg.Parity, modbusCfg.DataBits, modbusCfg.StopBits);
serialPort.Handshake = modbusCfg.Handshake;
serialPort.Open();
registeredDevicesCount = 0;
//stopWorkerThread = false;
//workerThread = new Thread(Worker);
//workerThread.Start();
@ -93,6 +99,27 @@ namespace TBF.Rig.Modbus.Common
}
/// <summary>
/// Registers a modbus device for scheduled polling
/// </summary>
/// <returns>Ticket numeber to be used as IsMyTurn() argumenr</returns>
public int RegisterForPolling()
{
registeredDevicesCount++;
return registeredDevicesCount; /// 1 .. number of registered devices
}
/// <summary>
/// Determines whether the registered device should do polling now
/// </summary>
/// <param name="ticketNr">Ticket number in range 1 .. registered devs.count returned by RegisterForPolling()</param>
/// <returns>true when yes</returns>
public bool IsMyTurn(int ticketNr)
{
return (StateMachine.Time % registeredDevicesCount == ticketNr - 1);
}
/// <summary>
/// Send an arbitrary modbus message.
/// When the message length is N, however only bytes 1..N-2 have to be set.
@ -189,69 +216,92 @@ namespace TBF.Rig.Modbus.Common
/// <summary>Run this device</summary>
public void RunDeviceBefore()
{
/// Create 'dataToProcess' buffer with all received bytes
int nrBytes;
if (serialPort == null || (nrBytes = serialPort.BytesToRead) < MinTelegramLen) return;
byte[] dataToProcess = new byte[nrBytes];
serialPort.Read(dataToProcess, 0, nrBytes);
if (modbusCfg.DebugLevel != DebugMode.Normal || serialPort == null || !serialPort.IsOpen) return;
while (dataToProcess.Length >= MinTelegramLen)
/// Read new received bytes and append them to a buffer
int bytesCount = serialPort.BytesToRead;
if (bytesCount > 0)
{
for (int candidateLen = MinTelegramLen; candidateLen <= dataToProcess.Length; candidateLen++)
bytesCount = serialPort.Read(buffer, 0, Math.Min(bytesCount, BUFFER_SIZE));
}
///
string st = string.Format("{0}", Name, Telegram.LogTelegram("Received data ", buffer, 0, bytesCount));
Debug.WriteLine(st);
log.Debug(st);
///
for (int i = 0; i < bytesCount && rcvdBytesCount < BUFFER_SIZE; i++, rcvdBytesCount++)
{
rcvdData[rcvdBytesCount] = buffer[i];
}
/// Try to detect various kinds of data in rcvdData buffer in a loop, start at offset 0
int offset = 0;
int lastValidOffset = 0; /// Offset of the first byte after the last successfully parsed frame
do
{
bool anyProcessed = false;
if (offset + 28 <= rcvdBytesCount &&
rcvdData[offset] == '\r' &&
rcvdData[offset + 1] == '\n' &&
rcvdData[offset + 3] == 28 &&
rcvdData[offset + 5] == 2)
{
if (candidateLen == 28 &&
dataToProcess[0] == '\r' &&
dataToProcess[1] == '\n' &&
dataToProcess[3] == 28 &&
dataToProcess[5] == 2)
int sum = 0;
for (int i = offset; i < offset + 27; i++) sum += rcvdData[i];
///
if (rcvdData[offset + 27] == (sum & 0xFF))
{
int sum = 0;
for (int i = 0; i < 27; i++) sum += dataToProcess[i];
///
if (dataToProcess[27] == (sum & 0xFF))
{
/// Split data in dataToProcess buffer into the verified telegram and newly created dataToProcess
byte[] receivedTelegram = dataToProcess.Take<byte>(candidateLen).ToArray<byte>();
dataToProcess = dataToProcess.Skip<byte>(candidateLen).ToArray<byte>();
/// Copy data to a created telegram
byte[] receivedTelegram = new byte[28];
for (int i = 0; i < 28; i++) receivedTelegram[i] = rcvdData[offset + i];
/// Enqueue
receivedTelegrams[0].Enqueue(receivedTelegram);
/// Enqueue
receivedTelegrams[0].Enqueue(receivedTelegram);
string s = string.Format("{0} - {1} queue size={2}", Name, Telegram.LogTelegram("Received message ", receivedTelegram), receivedTelegrams[0].Count);
Debug.WriteLine(s);
log.Debug(s);
break; /// Quit for loop
}
string s = string.Format("{0} queue size={1}", Telegram.LogTelegram("Received message ", receivedTelegram), receivedTelegrams[0].Count);
Debug.WriteLine(s);
log.Debug(s);
offset += 28;
lastValidOffset = offset;
anyProcessed = true;
}
}
if (Telegram.VerifyTelegramCRC(dataToProcess, candidateLen))
for (int candidateLen = 4; candidateLen <= rcvdBytesCount - offset; candidateLen++)
{
if (Telegram.VerifyTelegramCRC(offset, rcvdData, candidateLen))
{
/// A valid telegram found in dataToProcess buffer
/// Split data in dataToProcess buffer into the verified telegram and newly created dataToProcess
byte[] receivedTelegram = dataToProcess.Take<byte>(candidateLen).ToArray<byte>();
dataToProcess = dataToProcess.Skip<byte>(candidateLen).ToArray<byte>();
/// Copy data to a created telegram
byte[] receivedTelegram = new byte[candidateLen];
for (int i = 0; i < candidateLen; i++) receivedTelegram[i] = rcvdData[offset + i];
/// Enqueue
int deviceAddress = receivedTelegram[0];
receivedTelegrams[deviceAddress].Enqueue(receivedTelegram);
string s = string.Format("{0} - {1} queue size={2}", Name, Telegram.LogTelegram("Received message ", receivedTelegram), receivedTelegrams[deviceAddress].Count);
string s = string.Format("{0} queue size={1}", Telegram.LogTelegram("Received message ", receivedTelegram), receivedTelegrams[deviceAddress].Count);
Debug.WriteLine(s);
log.Debug(s);
break; /// Quit for loop
}
else if (candidateLen == dataToProcess.Length)
{
/// All bytes considered but no valid telegram found
string s = Telegram.LogTelegram(string.Format("{0} - Invalid data received ", Name), dataToProcess);
Debug.WriteLine(s);
log.Debug(s);
return;
offset += candidateLen;
lastValidOffset = offset;
anyProcessed = true;
}
}
if (!anyProcessed) offset++;
}
}
while (offset <= rcvdBytesCount - 4);
/// Remove processed data from the receive buffer
for (int i = lastValidOffset; i < rcvdBytesCount; i++)
{
rcvdData[i - lastValidOffset] = rcvdData[i];
}
rcvdBytesCount -= lastValidOffset;
}
/// <summary>Run this device</summary>
public void RunDeviceAfter()

View File

@ -24,9 +24,10 @@ namespace TBF.Rig.Modbus.Easytherm
public float requiredTemp { get { return easythermCfg.ProcParams.RequiredTemp; } }
public Easytherm()
{
}
int ticketNumber; /// 1 .. number of devices registered for regular polling
public Easytherm() { }
public Easytherm(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
: base(cfg)
@ -47,6 +48,7 @@ namespace TBF.Rig.Modbus.Easytherm
temperatureSetPointValid = false;
temperatureSetPointRequested = false;
actualTemperatureIsValid = false;
ticketNumber = modbus.RegisterForPolling();
}
/// <summary>Run this device</summary>
@ -81,26 +83,31 @@ namespace TBF.Rig.Modbus.Easytherm
// StateMachine.ControlBoard.UpdateUI("ReservoirTemp", easythermCfg.ReservoirNr, actualTemperature);
}
}
}
if (!temperatureSetPointValid && !temperatureSetPointRequested)
{
RequestTemperatureSetpoint();
temperatureSetPointRequested = true;
}
else if (temperatureSetPointValid && requiredTemp != temperatureSetPoint)
{
SetTemperatureSetpoint(requiredTemp);
log.InfoFormat("{0} - Set new temperature setpoint = {1}", Name, requiredTemp);
}
else if ((StateMachine.Time % 10) == (easythermCfg.ModbusAddress % 10)) /// This is to prevent overflow of the Modbus component queue for sending data
}
}
public void RunDeviceAfter()
{
if (easythermCfg.DebugLevel != Config.Entities.DebugMode.Simulate &&
easythermCfg.DebugLevel != Config.Entities.DebugMode.FailureDuringOperation)
{
RequestActualTemperature();
if (!temperatureSetPointValid && !temperatureSetPointRequested)
{
RequestTemperatureSetpoint();
temperatureSetPointRequested = true;
}
else if (temperatureSetPointValid && requiredTemp != temperatureSetPoint)
{
SetTemperatureSetpoint(requiredTemp);
log.InfoFormat("{0} - Set new temperature setpoint = {1}", Name, requiredTemp);
}
else if (modbus.IsMyTurn(ticketNumber))
{
RequestActualTemperature();
}
}
}
public void RunDeviceAfter() { }
public void StopDevice() { }
public void StopDevice2() { }

View File

@ -20,6 +20,6 @@ namespace TBF.Rig.Modbus
public static class Constants
{
public const int ModbusPollPeriod = 4;
public const int ModbusPollPeriod = 5;
}
}

View File

@ -25,6 +25,8 @@ namespace TBF.Rig.Modbus.PressureMeter.Meret
public double MeasuredVal { get { return receivedPressure; } }
public string AltString { get { return string.Empty; } }
int ticketNumber; /// 1 .. number of devices registered for regular polling
public PressureMeter() { }
@ -42,7 +44,10 @@ namespace TBF.Rig.Modbus.PressureMeter.Meret
///
/// IDevice interface
///
public void Initialize() { }
public void Initialize()
{
ticketNumber = modbus.RegisterForPolling();
}
public void RunDeviceBefore()
{
@ -71,8 +76,13 @@ namespace TBF.Rig.Modbus.PressureMeter.Meret
log.WarnFormat("Pressure: {0}={1}bar", Name, receivedPressure.ToString("F3"));
}
}
}
if ((StateMachine.Time % Constants.ModbusPollPeriod) == (pressureMtrCfg.ModbusAddress % Constants.ModbusPollPeriod)) /// Each 'ModbusDevices' seconds
public void RunDeviceAfter()
{
if (pressureMtrCfg.DebugLevel != Config.Entities.DebugMode.Simulate &&
pressureMtrCfg.DebugLevel != Config.Entities.DebugMode.FailureDuringOperation &&
modbus.IsMyTurn(ticketNumber))
{
const byte Function = 4; /// Read input registers
const ushort Address = 0; /// Pressure
@ -80,7 +90,6 @@ namespace TBF.Rig.Modbus.PressureMeter.Meret
}
}
public void RunDeviceAfter() { }
public void StopDevice() { }
public void StopDevice2() { }

View File

@ -42,9 +42,10 @@ namespace TBF.Rig.Modbus.TempMeter.Groch
public double MeasuredVal { get { return ReadTemperature(); } }
public string AltString { get { return "Invalid format"; } }
public TempMeter()
{
}
int ticketNumber; /// 1 .. number of devices registered for regular polling
public TempMeter() { }
public TempMeter(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
: base(cfg)
@ -89,7 +90,15 @@ namespace TBF.Rig.Modbus.TempMeter.Groch
return calendarEvents;
}
public void Initialize() { }
public void Initialize()
{
/// Only TempMeter with Channel == 0 communicates via the parent Modbus component
if (Channel == 0)
{
ticketNumber = modbus.RegisterForPolling();
}
}
public void RunDeviceBefore()
{
if (Channel != 0 ||
@ -104,7 +113,7 @@ namespace TBF.Rig.Modbus.TempMeter.Groch
///
if (modbus.ReceivedTelegrams[0].Count > 0)
{
byte[] telegram = modbus.ReceivedTelegrams[GrochAddress].Dequeue();
byte[] telegram = modbus.ReceivedTelegrams[0].Dequeue();
if (telegram.Length == 28)
{
byte checksum = 0;
@ -138,17 +147,12 @@ namespace TBF.Rig.Modbus.TempMeter.Groch
}
public void RunDeviceAfter()
{
if (Channel != 0 ||
tempMtrCfg.DebugLevel == Config.Entities.DebugMode.Simulate ||
tempMtrCfg.DebugLevel == Config.Entities.DebugMode.FailureDuringOperation)
{
return;
}
///
/// Only TempMeter with Channel == 0 communicates via the parent Modbus component
///
if ((StateMachine.Time % Constants.ModbusPollPeriod) == Constants.ModbusPollPeriod) /// Each 'ModbusDevices' seconds
if (Channel == 0 &&
tempMtrCfg.DebugLevel != Config.Entities.DebugMode.Simulate &&
tempMtrCfg.DebugLevel != Config.Entities.DebugMode.FailureDuringOperation &&
modbus.IsMyTurn(ticketNumber))
{
modbus.SendMessageGroch(new byte[] { 0x20, 0x20, 0x20, 0x20, 0x10, 2, 1, 3, 6, 0x16 });
}

View File

@ -25,6 +25,8 @@ namespace TBF.Rig.Modbus.TempMeter.Meret
public double MeasuredVal { get { return receivedTemp; } }
public string AltString { get { return string.Empty; } }
int ticketNumber; /// 1 .. number of devices registered for regular polling
public TempMeter() { }
@ -42,7 +44,10 @@ namespace TBF.Rig.Modbus.TempMeter.Meret
///
/// IDevice interface
///
public void Initialize() { }
public void Initialize()
{
ticketNumber = modbus.RegisterForPolling();
}
/// <summary>Run this device</summary>
public void RunDeviceBefore()
@ -72,8 +77,13 @@ namespace TBF.Rig.Modbus.TempMeter.Meret
log.WarnFormat("Temperature: {0}={1}°C", Name, receivedTemp.ToString("F1"));
}
}
}
if ((StateMachine.Time % Constants.ModbusPollPeriod) == (tempMtrCfg.ModbusAddress % Constants.ModbusPollPeriod)) /// Each 'ModbusDevices' seconds
public void RunDeviceAfter()
{
if (tempMtrCfg.DebugLevel != Config.Entities.DebugMode.Simulate &&
tempMtrCfg.DebugLevel != Config.Entities.DebugMode.FailureDuringOperation &&
modbus.IsMyTurn(ticketNumber))
{
const byte Function = 4; /// Read input registers
const ushort Address = 0; /// Temperature
@ -81,7 +91,6 @@ namespace TBF.Rig.Modbus.TempMeter.Meret
}
}
public void RunDeviceAfter() { }
public void StopDevice() { }
public void StopDevice2() { }

View File

@ -36,10 +36,10 @@ namespace TBF.Rig.Modbus.UltrasoundLevelMeter
/// <summary>Measurement time stamp when MsrmntState == MsrmntState.Valid</summary>
int msrmntTimeStamp;
int ticketNumber; /// 1 .. number of devices registered for regular polling
public LevelMeter()
{
}
public LevelMeter() { }
public LevelMeter(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
: base(cfg)
@ -72,6 +72,7 @@ namespace TBF.Rig.Modbus.UltrasoundLevelMeter
}
msrmntState = MsrmntState.Busy;
ticketNumber = modbus.RegisterForPolling();
log.FatalFormat("Successfully initialized device {0}", ToString());
}
@ -124,11 +125,13 @@ namespace TBF.Rig.Modbus.UltrasoundLevelMeter
Debug.WriteLine(line);
}
}
}
byte[] msg = new byte[8]; /// Buffer for data to send
if ((StateMachine.Time % 3) == 0) /// Each 3 seconds
public void RunDeviceAfter()
{
if (myCfg.DebugLevel != Config.Entities.DebugMode.Simulate &&
myCfg.DebugLevel != Config.Entities.DebugMode.FailureDuringOperation &&
modbus.IsMyTurn(ticketNumber))
{
///
/// Read distance, level, quantity, percentage and temperature in IEEE754 (DWORD-s)
@ -137,17 +140,15 @@ namespace TBF.Rig.Modbus.UltrasoundLevelMeter
UInt16 count = 5;
/// Prepare data to be sent
byte[] msg = new byte[8]; /// Buffer for data to send
msg[0] = myCfg.ModbusAddress;
msg[1] = 3; /// CMD =
msg[2] = (byte)(regAddr >> 8); /// Control Word Hi
msg[3] = (byte)(regAddr & 0xFF); /// Control Word Lo
msg[4] = (byte)(count >> 8); /// Serial Com Reference Hi
msg[5] = (byte)(count & 0xFF); /// Serial Com Reference Lo
modbus.SendMessage(msg);
}
else if ((StateMachine.Time % 3) == 1) /// Each 3 seconds
{
/////
///// Read STATUS1
/////
@ -155,17 +156,15 @@ namespace TBF.Rig.Modbus.UltrasoundLevelMeter
//UInt16 count = 1;
///// Prepare data to be sent
//byte[] msg = new byte[8]; /// Buffer for data to send
//msg[0] = myCfg.ModbusAddress;
//msg[1] = 3; /// CMD =
//msg[2] = (byte)(regAddr >> 8); /// Control Word Hi
//msg[3] = (byte)(regAddr & 0xFF); /// Control Word Lo
//msg[4] = (byte)(count >> 8); /// Serial Com Reference Hi
//msg[5] = (byte)(count & 0xFF); /// Serial Com Reference Lo
//modbus.SendMessage(msg);
}
else if ((StateMachine.Time % 3) == 2) /// Each 3 seconds
{
/////
///// Read distance, level, quantity, percentage and temperature in IEEE754 (DWORD-s)
/////
@ -173,18 +172,17 @@ namespace TBF.Rig.Modbus.UltrasoundLevelMeter
//UInt16 count = 10;
///// Prepare data to be sent
//byte[] msg = new byte[8]; /// Buffer for data to send
//msg[0] = myCfg.ModbusAddress;
//msg[1] = 3; /// CMD =
//msg[2] = (byte)(regAddr >> 8); /// Control Word Hi
//msg[3] = (byte)(regAddr & 0xFF); /// Control Word Lo
//msg[4] = (byte)(count >> 8); /// Serial Com Reference Hi
//msg[5] = (byte)(count & 0xFF); /// Serial Com Reference Lo
//modbus.SendMessage(msg);
}
}
public void RunDeviceAfter() { }
public void StopDevice() { }
public void StopDevice2() { }
}

View File

@ -33,10 +33,10 @@ namespace TBF.Rig.Modbus.WaterAnalyzer
/// <summary>Measurement time stamp when MsrmntState == MsrmntState.Valid</summary>
int msrmntTimeStamp;
int ticketNumber; /// 1 .. number of devices registered for regular polling
public Analyzer()
{
}
public Analyzer() { }
public Analyzer(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
: base(cfg)
@ -66,6 +66,7 @@ namespace TBF.Rig.Modbus.WaterAnalyzer
}
msrmntState = MsrmntState.Busy;
ticketNumber = modbus.RegisterForPolling();
log.FatalFormat("Successfully initialized device {0}", ToString());
}
@ -107,11 +108,13 @@ namespace TBF.Rig.Modbus.WaterAnalyzer
Debug.WriteLine(line);
}
}
}
byte[] msg = new byte[8]; /// Buffer for data to send
if ((StateMachine.Time % 10) == 0) /// Each 10 seconds
public void RunDeviceAfter()
{
if (myCfg.DebugLevel != Config.Entities.DebugMode.Simulate &&
myCfg.DebugLevel != Config.Entities.DebugMode.FailureDuringOperation &&
modbus.IsMyTurn(ticketNumber))
{
///
/// Send command to request 1 float value in 2 registers at addresses 0x50 and 0x51 from Modbus.WaterAnalyzer
@ -120,6 +123,7 @@ namespace TBF.Rig.Modbus.WaterAnalyzer
UInt16 count = 2;
/// Prepare data to be sent
byte[] msg = new byte[8]; /// Buffer for data to send
msg[0] = myCfg.ModbusAddress;
msg[1] = 3; /// CMD =
msg[2] = (byte)(regAddr >> 8); /// Control Word Hi
@ -131,7 +135,6 @@ namespace TBF.Rig.Modbus.WaterAnalyzer
}
}
public void RunDeviceAfter() { }
public void StopDevice() { }
public void StopDevice2() { }

View File

@ -812,9 +812,12 @@ namespace TBF.Rig
{
Thread.Sleep(100); /// Insert 1/10 sec.delay between RunOperations() and RunDeviceAfter()
foreach (var device in devices)
/// Call RunDeviceAfter() functions in reversed order
/// so that the parent compnent's RunDeviceAfter()
/// is called after RunDeviceAfter() of it's children.
for (int i = devices.Count - 1; i >= 0; i--)
{
device.RunDeviceAfter();
devices[i].RunDeviceAfter();
}
WaitNextTick();