In recent months I have spent a lot of time testing the various Modbus TCP Server libraries available for Arduino for a HIL project on which I am working.

After numerous tests with the various libraries available, this is the conclusion I came to:

  Uno Vs   Mega 2560

prefer Arduino Mega 2560 to the Uno board!

 

 

read this article to understand why

These were the requirements I needed:

  1. at least 100 holding registers available
  2. at least 100 input registers available
  3. FC3 supported (read holding registers)
  4. FC6 supported (write single register )
  5. FC16 supported (write multiple register write)

With reference to previous needs, Arduino MEga 2560 is able to fully satisfied, Arduino Uno not at all!

Based on official Arduino Modbus Library, this is the source code I uploaded on both boards ( first on Arduino Uno assigning it the IP addr=192.168.1.22, then to the Arduino Mega assigning it the IP addr=192.168.1.23):

#include <Ethernet.h>
#include <ArduinoModbus.h>

bool _1s;
unsigned long TimeAct, TimePrev, HodingResult, InputResult, HeartBeat, i, StartingAddr;
long Cmd;

EthernetServer EthServer(502);
ModbusTCPServer modbusTCPServer;

void setup() {
  // Ethernet Settings
  byte mac[] = { 0x4E, 0xA0, 0xBE, 0x3F, 0xFE, 0x0F };  // Define MAc address
  byte ip[] = { 192, 168, 1, 22 };                      // Define IP address
  byte subnet[] = { 255, 255, 255, 0 };                 // Define SubNEt mask

  // initialize the ethernet device
  Ethernet.begin(mac, ip, subnet);                      // Assign MAC, IP, and subnet mask
  Serial.begin(9600);
  EthServer.begin();          // start listening for clients
  modbusTCPServer.begin();    // start listening for clients

  // Define Holding register:
  HodingResult = modbusTCPServer.configureHoldingRegisters(0, 100);
  InputResult = modbusTCPServer.configureInputRegisters(0, 100);

  Serial.print("Holding Reg init result =");
  Serial.print(HoldingResult);
  Serial.print("\n");

  Serial.print("Input Reg init result =");
  Serial.print(InputResult);
  Serial.print("\n");

  Serial.print("Modbus server address=");
  Serial.println(Ethernet.localIP());
  Serial.print("\n");
}

void loop() {
  // Modbus server accept incoming connections
  EthernetClient client = EthServer.available();

  if (client.connected()) {
    modbusTCPServer.accept(client);
    // poll for Modbus TCP requests, while client connected
    modbusTCPServer.poll();
    // Serial.print("poll");
  }

  //---------------------------------------------------------------------------------
  // TIME  clock 1s
  TimeAct = millis();     // Millis value between  0 and  655535

  _1s = false;
  if (  ( (TimeAct > TimePrev) and (TimeAct - TimePrev) > 1000) or ((TimeAct < TimePrev) and (65535 - TimePrev + TimeAct) > 1000 )  ) {
    _1s = true;
    TimePrev = TimeAct;
  }
  //---------------------------------------------------------------------------------
  // HeartBeat
  if (_1s) {
    HeartBeat++;
    if (HeartBeat > 255) {
      HeartBeat = 0;
    }
    Serial.print("HeartBeat=");
    Serial.println(HeartBeat);
    Serial.print("\n");
  }
  //---------------------------------------------------------------------------------
  // Modbus server  :

  // holding register 40001: heartbeat (FC3)
  modbusTCPServer.holdingRegisterWrite(0x00, HeartBeat);

  // holding register 40500: Command Word (FC6)
  Cmd = modbusTCPServer.holdingRegisterRead(90);


  if (_1s) {
    Serial.print("cmd");  // printout the Received holding register 90
    Serial.print(Cmd);
    Serial.print("\n");
  }
}

As you can see, Arduino Uno, running as Modbus TCP server has following limits

  1. not able to properly initialize the input registers (Input Reg init result = printout is zero on serial Monitor)
  2. manage up to 50 holding registers (ONLY)  (beyond this value you will notice that the memory areas looks like "dirty".. probley used by the CPU as flag or somethings else..)

This is the video about the Uno:

 and this is the one about Mega 2560: