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:05:06 +02:00
parent d84588650f
commit f33bc4f167
2 changed files with 83 additions and 17 deletions

View File

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

View File

@ -22,10 +22,20 @@ namespace TBF.Rig.Modbus.Common
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 RegTelegramsPerSecond = 3; /// Number of registered polling telegrams per second
const int RegTelegramsPerSecond = 2; /// Number of registered polling telegrams per second
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;
/// Serial port and received data buffers
@ -56,23 +66,32 @@ namespace TBF.Rig.Modbus.Common
: base(cfg)
{
modbusCfg = cfg as ModbusCfg;
log.Warn(this.ToString());
}
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];
for (int i = 0; i < receivedTelegrams.Length; i++)
{
receivedTelegrams[i] = new Queue<byte[]>();
}
buffer = new byte[BUFFER_SIZE];
rcvdData = new byte[BUFFER_SIZE];
rcvdBytesCount = 0;
registeredDevicesCount = 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.Handshake = modbusCfg.Handshake;
serialPort.Open();
log.FatalFormat("{0} - Device successfully initialized", Name);
log.FatalFormat("{0} initialized: {1}", Name, this);
}
else
{
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;
}
/// <summary>Run this device</summary>
public void RunDeviceAfter()
{
int telegramsToSendNow = Math.Min(MaxTelegramsPerSecond, telegramsToSend.Count);
for (int i = 0; i < telegramsToSendNow; i++, Thread.Sleep(100))
telegramsToSendInThisTick = Math.Min(MaxTelegramsPerSecond, telegramsToSend.Count);
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>
public void StopDevice()
{
/// Send telegrams currently in the queue
while (telegramsToSend.Count > 0)
telegramsToSendInThisTick = telegramsToSend.Count;
/// 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);
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();