RTU Timeout on TCP/RTU bridge

Hi!

I'm testing the https://github.com/veista/modbus_bridge project as a link between QModMaster download | SourceForge.net and https://pypi.org/project/pyModSlave/. As hardware, I'm using a NodeMCU 1.0 and a USB/TTL converter.

When I make any request from the TCP client, I receive an RTU Timeout.

I've already tried using hardwareSerial, baudrates of 9600 and 19200 and powering the board with a regulated supply @5 V-1 A.

Both programs work normally when I communicate them directly with the ESP, either reading from the RTU slave or receiving reads from the TCP client.

When I use ESP as a bridge, the RTU slave receives the request normally and responds correctly in < 5 ms.

my current code is

#include <ESP8266WiFi.h>
#include <ModbusTCP.h>
#include <ModbusRTU.h>

ModbusRTU rtu;
ModbusTCP tcp;

IPAddress srcIp;

uint16_t transRunning = 0;
uint8_t slaveRunning = 0;

uint16_t ModbusBaudRate = 19200;

const char* ssid     = "<SSID>";
const char* password = "<PASSWORD>";

Modbus::ResultCode cbTcpRaw(uint8_t* data, uint8_t len, void* custom) {
  auto src = (Modbus::frame_arg_t*) custom;

  srcIp = src->ipaddr;
  slaveRunning = src->slaveId;
  transRunning = src->transactionId;

  rtu.rawRequest(slaveRunning, data, len);

  return Modbus::EX_SUCCESS;
}

Modbus::ResultCode cbRtuRaw(uint8_t* data, uint8_t len, void* custom) {
  tcp.setTransactionId(transRunning);
  tcp.rawResponce(srcIp, data, len, slaveRunning);

  transRunning = 0;
  slaveRunning = 0;
  srcIp = (0,0,0,0);
  return Modbus::EX_PASSTHROUGH;
}

void setup() {
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
    delay(1000);

  tcp.server();
  tcp.onRaw(cbTcpRaw);

  Serial.begin(ModbusBaudRate, SERIAL_8E1);
  rtu.begin(&Serial);
  rtu.master();
  rtu.onRaw(cbRtuRaw);
}

void loop() {
  rtu.task();
  tcp.task();
  yield();
}

yet, no change.

Please, any hint on what to test or what else to investigate? Thanks.

By the following code, it seems like the problem happens before the library calls:

#include <ESP8266WiFi.h>

#include <ModbusTCP.h>
#include <ModbusRTU.h>

#include <SoftwareSerial.h>
#include <StreamBuf.h>

#define BSIZE 1024

const unsigned long baudrate = 19200;
const unsigned long chtimeus = 16 * 1000000 / baudrate;

ModbusRTU rtu;
ModbusTCP tcp;

IPAddress srcIp;

SoftwareSerial debug_serial(D1, D2);

uint8_t serialw_rtur[BSIZE];
uint8_t serialr_rtuw[BSIZE];

StreamBuf serialw_rtur_sb(serialw_rtur, BSIZE);
StreamBuf serialr_rtuw_sb(serialr_rtuw, BSIZE);

DuplexBuf modbus_db(&serialw_rtur_sb, &serialr_rtuw_sb);
DuplexBuf serial_db(&serialr_rtuw_sb, &serialw_rtur_sb);

uint8_t com_buf[BSIZE];
uint8_t log_buf[BSIZE];

StreamBuf com_sbuf(com_buf, BSIZE);
StreamBuf log_sbuf(log_buf, BSIZE);

unsigned long last_us = 0;

uint16_t transRunning = 0;
uint8_t slaveRunning = 0;

bool cbRtuTrans(Modbus::ResultCode event, uint16_t transactionId, void* data) {
  if (event != Modbus::EX_SUCCESS) {
    debug_serial.printf("Modbus result: %02X, Mem: %d\n", event, ESP.getFreeHeap());
    transRunning = 0;
  }
  return true;
}

Modbus::ResultCode cbTcpRaw(uint8_t* data, uint8_t len, void* custom) {
  auto src = (Modbus::frame_arg_t*) custom;
  
  debug_serial.print("TCP IP in - ");
  debug_serial.print(IPAddress(src->ipaddr));
  debug_serial.printf(" Fn: %02X, len: %d \n\r", data[0], len);

  if (transRunning) {
    tcp.setTransactionId(src->transactionId);
    tcp.errorResponce(IPAddress(src->ipaddr), (Modbus::FunctionCode)data[0], Modbus::EX_SLAVE_DEVICE_BUSY);
    return Modbus::EX_SLAVE_DEVICE_BUSY;
  }

  rtu.rawRequest(src->unitId, data, len, cbRtuTrans);
  
  if (!src->unitId) {
    tcp.setTransactionId(src->transactionId);
    tcp.errorResponce(IPAddress(src->ipaddr), (Modbus::FunctionCode)data[0], Modbus::EX_ACKNOWLEDGE);

    transRunning = 0;
    slaveRunning = 0;
    return Modbus::EX_ACKNOWLEDGE;
  }
  
  srcIp = IPAddress(src->ipaddr);
  
  slaveRunning = src->unitId;
  
  transRunning = src->transactionId;
  
  return Modbus::EX_SUCCESS;  
  
}

Modbus::ResultCode cbRtuRaw(uint8_t* data, uint8_t len, void* custom) {
  auto src = (Modbus::frame_arg_t*)custom;
  tcp.setTransactionId(transRunning);
  uint16_t succeed = tcp.rawResponce(srcIp, data, len, slaveRunning);
  if (!succeed) {
    debug_serial.print("fail");
  }
  debug_serial.printf("RTU Slave: %d, Fn: %02X, len: %d, ", src->slaveId, data[0], len);
  debug_serial.print("Response TCP IP: ");
  debug_serial.println(srcIp);

  transRunning = 0;
  slaveRunning = 0;
  return Modbus::EX_PASSTHROUGH;
}

void print_log(char *msg) {
  debug_serial.print(msg);
  debug_serial.print(": ");
  while(log_sbuf.available()) {
    debug_serial.print(log_sbuf.read(), HEX);
    debug_serial.print(' ');    
  }
  debug_serial.println();
}

void setup() {
  Serial.begin(baudrate, SERIAL_8E1);
  debug_serial.begin(baudrate, SWSERIAL_8E1);

  WiFi.begin("<SSID>", "<PASSWORD>");
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    debug_serial.print(".");
  }

  debug_serial.println("");
  debug_serial.println("IP address: ");
  debug_serial.println(WiFi.localIP());

  tcp.server();
  tcp.onRaw(cbTcpRaw);

  rtu.begin((Stream*)&modbus_db);
  rtu.master();
  rtu.onRaw(cbRtuRaw);
}

void loop() {
  rtu.task();
  tcp.task();
  yield();

  if(Serial.available()) {

    while(Serial.available()) {
      
      char c = Serial.read();

      last_us = micros();

      while(micros() - last_us < chtimeus) {
        if(Serial.available())
          break;
      }

      com_sbuf.write(c);
      log_sbuf.write(c);

    }

    while(com_sbuf.available())
      serial_db.write(com_sbuf.read());

    print_log("received response: ");

  }

  if(serial_db.available()) {

    while(serial_db.available()) {
      
      char c = serial_db.read();

      com_sbuf.write(c);
      log_sbuf.write(c);

    }

    while(com_sbuf.available())
      Serial.write(com_sbuf.read());

    print_log("sent request: ");

  }

}

output from the TCP monitor:

Sys > 17:11:33:975 - Connecting to IP : 192.168.001.014:502 OK
[TCP]>Tx > 17:11:44:073 - 00  01  00  00  00  06  01  03  00  00  00  0A  
Sys > 17:11:44:584 - Error : Timeout
[TCP]>Tx > 17:11:49:083 - 00  02  00  00  00  06  01  03  00  00  00  0A  
[TCP]>Rx > 17:11:49:144 - 00  02  00  00  00  03  FF  83  06  
Sys > 17:11:49:144 - Error : Slave device or server is busy
[TCP]>Tx > 17:11:54:092 - 00  03  00  00  00  06  01  03  00  00  00  0A  
Sys > 17:11:54:597 - Error : Timeout
[TCP]>Tx > 17:11:59:092 - 00  04  00  00  00  06  01  03  00  00  00  0A  
[TCP]>Rx > 17:11:59:183 - 00  04  00  00  00  03  FF  83  06  
Sys > 17:11:59:183 - Error : Slave device or server is busy
[TCP]>Tx > 17:12:04:095 - 00  05  00  00  00  06  01  03  00  00  00  0A  
Sys > 17:12:04:601 - Error : Timeout
[TCP]>Tx > 17:12:09:102 - 00  06  00  00  00  06  01  03  00  00  00  0A  
[TCP]>Rx > 17:12:09:215 - 00  06  00  00  00  03  FF  83  06  
Sys > 17:12:09:215 - Error : Slave device or server is busy
[TCP]>Tx > 17:12:14:093 - 00  07  00  00  00  06  01  03  00  00  00  0A  
Sys > 17:12:14:603 - Error : Timeout
[TCP]>Tx > 17:12:19:096 - 00  08  00  00  00  06  01  03  00  00  00  0A  
[TCP]>Rx > 17:12:19:145 - 00  08  00  00  00  03  FF  83  06  
Sys > 17:12:19:145 - Error : Slave device or server is busy
[TCP]>Tx > 17:12:24:112 - 00  09  00  00  00  06  01  03  00  00  00  0A  
Sys > 17:12:24:626 - Error : Timeout
[TCP]>Tx > 17:12:29:129 - 00  0A  00  00  00  06  01  03  00  00  00  0A  
[TCP]>Rx > 17:12:29:191 - 00  0A  00  00  00  03  FF  83  06  
Sys > 17:12:29:191 - Error : Slave device or server is busy
[TCP]>Tx > 17:12:34:137 - 00  0B  00  00  00  06  01  03  00  00  00  0A  
Sys > 17:12:34:641 - Error : Timeout

output from the RTU monitor:

[RTU]>Rx > 17:11:44:150 - 01 03 00 00 00 0A C5 CD 
[RTU]>Tx > 17:11:44:167 - 01 03 14 1A AE 55 C2 20 33 8A 10 12 E5 60 D0 C4 6E B6 DB 2B 6C 79 97 A9 93 
[RTU]>Rx > 17:11:54:186 - 01 03 00 00 00 0A C5 CD 
[RTU]>Tx > 17:11:54:189 - 01 03 14 B0 25 A9 A9 7B 8C E9 F5 B1 D0 8B 53 7D 20 93 C5 D7 E2 02 07 CD 0C 
[RTU]>Rx > 17:12:04:218 - 01 03 00 00 00 0A C5 CD 
[RTU]>Tx > 17:12:04:221 - 01 03 14 CC C8 23 D9 49 20 19 20 87 A8 94 16 58 28 43 2A FF F7 64 C7 93 EF 
[RTU]>Rx > 17:12:14:265 - 01 03 00 00 00 0A C5 CD 
[RTU]>Tx > 17:12:14:268 - 01 03 14 85 0A F2 D1 E7 23 A1 3C C1 E5 AD 69 02 6D C5 18 48 D7 3A F1 78 7A 
[RTU]>Rx > 17:12:24:189 - 01 03 00 00 00 0A C5 CD 
[RTU]>Tx > 17:12:24:192 - 01 03 14 18 B7 6B 3E D7 63 15 60 2F 97 B0 FB 7E 2B B9 99 BD 51 E0 2F 82 F5 
[RTU]>Rx > 17:12:34:231 - 01 03 00 00 00 0A C5 CD 
[RTU]>Tx > 17:12:34:234 - 01 03 14 86 36 4C 88 D8 7A E7 35 B4 C2 B5 D0 B3 97 2C 08 30 86 F5 F9 25 23 

output from debug_serial:

TCP IP in - 192.168.1.13 Fn: 03, len: 5 

sent request: : 1 3 0 0 0 A C5 CD 
received response: : 1 20 91 E4 AB 9 20 26 C 24 E5 
received response: : 41 C4 CB DB 2B 2B 5D A9 F2 
TCP IP in - 192.168.1.13 Fn: 03, len: 5 

Modbus result: E4, Mem: 41336
TCP IP in - 192.168.1.13 Fn: 03, len: 5 

sent request: : 1 3 0 0 0 A C5 CD 
received response: : 1 20 11 2B A9 6A 2F 2C F5 6C B7 53 5F 9A C5 9D 2 50 8E 
TCP IP in - 192.168.1.13 Fn: 03, len: 5 

Modbus result: E4, Mem: 41336
TCP IP in - 192.168.1.13 Fn: 03, len: 5 

sent request: : 1 3 0 0 0 A C5 CD 
received response: : 1 20 11 E 23 76 A CA 20 18 8D 66 58 69 A9 FF 1F 1D 93 FF 
TCP IP in - 192.168.1.13 Fn: 03, len: 5 

Modbus result: E4, Mem: 41336
TCP IP in - 192.168.1.13 Fn: 03, len: 5 

sent request: : 1 3 0 0 0 A C5 CD 
received response: : 1 20 51 A BE 77 23 68 A E5 6B 4B 6D 71 84 5D 3A 7C E9 
TCP IP in - 192.168.1.13 Fn: 03, len: 5 

Modbus result: E4, Mem: 42008
TCP IP in - 192.168.1.13 Fn: 03, len: 5 

sent request: : 1 3 0 0 0 A C5 CD 
received response: : 1 20 11 74 5B F9 D7 AC 11 BD 97 
received response: : DB 7E A5 CB BD 54 2F B0 FF 
TCP IP in - 192.168.1.13 Fn: 03, len: 5 

Modbus result: E4, Mem: 41336
TCP IP in - 192.168.1.13 Fn: 03, len: 5 

sent request: : 1 3 0 0 0 A C5 CD 
received response: : 1 20 91 36 A D8 AF 5E A2 C2 6D 37 BB 2C 8 32 F5 7E D2 FE 
Modbus result: E4, Mem: 42008