diff --git a/Common/Telegram.cs b/Common/Telegram.cs
index 65bfccde6..d56cfe022 100644
--- a/Common/Telegram.cs
+++ b/Common/Telegram.cs
@@ -47,6 +47,21 @@ namespace Common
return crc;
}
+ ///
+ /// 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.
+ ///
+ /// Data telegram
+ /// Calculated CRC
+ 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;
+ }
+
///
/// 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));
}
+ ///
+ /// 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.
+ ///
+ /// Data telegram
+ /// true if the CRC in the telegram is correct
+ 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));
+ }
+
///
diff --git a/TBF/Properties/AssemblyInfo.cs b/TBF/Properties/AssemblyInfo.cs
index 83d50c13a..670963617 100644
--- a/TBF/Properties/AssemblyInfo.cs
+++ b/TBF/Properties/AssemblyInfo.cs
@@ -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")]
diff --git a/TBF/Rig/ControlBoard/Uni/UniCB.cs b/TBF/Rig/ControlBoard/Uni/UniCB.cs
index 2162fd08b..808a1472f 100644
--- a/TBF/Rig/ControlBoard/Uni/UniCB.cs
+++ b/TBF/Rig/ControlBoard/Uni/UniCB.cs
@@ -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);
}
diff --git a/TBF/Rig/GenericDevices/IModbus.cs b/TBF/Rig/GenericDevices/IModbus.cs
index e58a48300..52a91f3c5 100644
--- a/TBF/Rig/GenericDevices/IModbus.cs
+++ b/TBF/Rig/GenericDevices/IModbus.cs
@@ -27,5 +27,18 @@ namespace TBF.Rig.GenericDevices
void SendMessage(byte modbusAddress, byte function, ushort dataAddress, ushort dataCount);
Queue[] ReceivedTelegrams { get; }
+
+ ///
+ /// Registers a modbus device for scheduled polling
+ ///
+ /// Ticket numeber to be used as IsMyTurn() argumenr
+ int RegisterForPolling();
+
+ ///
+ /// Determines whether the registered device should do polling now
+ ///
+ /// Ticket number in range 1 .. registered devs.count returned by RegisterForPolling()
+ /// true when yes
+ bool IsMyTurn(int ticketNr);
}
}
diff --git a/TBF/Rig/Modbus/Ambient/Comet/Ambient.cs b/TBF/Rig/Modbus/Ambient/Comet/Ambient.cs
index 743627134..62e12d045 100644
--- a/TBF/Rig/Modbus/Ambient/Comet/Ambient.cs
+++ b/TBF/Rig/Modbus/Ambient/Comet/Ambient.cs
@@ -74,9 +74,10 @@ namespace TBF.Rig.Modbus.Ambient.Comet
/// Measurement time stamp when MsrmntState == MsrmntState.Valid
int msrmntTimeStamp;
- public Ambient()
- {
- }
+ int ticketNumber; /// 1 .. number of devices registered for regular polling
+
+
+ public Ambient() { }
///
/// 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() { }
diff --git a/TBF/Rig/Modbus/Common/Modbus.cs b/TBF/Rig/Modbus/Common/Modbus.cs
index 9b555ba5a..a54b06d8d 100644
--- a/TBF/Rig/Modbus/Common/Modbus.cs
+++ b/TBF/Rig/Modbus/Common/Modbus.cs
@@ -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 telegramsToSend;
- public Modbus()
- {
- }
+ int registeredDevicesCount; /// Number of devices registered for poling
+
+
+ public Modbus() { }
///
/// 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[256];
- for (int i = 0; i < receivedTelegrams.Length; i++)
- {
- receivedTelegrams[i] = new Queue();
- }
- telegramsToSend = new Queue();
-
- 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[256];
+ for (int i = 0; i < receivedTelegrams.Length; i++)
+ {
+ receivedTelegrams[i] = new Queue();
+ }
+ telegramsToSend = new Queue();
+
+ 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
}
+ ///
+ /// Registers a modbus device for scheduled polling
+ ///
+ /// Ticket numeber to be used as IsMyTurn() argumenr
+ public int RegisterForPolling()
+ {
+ registeredDevicesCount++;
+ return registeredDevicesCount; /// 1 .. number of registered devices
+ }
+
+ ///
+ /// Determines whether the registered device should do polling now
+ ///
+ /// Ticket number in range 1 .. registered devs.count returned by RegisterForPolling()
+ /// true when yes
+ public bool IsMyTurn(int ticketNr)
+ {
+ return (StateMachine.Time % registeredDevicesCount == ticketNr - 1);
+ }
+
+
///
/// 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
/// Run this device
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(candidateLen).ToArray();
- dataToProcess = dataToProcess.Skip(candidateLen).ToArray();
+ /// 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(candidateLen).ToArray();
- dataToProcess = dataToProcess.Skip(candidateLen).ToArray();
+ /// 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;
+ }
/// Run this device
public void RunDeviceAfter()
diff --git a/TBF/Rig/Modbus/Easytherm/Easytherm.cs b/TBF/Rig/Modbus/Easytherm/Easytherm.cs
index f9962f5f7..2864680ca 100644
--- a/TBF/Rig/Modbus/Easytherm/Easytherm.cs
+++ b/TBF/Rig/Modbus/Easytherm/Easytherm.cs
@@ -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 components)
: base(cfg)
@@ -47,6 +48,7 @@ namespace TBF.Rig.Modbus.Easytherm
temperatureSetPointValid = false;
temperatureSetPointRequested = false;
actualTemperatureIsValid = false;
+ ticketNumber = modbus.RegisterForPolling();
}
/// Run this device
@@ -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() { }
diff --git a/TBF/Rig/Modbus/Enums.cs b/TBF/Rig/Modbus/Enums.cs
index f94f9be86..fa1f1e7d8 100644
--- a/TBF/Rig/Modbus/Enums.cs
+++ b/TBF/Rig/Modbus/Enums.cs
@@ -20,6 +20,6 @@ namespace TBF.Rig.Modbus
public static class Constants
{
- public const int ModbusPollPeriod = 4;
+ public const int ModbusPollPeriod = 5;
}
}
diff --git a/TBF/Rig/Modbus/PressureMeter/Meret/PressureMeter.cs b/TBF/Rig/Modbus/PressureMeter/Meret/PressureMeter.cs
index 08842138f..0e4c2b4c8 100644
--- a/TBF/Rig/Modbus/PressureMeter/Meret/PressureMeter.cs
+++ b/TBF/Rig/Modbus/PressureMeter/Meret/PressureMeter.cs
@@ -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() { }
diff --git a/TBF/Rig/Modbus/TempMeter/Groch/TempMeter.cs b/TBF/Rig/Modbus/TempMeter/Groch/TempMeter.cs
index 974a575e8..d8d5688cd 100644
--- a/TBF/Rig/Modbus/TempMeter/Groch/TempMeter.cs
+++ b/TBF/Rig/Modbus/TempMeter/Groch/TempMeter.cs
@@ -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 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 });
}
diff --git a/TBF/Rig/Modbus/TempMeter/Meret/TempMeter.cs b/TBF/Rig/Modbus/TempMeter/Meret/TempMeter.cs
index 7907190b2..22b9934da 100644
--- a/TBF/Rig/Modbus/TempMeter/Meret/TempMeter.cs
+++ b/TBF/Rig/Modbus/TempMeter/Meret/TempMeter.cs
@@ -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();
+ }
/// Run this device
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() { }
diff --git a/TBF/Rig/Modbus/UltrasoundLevelMeter/LevelMeter.cs b/TBF/Rig/Modbus/UltrasoundLevelMeter/LevelMeter.cs
index 680fc44b4..49470ccf1 100644
--- a/TBF/Rig/Modbus/UltrasoundLevelMeter/LevelMeter.cs
+++ b/TBF/Rig/Modbus/UltrasoundLevelMeter/LevelMeter.cs
@@ -36,10 +36,10 @@ namespace TBF.Rig.Modbus.UltrasoundLevelMeter
/// Measurement time stamp when MsrmntState == MsrmntState.Valid
int msrmntTimeStamp;
+ int ticketNumber; /// 1 .. number of devices registered for regular polling
- public LevelMeter()
- {
- }
+
+ public LevelMeter() { }
public LevelMeter(Generic.IComponentCfg cfg, IList 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() { }
}
diff --git a/TBF/Rig/Modbus/WaterAnalyzer/Analyzer.cs b/TBF/Rig/Modbus/WaterAnalyzer/Analyzer.cs
index ab4756316..598954cbf 100644
--- a/TBF/Rig/Modbus/WaterAnalyzer/Analyzer.cs
+++ b/TBF/Rig/Modbus/WaterAnalyzer/Analyzer.cs
@@ -33,10 +33,10 @@ namespace TBF.Rig.Modbus.WaterAnalyzer
/// Measurement time stamp when MsrmntState == MsrmntState.Valid
int msrmntTimeStamp;
+ int ticketNumber; /// 1 .. number of devices registered for regular polling
- public Analyzer()
- {
- }
+
+ public Analyzer() { }
public Analyzer(Generic.IComponentCfg cfg, IList 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() { }
diff --git a/TBF/Rig/StateMachine.cs b/TBF/Rig/StateMachine.cs
index 530bc20ee..9f8eb7369 100644
--- a/TBF/Rig/StateMachine.cs
+++ b/TBF/Rig/StateMachine.cs
@@ -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();