Modbus with Ethernet Shield

Hello

I’m trying to implement Modbus Master using my Arduino Mega & Ethernet Shield then connect it to Allen-Bradely PLC .

First, I have done a little modification to example code below Then connect my arduino and my laptop to a switch and tested it with modbus simulator (Modbus Slave program from www.modbustools.com) and I succeeded to write & Read

After that I Connected my Laptop to a EKI-7659C Industrial switch which is connected to the Allen-Bradely PLC and also I was able to read registers through the modbus simulator

Then I connected my Arduino & Ethernet shield and I gave them IP matching with the network, First I couldn’t connect then I had to change the port speed from 100Mbps to 10Mbps. After that the arduino is successfully connected and I can ping it from the laptop and also I have received successful connection serial messages through my Serial Monitor.

The problem here is I can’t read any register, “holdingRegisterRead” is always return “-1” which means unsuccessful.

Code:

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

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xE8 }; // Ethernet MAC Address
IPAddress ip(192,168,1,140); // Ethernet MAC IP address

EthernetClient client;
ModbusTCPClient modbusTCPClient(client);

IPAddress server(192,168,1,25); // update with the IP Address of your Modbus server

void setup() {

   Serial.begin(9600);

//  // start the Ethernet connection:
 if (Ethernet.begin(mac) == 0) {
   Serial.println("Failed to configure Ethernet using DHCP");

   // try to congifure using IP address :
   Ethernet.begin(mac, ip);
 } else {
   Serial.print("  DHCP assigned IP ");
   Serial.println(Ethernet.localIP());
 }

 // give the Ethernet shield a second to initialize:
 delay(1000);
 Serial.print("connecting to ");
 Serial.print(server);
 Serial.println("...");

//   if you get a connection, report back via serial:
 if (client.connect(server, 502)) {
   Serial.print("connected to ");
   Serial.println(client.remoteIP());
   client.println("Connection: close");
   client.println();
 } else {
   // if you didn't get a connection to the server:
   Serial.println("connection failed");
 }
//  
   Serial.println("Modbus TCP Client Toggle");
       
   Ethernet.begin(mac, ip);  // initialize Ethernet device

   delay(3000);

}

void loop() {

 long regStatus[10];
 long regRaw[10]; 

 long regStatusTest,regStatusTest2;
 String readString;
 long Address;
 
 if (!modbusTCPClient.connected()) {
   // client not connected, start the Modbus TCP client
   Serial.println("Attempting to connect to Modbus TCP server");
   
   if (!modbusTCPClient.begin(server)) {
     Serial.println("Modbus TCP Client failed to connect!");
   } else {
     Serial.println("Modbus TCP Client connected");
   }
 } else {
//     client connected

//////////////////TEST///////////////////////////////////////////////////

while (Serial.available()) {
 delay(2);
 char c = Serial.read();
 readString += c;
}
if (readString.length() > 0) {
 Serial.println(readString);
 Address = atol(readString.c_str());
 Serial.println(Address);
}

   regStatusTest = modbusTCPClient.holdingRegisterRead(Address);
   Serial.print("regStatusTest = ");
   Serial.println(regStatusTest);
   regStatusTest2 = modbusTCPClient.holdingRegisterRead(Address);
   Serial.print("regStatusTest2 = ");
   Serial.println(regStatusTest2);

////////////////End Of TEST //////////////////////////////////////////////
   
   // wait for 1 second
   delay(1000);
 }
}

You must not call Ethernet.begin() after you connected to the server.

I have received successful connection serial messages through my Serial Monitor.

Post the exact output you got using that sketch!

Have you tried to simple use the Modbus library to connect to the Modbus server? The “connection test” in your sketch might confuse your PLC and it might disable the Arduinos IP for some time.

The ArduinoModbus library is written for ARM based Arduinos (mainly the MKR series). As it’s quite wasteful with memory it’s a bad choice for AVR based Arduinos although it compiles and basically works on that platform too.

Please explain, what the delay(2) call is thought for. In my opinion you should delete that line.

Thanks Pylon for your reply

I forgot the old code running for about 15 mins and when I came back I found that it started to read and worked find!! I checked Serial Monitor time stamps and found that it took about 10 mins with "-1" response then it's reconnected to Modbus slave and started to response with the correct data.
This is strange behavior and i tested it twice same happened.

pylon:
You must not call Ethernet.begin() after you connected to the server.

Ok, I will remove it.

pylon:
Post the exact output you got using that sketch!

Ok I will attach it after I do the modifications suggested by you

pylon:
Have you tried to simple use the Modbus library to connect to the Modbus server?

The ArduinoModbus library is written for ARM based Arduinos (mainly the MKR series). As it's quite wasteful with memory it's a bad choice for AVR based Arduinos although it compiles and basically works on that platform too.

Actually you are totally right, I though the code is not that much but I had problems when I uploaded it to Arduino UNO, as a test code I took the easy step and upgraded to Mega. Anyway I will include Modbus library and try the code again.

pylon:
The "connection test" in your sketch might confuse your PLC and it might disable the Arduinos IP for some time.

I don't quite understand what this means, can you explain it because it seems that this is what happened exactly :slight_smile:
I couldn't connect for about 9-10 mins then it's suddenly started to connect and receive data

pylon:
Please explain, what the delay(2) call is thought for. In my opinion you should delete that line.

This part of code is just to put an addresses (for testing) through the serial monitor, I just prefer to put any delay when dealing with serial but yes no problem I will remove it.

This is strange behavior and i tested it twice same happened.

This is not that strange, it can be explained by your connection test which confused the server that much that it refused the connection for about 10 min.

I don't quite understand what this means, can you explain it because it seems that this is what happened exactly :slight_smile:
I couldn't connect for about 9-10 mins then it's suddenly started to connect and receive data

You connect to the Modbus server but don't talk Modbus to it. It's completely up to the Modbus server how to react to that "attack", it seems your PLC simply refused service to your IP for 10 min.

This part of code is just to put an addresses (for testing) through the serial monitor, I just prefer to put any delay when dealing with serial but yes no problem I will remove it.

Regarding the Arduino hardware serial implementation delay() calls almost never help, but often make the debugging much harder.