I have a project where i am trying to connect multiple clients to one Modbus TCP server. However the current library does not support one server having multiple clients, So i tried to set multiple server up one for every clients. This seems to work well. It is not the cleanest code because i have to edit the registers of both servers when the data changes.
Is there a way to connect multiple client to one server?
I am using an STM32F303 on a NUCLEO-BOARD to test.
#include <SPI.h>
#include <Ethernet.h>
#include <ArduinoModbus.h>
#include <Adafruit_MAX31865.h>
// Use software SPI: CS, DI, DO, CLK
Adafruit_MAX31865 thermo = Adafruit_MAX31865(6, A0, A1, A3);
// The value of the Rref resistor. Use 430.0 for PT100 and 4300.0 for PT1000
#define RREF 400.0
// The 'nominal' 0-degrees-C resistance of the sensor
// 100.0 for PT100, 1000.0 for PT1000
#define RNOMINAL 100.0
byte mac[] = {
0x80, 0x20, 0xE1, 0xEF, 0xFE, 0xED};
// Default to use W5100. Must change to false for W5500, W5100S, for faster SPI clock
#define USE_W5100 false
/**
* @brief The pins used for the pulse interrupts.
*/
const int interruptPin1 = 0;
const int interruptPin2 = 1;
const int interruptPin3 = 9;
const int interruptPin4 = 4;
const int interruptPin5 = 5;
const int interruptPin6 = A2;
const int interruptPin7 = 7;
const int interruptPin8 = 8;
uint16_t interruptNumber = 0;
unsigned long previousTime = micros();
uint16_t interruptNumber1 = 0;
uint16_t interruptNumber2 = 0;
uint16_t interruptNumber3 = 0;
uint16_t interruptNumber4 = 0;
uint16_t interruptNumber5 = 0;
uint16_t interruptNumber6 = 0;
uint16_t interruptNumber7 = 0;
uint16_t interruptNumber8 = 0;
unsigned long previousTime1 = 0;
unsigned long previousTime2 = 0;
unsigned long previousTime3 = 0;
unsigned long previousTime4 = 0;
unsigned long previousTime5 = 0;
unsigned long previousTime6 = 0;
unsigned long previousTime7 = 0;
unsigned long previousTime8 = 0;
EthernetServer ethServer(502);
ModbusTCPServer modbusTCPServer;
ModbusTCPServer modbusTCPServer1;
EthernetClient client1;
bool client1_connected = false;
EthernetClient client2;
bool client2_connected = false;
/**
* @brief The maximum number of Modbus TCP clients.
*/
#define MAX_MB_CLIENTS 2
/**
* @brief This structure represents a Modbus client.
*/
struct DbmaticClient
{
EthernetClient client = NULL;
/**
* @brief The modbus TCP server instance for this client.
*/
ModbusTCPServer mbServer;
/**
* @brief True when the client is connected, false if not.
*/
bool connected = false;
int slaveId = 0;
};
void setup()
{
Serial.begin(115200);
Ethernet.init(10);
Serial.println("Initialize Ethernet with DHCP:");
if (Ethernet.begin(mac) == 0)
{
Serial.println("Failed to configure Ethernet using DHCP");
bool isW5500 = (Ethernet.hardwareStatus() == EthernetW5500);
Serial.print(F("Ethernet type is "));
Serial.println(isW5500 ? F("W5500") : F("W5100"));
if (Ethernet.hardwareStatus() == EthernetNoHardware)
{
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
}
else if (Ethernet.linkStatus() == LinkOFF)
{
Serial.println("Ethernet cable is not connected.");
}
}
Serial.print("My IP address: ");
Serial.println(Ethernet.localIP());
ethServer.begin();
pinMode(interruptPin1, INPUT_PULLUP);
pinMode(interruptPin2, INPUT_PULLUP);
pinMode(interruptPin3, INPUT_PULLUP);
pinMode(interruptPin4, INPUT_PULLUP);
pinMode(interruptPin5, INPUT_PULLUP);
pinMode(A2, INPUT_PULLUP);
pinMode(interruptPin7, INPUT_PULLUP);
pinMode(interruptPin8, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin1), interrupt1Callback, FALLING);
attachInterrupt(digitalPinToInterrupt(interruptPin2), interrupt2Callback, FALLING);
attachInterrupt(digitalPinToInterrupt(interruptPin3), interrupt3Callback, FALLING);
attachInterrupt(digitalPinToInterrupt(interruptPin4), interrupt4Callback, FALLING);
attachInterrupt(digitalPinToInterrupt(interruptPin5), interrupt5Callback, FALLING);
attachInterrupt(digitalPinToInterrupt(A2), interrupt6Callback, FALLING);
attachInterrupt(digitalPinToInterrupt(interruptPin7), interrupt7Callback, FALLING);
attachInterrupt(digitalPinToInterrupt(interruptPin8), interrupt8Callback, FALLING);
// start the Modbus TCP server
if (!modbusTCPServer.begin(1))
{
Serial.println("Failed to start Modbus TCP Server!");
while (1)
;
}
modbusTCPServer.configureHoldingRegisters(0x00, 100);
Serial.println("Start Modbus TCP Server!");
delay(1000);
if (!modbusTCPServer1.begin(2))
{
Serial.println("Failed to start Modbus TCP Server!");
while (1)
;
}
modbusTCPServer1.configureHoldingRegisters(0x00, 100);
Serial.println("Start Modbus TCP Server 1!");
// for(int i = 0; i < MAX_MB_CLIENTS; ++i) {
// setupDbmaticClient(mbClient + i, i);
// }
thermo.begin(MAX31865_2WIRE);
Serial.println("Boot complete");
}
void handle_connect()
{
EthernetClient client = ethServer.accept();
if(client) {
if(!client1_connected) {
Serial.println("Connecting client 1");
client1 = client;
client1_connected = true;
Serial.print("the connected client1 state: ");
Serial.println(client1.connected());
modbusTCPServer.accept(client1);
Serial.println(client1.connected());
return;
} else if (!client2_connected) {
Serial.println("Connecting client 2");
client2 = client;
client2_connected = true;
Serial.print("the connected client2 state: ");
Serial.println(client2.connected());
modbusTCPServer1.accept(client2);
Serial.println(client2.connected());
return;
}
client.stop();
Serial.println("Closed new client because al connection slots are in use");
}
}
void handle_modbus()
{
if(client1.connected()){
modbusTCPServer.poll();
}
if(client2.connected()){
Serial.println("Polling for client 2");
modbusTCPServer1.poll();
}
if(!client1.connected() && client1_connected){
client1_connected = false;
Serial.println("Client 1 closing the connection");
client1.stop();
}
if(!client2.connected() && client2_connected){
client2_connected = false;
Serial.println("Client 2 closing the connection");
client2.stop();
}
}
unsigned long last_temp_reading = 0;
void handle_temp()
{
if (millis() - last_temp_reading <= 1000)
{
return;
}
uint16_t rtd = thermo.readRTD();
float ratio = rtd;
ratio /= 32768;
// Serial.print("Temperature = ");
// Serial.println(thermo.temperature(RNOMINAL, RREF));
// Check and print any faults
uint8_t fault = thermo.readFault();
if (fault)
{
Serial.print("Fault 0x");
Serial.println(fault, HEX);
if (fault & MAX31865_FAULT_HIGHTHRESH)
{
Serial.println("RTD High Threshold");
}
if (fault & MAX31865_FAULT_LOWTHRESH)
{
Serial.println("RTD Low Threshold");
}
if (fault & MAX31865_FAULT_REFINLOW)
{
Serial.println("REFIN- > 0.85 x Bias");
}
if (fault & MAX31865_FAULT_REFINHIGH)
{
Serial.println("REFIN- < 0.85 x Bias - FORCE- open");
}
if (fault & MAX31865_FAULT_RTDINLOW)
{
Serial.println("RTDIN- < 0.85 x Bias - FORCE- open");
}
if (fault & MAX31865_FAULT_OVUV)
{
Serial.println("Under/Over voltage");
}
thermo.clearFault();
}
last_temp_reading = millis();
}
void loop()
{
handle_connect();
handle_modbus();
handle_temp();
}
void interrupt1Callback()
{
interruptNumber1++;
modbusTCPServer.holdingRegisterWrite(0x00, interruptNumber1);
unsigned long currentTime = micros();
int pulseTime = int((currentTime - previousTime1) / 10);
previousTime1 = currentTime;
modbusTCPServer.holdingRegisterWrite(0x20, int(pulseTime / 100));
modbusTCPServer.holdingRegisterWrite(0x21, pulseTime & 0xFFFF);
modbusTCPServer1.holdingRegisterWrite(0x20, int(pulseTime / 100));
modbusTCPServer1.holdingRegisterWrite(0x21, pulseTime & 0xFFFF);
}
void interrupt2Callback()
{
interruptNumber2++;
modbusTCPServer.holdingRegisterWrite(0x01, interruptNumber2);
unsigned long currentTime = micros();
int pulseTime = int((currentTime - previousTime2) / 10);
previousTime2 = currentTime;
modbusTCPServer.holdingRegisterWrite(0x22, int(pulseTime / 100));
modbusTCPServer.holdingRegisterWrite(0x23, pulseTime & 0xFFFF);
modbusTCPServer1.holdingRegisterWrite(0x22, int(pulseTime / 100));
modbusTCPServer1.holdingRegisterWrite(0x23, pulseTime & 0xFFFF);
}
void interrupt3Callback()
{
interruptNumber3++;
modbusTCPServer.holdingRegisterWrite(0x02, interruptNumber3);
unsigned long currentTime = micros();
int pulseTime = int((currentTime - previousTime3) / 10);
previousTime3 = currentTime;
modbusTCPServer.holdingRegisterWrite(0x24, int(pulseTime / 100));
modbusTCPServer.holdingRegisterWrite(0x25, pulseTime & 0xFFFF);
modbusTCPServer1.holdingRegisterWrite(0x24, int(pulseTime / 100));
modbusTCPServer1.holdingRegisterWrite(0x25, pulseTime & 0xFFFF);
}
void interrupt4Callback()
{
interruptNumber4++;
modbusTCPServer.holdingRegisterWrite(0x03, interruptNumber4);
unsigned long currentTime = micros();
int pulseTime = int((currentTime - previousTime4) / 10);
previousTime4 = currentTime;
modbusTCPServer.holdingRegisterWrite(0x26, int(pulseTime / 100));
modbusTCPServer.holdingRegisterWrite(0x27, pulseTime & 0xFFFF);
modbusTCPServer1.holdingRegisterWrite(0x26, int(pulseTime / 100));
modbusTCPServer1.holdingRegisterWrite(0x27, pulseTime & 0xFFFF);
}
void interrupt5Callback()
{
interruptNumber5++;
modbusTCPServer.holdingRegisterWrite(0x04, interruptNumber5);
unsigned long currentTime = micros();
int pulseTime = int((currentTime - previousTime5) / 10);
previousTime5 = currentTime;
modbusTCPServer.holdingRegisterWrite(0x28, int(pulseTime / 100));
modbusTCPServer.holdingRegisterWrite(0x29, pulseTime & 0xFFFF);
modbusTCPServer1.holdingRegisterWrite(0x28, int(pulseTime / 100));
modbusTCPServer1.holdingRegisterWrite(0x29, pulseTime & 0xFFFF);
}
void interrupt6Callback()
{
interruptNumber6++;
modbusTCPServer.holdingRegisterWrite(0x05, interruptNumber6);
unsigned long currentTime = micros();
int pulseTime = int((currentTime - previousTime6) / 10);
previousTime6 = currentTime;
modbusTCPServer.holdingRegisterWrite(0x2A, int(pulseTime / 100));
modbusTCPServer.holdingRegisterWrite(0x2B, pulseTime & 0xFFFF);
modbusTCPServer1.holdingRegisterWrite(0x2A, int(pulseTime / 100));
modbusTCPServer1.holdingRegisterWrite(0x2B, pulseTime & 0xFFFF);
}
void interrupt7Callback()
{
interruptNumber7++;
modbusTCPServer.holdingRegisterWrite(0x06, interruptNumber7);
unsigned long currentTime = micros();
int pulseTime = int((currentTime - previousTime7) / 10);
previousTime7 = currentTime;
modbusTCPServer.holdingRegisterWrite(0x2C, int(pulseTime / 100));
modbusTCPServer.holdingRegisterWrite(0x2D, pulseTime & 0xFFFF);
modbusTCPServer1.holdingRegisterWrite(0x2C, int(pulseTime / 100));
modbusTCPServer1.holdingRegisterWrite(0x2D, pulseTime & 0xFFFF);
}
void interrupt8Callback()
{
interruptNumber8++;
modbusTCPServer.holdingRegisterWrite(0x07, interruptNumber8);
unsigned long currentTime = micros();
int pulseTime = int((currentTime - previousTime8) / 10);
previousTime8 = currentTime;
modbusTCPServer.holdingRegisterWrite(0x2E, int(pulseTime / 100));
modbusTCPServer.holdingRegisterWrite(0x2F, pulseTime & 0xFFFF);
}
I have a project where i am trying to connect multiple clients to one Modbus TCP server. However the current library does not support one server having multiple clients, So i tried to set multiple server up one for every clients. This seems to work well. It is not the cleanest code because i have to edit the registers of both servers when the data changes.
Is there a way to connect multiple client to one server?
I am using an STM32F303 on a NUCLEO-BOARD to test.