Arduino Modbus TCP Slave (server): IDE example

into IDE example, I find Arduino as Modbus Slave TCP for WIFI only.
Do someone have a sample of the code (declaration,...) to use the library with RJ45 (Ethernet shield W5100)?
thanks

You failed to provide a link to the library you're using, so we're not able to help you.

this

That's a simple combination of a Ethernet server sketch with the WiFiModbusServerLED sketch example of the linked library (not tested):

#include <SPI.h>
#include <Ethernet.h>
#include <ArduinoRS485.h> // ArduinoModbus depends on the ArduinoRS485 library
#include <ArduinoModbus.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network.
// gateway and subnet are optional:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 177);
IPAddress myDns(192, 168, 1, 1);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 0, 0);


EthernetServer server(502);
ModbusTCPServer modbusTCPServer;

void setup() {
  // You can use Ethernet.init(pin) to configure the CS pin
  //Ethernet.init(10);  // Most Arduino shields
  //Ethernet.init(5);   // MKR ETH shield
  //Ethernet.init(0);   // Teensy 2.0
  //Ethernet.init(20);  // Teensy++ 2.0
  //Ethernet.init(15);  // ESP8266 with Adafruit Featherwing Ethernet
  //Ethernet.init(33);  // ESP32 with Adafruit Featherwing Ethernet

  // initialize the ethernet device
  Ethernet.begin(mac, ip, myDns, gateway, subnet);

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) {
      delay(1); // do nothing, no point running without Ethernet hardware
    }
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }

  // start listening for clients
  server.begin();

  Serial.print("Modbus server address:");
  Serial.println(Ethernet.localIP());
  // start the Modbus TCP server
  if (!modbusTCPServer.begin()) {
    Serial.println("Failed to start Modbus TCP Server!");
    while (1);
  }

  // configure the LED
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);

  // configure a single coil at address 0x00
  modbusTCPServer.configureCoils(0x00, 1);
}

void loop() {
  // wait for a new client:
  EthernetClient client = server.available();

  // when the client sends the first byte, say hello:
  if (client) {
    // a new client connected
    Serial.println("new client");

    // let the Modbus TCP accept the connection 
    modbusTCPServer.accept(client);

    while (client.connected()) {
      // poll for Modbus TCP requests, while client connected
      modbusTCPServer.poll();

      // update the LED
      updateLED();
    }

    Serial.println("client disconnected");
  }
}

void updateLED() {
  // read the current value of the coil
  int coilValue = modbusTCPServer.coilRead(0x00);

  if (coilValue) {
    // coil value set, turn LED on
    digitalWrite(ledPin, HIGH);
  } else {
    // coild value clear, turn LED off
    digitalWrite(ledPin, LOW);
  }
}

Hi Pylon, by usig your code try compiling I get:

"'ModbusTCPServer' does not name a type "

Why?

I edited my post and inserted the forgotten includes.

Hi Pylon, I run your code but it's not working..
Using a Modbus Client (Modbus Poll) and analyzing with Wireshark, Arduino answers to Modbus query only with a TCP message..not Modbus structure into the TCP frame. Does it work on you? I'm using Arduino uno + W5100 Eth shield . I test also with mega 2560+Eth Shiled; same story

Does it work on you?

No, I wrote it's a quick hack, I don't have the equivalent hardware at hand.

I forgot the server configuration, I edited my code again to include that. Please notice the server will have only one single coil register available so you cannot request any information. If you want to send different requests you have to adapt the code accordingly.

I tried your code but no way..it doesn't work

I tried your code but no way..it doesn't work

Define "it doesn't work" in more detail. Did you adapt the code to your needs? Did you understand the last sentence of my previous post?

yes I did.
1-I copyand paste your code
2-try to adapt to my needs (holding register).

Both case not working (timeout answer in modbus call) (teh same of Wireshark print screen I sent)

Post the code you're currently working with! Don't forget the code tags!

es this

#include <SPI.h>
#include <Ethernet.h>
//#include <ArduinoRS485.h>
#include <ArduinoModbus.h>

// IP Addressing
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 177);
IPAddress myDns(192, 168, 1, 1);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

int Code;

EthernetServer server(502);
ModbusTCPServer modbusTCPServer;

void setup() {
// Ethernet Settings
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xFF }; // Define MAc address
byte ip[] = { 192, 168, 1, 177 }; // Define IP address
byte subnet[] = { 255, 255, 255, 0 }; // Ddefine SubNEt mask

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

// Define Holding register
Code = modbusTCPServer.configureHoldingRegisters(0x00, 100);

Serial.print("Holding register initializatinn Result= ");
Serial.print(Code);
Serial.print("\n");
Serial.print("Modbus server address:");
Serial.println(Ethernet.localIP());
}

void loop() {

// wait for a new client:
EthernetClient client = server.available();

// when the client sends the first byte, say hello:
if (client) {

// a new client connected
Serial.println("new client");
modbusTCPServer.begin(); // start listening for clients

// let the Modbus TCP accept the connection
modbusTCPServer.accept(client);

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

}

In my code I defined 100 holding register (starting from addr. 0 (40000). Trying to poll it (ex Client Modbus) always get timeout (no answer).

Does that code really match your network?

IPAddress ip(192, 168, 1, 177);
IPAddress myDns(192, 168, 1, 1);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

Please edit your post and insert code tags!

1 Like

this is the running code ( i fixed some stuff from sample). It runs good but on Mega 2650 only.

Arduino Uno has some issue... (I made some test on it https://www.fleaplc.it/index.php/tutorials/22-why-arduino-uno-is-not-suitable-as-modbus-tcp-slave)

#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, 23 };                      // 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 resgiter 40001: heartbeat (FC3)
  modbusTCPServer.holdingRegisterWrite(0x00, HeartBeat);

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


  if (_1s) {
    Serial.print("cmd");
    Serial.print(Cmd);
    Serial.print("\n");
  }
}
1 Like

Arduino Uno has some issue...

The UNO doesn't have enough RAM for the ArduinoModbus library. There are other libraries available that don't use that much RAM and should run on the UNO but I didn't test any of them (I don't use Modbus TCP myself).

Hello, I tried the library ArduinoModbus - it worked with some win applications, but with PHP not.
I spent three days with the PHP error "An exception occurred Read total timeout expired" and finally try the Arduino library ModbusIP.
It works with PHP with the first time.
https://github.com/andresarmento/modbus-arduino/tree/master/libraries/ModbusIP

It works with PHP with the first time.

PHP <-> Modbus TCP? That's something completely different, you're mixing unrelated stuff.

Hello @fleaplc.
I'm trying to use your code for the server and I get the following error:
I'm using the MEGA2560 R3 and the Ethernet Shield 2 W5500

MODBUS_TCP:33:16: error: 'HoldingResult' was not declared in this scope

Serial.print(HoldingResult);

^~~~~~~~~~~~~

C:\Users\cares\Desktop\ARDUINO ELEGOO Mega\MY PROGRAMS MEGA2560\MODBUS_TCP\MODBUS_TCP.ino:33:16: note: suggested alternative: 'HodingResult'

Serial.print(HoldingResult);

^~~~~~~~~~~~~

HodingResult

exit status 1
'HoldingResult' was not declared in this scope