Modbus : Multiple modules use common time scheduling (one Thread.Sleep in RunDeviceAfter), ver. 3.1.1605

This commit is contained in:
Milan Hanajik
2021-04-09 13:37:46 +02:00
parent d84588650f
commit f33bc4f167
2 changed files with 83 additions and 17 deletions
+2 -2
View File
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
// Build Number // Build Number
// Revision // Revision
// //
[assembly: AssemblyVersion("3.1.1604.0")] [assembly: AssemblyVersion("3.1.1605.0")]
[assembly: AssemblyFileVersion("3.1.1604.0")] [assembly: AssemblyFileVersion("3.1.1605.0")]
+81 -15
View File
@@ -22,10 +22,20 @@ namespace TBF.Rig.Modbus.Common
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); } public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
const int MaxTelegramsPerSecond = 5; /// Max. number of telegrams to be sent per second (100 ms for each telegram) const int MaxTelegramsPerSecond = 5; /// Max. number of telegrams to be sent per second (100 ms for each telegram)
const int RegTelegramsPerSecond = 3; /// Number of registered polling telegrams per second const int RegTelegramsPerSecond = 2; /// Number of registered polling telegrams per second
const int MinTelegramLen = 4; const int MinTelegramLen = 4;
/// <summary>
/// Enumeration of modbus components via static fields and methods
/// </summary>
static int nextIdx = 0;
static int modbusComponentsCount { get { return nextIdx; } }
static Modbus[] modbusComponents;
///
int modbusComponentIx; /// 0-based diverter number assigned in Initialize()
private readonly ModbusCfg modbusCfg; private readonly ModbusCfg modbusCfg;
/// Serial port and received data buffers /// Serial port and received data buffers
@@ -56,23 +66,32 @@ namespace TBF.Rig.Modbus.Common
: base(cfg) : base(cfg)
{ {
modbusCfg = cfg as ModbusCfg; modbusCfg = cfg as ModbusCfg;
log.Warn(this.ToString());
} }
public override void Initialize() public override void Initialize()
{ {
telegramsToSend = new Queue<byte[]>(); modbusComponentIx = nextIdx++;
///
if (modbusComponents == null || modbusComponents.Length < nextIdx)
{
Modbus[] componentsSoFar = modbusComponents;
modbusComponents = new Modbus[modbusComponentsCount];
if (componentsSoFar != null)
{
for (int i = 0; i < componentsSoFar.Length; i++) modbusComponents[i] = componentsSoFar[i];
}
modbusComponents[modbusComponentsCount - 1] = this;
}
telegramsToSend = new Queue<byte[]>();
receivedTelegrams = new Queue<byte[]>[256]; receivedTelegrams = new Queue<byte[]>[256];
for (int i = 0; i < receivedTelegrams.Length; i++) for (int i = 0; i < receivedTelegrams.Length; i++)
{ {
receivedTelegrams[i] = new Queue<byte[]>(); receivedTelegrams[i] = new Queue<byte[]>();
} }
buffer = new byte[BUFFER_SIZE]; buffer = new byte[BUFFER_SIZE];
rcvdData = new byte[BUFFER_SIZE]; rcvdData = new byte[BUFFER_SIZE];
rcvdBytesCount = 0; rcvdBytesCount = 0;
registeredDevicesCount = 0; registeredDevicesCount = 0;
firstScheduledTicketNo = 0; firstScheduledTicketNo = 0;
@@ -86,12 +105,12 @@ namespace TBF.Rig.Modbus.Common
serialPort = new SerialPort(comPortName, modbusCfg.BaudRate, modbusCfg.Parity, modbusCfg.DataBits, modbusCfg.StopBits); serialPort = new SerialPort(comPortName, modbusCfg.BaudRate, modbusCfg.Parity, modbusCfg.DataBits, modbusCfg.StopBits);
serialPort.Handshake = modbusCfg.Handshake; serialPort.Handshake = modbusCfg.Handshake;
serialPort.Open(); serialPort.Open();
log.FatalFormat("{0} - Device successfully initialized", Name); log.FatalFormat("{0} initialized: {1}", Name, this);
} }
else else
{ {
serialPort = null; serialPort = null;
log.FatalFormat("{0} - Device simulated", Name); log.FatalFormat("{0} simulated: {1}", Name, this);
} }
} }
@@ -256,25 +275,72 @@ namespace TBF.Rig.Modbus.Common
rcvdBytesCount -= lastValidOffset; rcvdBytesCount -= lastValidOffset;
} }
/// <summary>Run this device</summary> /// <summary>Run this device</summary>
public void RunDeviceAfter() public void RunDeviceAfter()
{ {
int telegramsToSendNow = Math.Min(MaxTelegramsPerSecond, telegramsToSend.Count); telegramsToSendInThisTick = Math.Min(MaxTelegramsPerSecond, telegramsToSend.Count);
for (int i = 0; i < telegramsToSendNow; i++, Thread.Sleep(100)) if (modbusComponentIx == 0)
{ {
WriteMessageToSerialPort(telegramsToSend.Dequeue()); int maxTelegramsToSendInThisTick = telegramsToSendInThisTick;
for (int i = 1; i < modbusComponentsCount; i++)
{
if (modbusComponents[i].telegramsToSendInThisTick > maxTelegramsToSendInThisTick)
{
maxTelegramsToSendInThisTick = modbusComponents[i].telegramsToSendInThisTick;
}
}
for (int t = 0; t < maxTelegramsToSendInThisTick; t++, Thread.Sleep(100))
{
for (int i = 0; i < modbusComponentsCount; i++)
{
if (t < modbusComponents[i].telegramsToSendInThisTick)
{
modbusComponents[i].WriteOneMessageToSerialPort();
}
}
}
} }
} }
///
int telegramsToSendInThisTick;
///
void WriteOneMessageToSerialPort()
{
WriteMessageToSerialPort(telegramsToSend.Dequeue());
}
/// <summary>Stop this device</summary> /// <summary>Stop this device</summary>
public void StopDevice() public void StopDevice()
{ {
/// Send telegrams currently in the queue telegramsToSendInThisTick = telegramsToSend.Count;
while (telegramsToSend.Count > 0)
/// Send all telegrams currently in all queues
if (modbusComponentIx == 0)
{ {
int maxTelegramsToSendInThisTick = telegramsToSendInThisTick;
for (int i = 1; i < modbusComponentsCount; i++)
{
if (modbusComponents[i].telegramsToSendInThisTick > maxTelegramsToSendInThisTick)
{
maxTelegramsToSendInThisTick = modbusComponents[i].telegramsToSendInThisTick;
}
}
Thread.Sleep(100); Thread.Sleep(100);
WriteMessageToSerialPort(telegramsToSend.Dequeue()); for (int t = 0; t < maxTelegramsToSendInThisTick; t++, Thread.Sleep(100))
{
for (int i = 0; i < modbusComponentsCount; i++)
{
if (t < modbusComponents[i].telegramsToSendInThisTick)
{
modbusComponents[i].WriteOneMessageToSerialPort();
}
}
}
} }
if (serialPort != null && serialPort.IsOpen) serialPort.Close(); if (serialPort != null && serialPort.IsOpen) serialPort.Close();