Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple clients to one modbus TCP server #113

Open
DriesVandb opened this issue Apr 6, 2023 · 0 comments
Open

Multiple clients to one modbus TCP server #113

DriesVandb opened this issue Apr 6, 2023 · 0 comments

Comments

@DriesVandb
Copy link

DriesVandb commented Apr 6, 2023

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);
}

@DriesVandb DriesVandb changed the title Multiple clients to one modbus TCP server on stm32 Multiple clients to one modbus TCP server Apr 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant