Why different Request Intervals Cause Significant Delay in MODBUS TCP/IP Communication

Hello everyone, I am using Arduino DUE and Arduino Ethernet Shield 2 for MODBUS TCP/IP communication. Specifically, I have the Arduino DUE acting as a MODBUS Master, while the PC serves as the SLAVE using MODBUS Slave software.
When I set the REQUEST_INTERVAL to 2 seconds, the Response time (microseconds) is 378. When I set the interval to 0.02 seconds, the Response time (microseconds) is 19744. Do you think the slowdown is caused by the Arduino DUE being overloaded or the Arduino Ethernet Shield 2 being overloaded?
Here is my code:

#include <SPI.h>
#include <Ethernet.h>

// Pin Definitions

// Network Configuration
byte mac[] = { 0xA8, 0x61, 0x0A, 0xAE, 0x0A, 0xCC };
IPAddress server(192, 168, 123, 209);  // ModbusTCP server address
IPAddress localIP(192, 168, 123, 207); // Local IP address as slave
EthernetClient ethClient;
EthernetServer slaveServer(502);        // Modbus slave server

// ModbusTCP Configuration
uint16_t transactionId = 0;
uint16_t holdingRegisters[100];         // Holding registers array
bool isMasterMode = true;               // Mode switching flag
unsigned long modeChangeTimer = 0;       // Mode change timer
const unsigned long MODE_CHANGE_INTERVAL = 10000; // Mode change interval(ms)

unsigned long requestStartTime = 0;  // Request start time
unsigned long lastRequestTime = 0;   // Last request time
const unsigned long REQUEST_INTERVAL = 2000000; // 2 seconds = 2000000 microseconds

void sendModbusRequest(byte slaveId, byte functionCode, uint16_t startAddr, uint16_t quantity) {
  byte request[12];
  
  // Modbus TCP Frame Header
  request[0] = highByte(transactionId);
  request[1] = lowByte(transactionId++);
  request[2] = 0x00; // Protocol Identifier High Byte
  request[3] = 0x00; // Protocol Identifier Low Byte
  request[4] = 0x00; // Length High Byte
  request[5] = 0x06; // Length Low Byte
  request[6] = slaveId;
  request[7] = functionCode;
  request[8] = highByte(startAddr);
  request[9] = lowByte(startAddr);
  request[10] = highByte(quantity);
  request[11] = lowByte(quantity);
  
  ethClient.write(request, 12);
}


void readModbusResponse() {
  byte buffer[256];
  int len = 0;
  
  while (ethClient.available() && len < 256) {
    buffer[len++] = ethClient.read();
  }
  
  if (len > 0) {
    // Serial.print("Response received, length: ");
    // Serial.println(len);
    // Serial.print("Data content: ");
    
    // // Print each byte in hexadecimal format
    // for(int i = 0; i < len; i++) {
    //   if(buffer[i] < 0x10) {
    //     Serial.print("0"); // Add leading zero
    //   }
    //   Serial.print(buffer[i], HEX);
    //   Serial.print(" ");
    // }
    // Serial.println(); // New line
    
    // Parse Modbus response
    if(len >= 9 && buffer[7] == 0x03) {  // Verify read holding register response
      byte dataLen = buffer[8];  // Number of data bytes
      if(len >= (9 + dataLen)) {
        // uint16_t registerValue = (buffer[9] << 8) | buffer[10];  // Combine high and low bytes
        // Serial.print("Register value: ");
        // Serial.println(registerValue);
        unsigned long responseTime = micros() - requestStartTime;  // Calculate response time
        
        Serial.print("Response time (microseconds): ");
        Serial.println(responseTime);
      }
    }
  }
}


void runMasterMode() {
  if (!ethClient.connected()) {
    if (ethClient.connect(server, 502)) {
      Serial.println("Connected to Modbus server");
    } else {
      Serial.println("Connection failed");
      return;
    }
  }

    requestStartTime = micros();  // Record sending time
    sendModbusRequest(0x01, 0x03, 0x0000, 0x0001);
    lastRequestTime = micros();
  
  if (ethClient.available()) {
    readModbusResponse();
  }
}



void setup() {
  Serial.begin(9600);  // Initialize Serial for debugging

  // Initialize Ethernet
  Ethernet.begin(mac, localIP);

  

}

void loop() {


  // Check if sending interval has elapsed
  if (micros() - lastRequestTime >= REQUEST_INTERVAL) {
    runMasterMode();
  }
}

I would think the Arduino DUE is saturating the capabilities of the Ethernet Shield.

Yes, I think so too. Do you know if there are any Ethernet shields with higher processing capabilities available for Arduino?

I would not know for certain - may be look at Wiznet W6100 based Ethernet Shields.

Do you really need a REQUEST_INTERVAL of 20ms ?

Also - in a busy network with a lot of traffic, a 20 ms interval could lead to collisions or delays, particularly if the devices are not prioritized.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.