E4 timeout error - RTU master to TCP bridge
profi-max opened this issue · 2 comments
profi-max commented
Thanks to the author for the library. But I had a problem when repeating the example. Periodically an E4 error occurs. Please help.
I use ArduinoIDE + ESP8266
Modbus RTU as master at SoftwareSerial <-bridge-> TCP server
The code below works, but very often an error occurs E4 (timeout raises function cbRtuTrans()) , after which the work completely stops.
/*
ModbusRTU ESP8266/ESP32
ModbusTCP to ModbusRTU bridge with on-device ModbusRTU simulator
*/
#ifdef ESP8266
#include <ESP8266WiFi.h>
#else //ESP32
#include <WiFi.h>
#endif
#include <ModbusTCP.h>
#include <ModbusRTU.h>
#include <SoftwareSerial.h>
SoftwareSerial S;
#include <StreamBuf.h>
ModbusRTU rtu;
ModbusTCP tcp;
IPAddress srcIp;
uint16_t transRunning = 0; // Currently executed ModbusTCP transaction
uint8_t slaveRunning = 0; // Current request slave
bool cbTcpTrans(Modbus::ResultCode event, uint16_t transactionId, void* data) { // Modbus Transaction callback
if (event != Modbus::EX_SUCCESS) // If transaction got an error
Serial.printf("Modbus TCP result: %02X, Mem: %d\n", event, ESP.getFreeHeap()); // Display Modbus error code (222527)
if (event == Modbus::EX_TIMEOUT) { // If Transaction timeout took place
tcp.disconnect(tcp.eventSource()); // Close connection
transRunning = 0;
slaveRunning = 0;
}
return true;
}
bool cbRtuTrans(Modbus::ResultCode event, uint16_t transactionId, void* data) {
if (event != Modbus::EX_SUCCESS) // If transaction got an error
Serial.printf("Modbus RTU result: %02X, Mem: %d\n", event, ESP.getFreeHeap()); // Display Modbus error code (222527)
return true;
}
// Callback receives raw data
Modbus::ResultCode cbTcpRaw(uint8_t* data, uint8_t len, void* custom) {
auto src = (Modbus::frame_arg_t*) custom;
Serial.print("TCP IP in - ");
Serial.print(IPAddress(src->ipaddr));
Serial.printf(" Fn: %02X, len: %d \n\r", data[0], len);
if (transRunning) { // Note that we can't process new requests from TCP-side while waiting for responce from RTU-side.
tcp.setTransactionId(src->transactionId); // Set transaction id as per incoming request
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) { // If broadcast request (no responce from slave is expected)
tcp.setTransactionId(src->transactionId); // Set transaction id as per incoming request
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;
}
// Callback receives raw data from ModbusTCP and sends it on behalf of slave (slaveRunning) to master
Modbus::ResultCode cbRtuRaw(uint8_t* data, uint8_t len, void* custom) {
auto src = (Modbus::frame_arg_t*) custom;
if (!transRunning) // Unexpected incoming data
return Modbus::EX_PASSTHROUGH;
tcp.setTransactionId(transRunning); // Set transaction id as per incoming request
uint16_t succeed = tcp.rawResponce(srcIp, data, len, slaveRunning);
if (!succeed){
Serial.print("TCP IP out - failed");
}
Serial.printf("RTU Slave: %d, Fn: %02X, len: %d, ", src->slaveId, data[0], len);
Serial.print("Response TCP IP: ");
Serial.println(srcIp);
transRunning = 0;
slaveRunning = 0;
return Modbus::EX_PASSTHROUGH;
}
void setup() {
S.begin(115200, SWSERIAL_8N1, 13, 15);
Serial.begin(115000);
WiFi.begin("Zyxel2", "mypass12345");
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
tcp.server(); // Initialize ModbusTCP to pracess as server
tcp.onRaw(cbTcpRaw); // Assign raw data processing callback
rtu.begin(&S);
rtu.master(); // Initialize ModbusRTU as master
rtu.onRaw(cbRtuRaw); // Assign raw data processing callback
}
void loop() {
rtu.task();
tcp.task();
yield();
}
Terminal messagese:
RTU Slave: 1, Fn: 03, len: 22, Response TCP IP: 192.168.1.78
TCP IP in - 192.168.1.78 Fn: 03, len: 5
RTU Slave: 1, Fn: 03, len: 22, Response TCP IP: 192.168.1.78
TCP IP in - 192.168.1.78 Fn: 03, len: 5
RTU Slave: 1, Fn: 03, len: 22, Response TCP IP: 192.168.1.78
TCP IP in - 192.168.1.78 Fn: 03, len: 5
Modbus RTU result: E4, Mem: 46600
TCP IP in - 192.168.1.78 Fn: 03, len: 5
TCP IP in - 192.168.1.78 Fn: 03, len: 5
But if I change the code to be confident in equipment and RTU side, then the error never arises.
bool cbRead(Modbus::ResultCode event, uint16_t transactionId, void* data) {
Serial.printf_P("Request Read result: 0x%02X, Mem: %d\n", event, ESP.getFreeHeap());
return true;
}
void loop() {
static uint16_t buffer1[100];
memset(buffer1, 0, 32);
if (!rtu.slave())
rtu.readHreg(1, 0, buffer1, 16, cbRead);
rtu.task();
///////// tcp.task();
yield();
}
The trick like this didn't help me:
#ifdef MODBUSIP_MAX_READMS //if the macro MODBUSIP_MAX_READMS is defined
#undef MODBUSIP_MAX_READMS//un-define it
#define MODBUSIP_MAX_READMS 300//redefine it with the new value
#endif
profi-max commented
I transferred the project to the VSCode+Platformio to be able to change the library files. Unfortunately, E4 error remains.
With defines:
#define MODBUSIP_DEBUG
#define MODBUSRTU_DEBUG
#define MODBUSRTU_MAX_READMS 300
Terminal messages:
TCP IP in - 192.168.1.78 Fn: 03, len: 5
3 0 0 0 A
3 14 1 F4 0 C8 A AB 5 5F F 8 D 98 0 1 0 B 0 0 0 0 A6 A6
RTU Slave: 1, Fn: 03, len: 22, Response TCP IP: 192.168.1.78
0: Bytes available 12
TCP IP in - 192.168.1.78 Fn: 03, len: 5
3 0 0 0 A
3 14 1 F4 0 C8 A AB 5 5F F 8 D 98 0 1 0 B 0 0 0 0 A6 A6
RTU Slave: 1, Fn: 03, len: 22, Response TCP IP: 192.168.1.78
0: Bytes available 12
TCP IP in - 192.168.1.78 Fn: 03, len: 5
3 0 0 0 A
3 14 1 F4 0 C8 A D5 5 67 E AB D 98 0 1 0 B 0 0 0 0 F6 BB
RTU Slave: 1, Fn: 03, len: 22, Response TCP IP: 192.168.1.78
0: Bytes available 12
TCP IP in - 192.168.1.78 Fn: 03, len: 5
3 0 0 0 A
3 14 1 F4 0 C8 A D5 5 67 E AB D 98 0 1 0 B 0 0 0 7D F7
Modbus RTU result: E4, Mem: 47072
0: Bytes available 12
TCP IP in - 192.168.1.78 Fn: 03, len: 5
0: Bytes available 12
TCP IP in - 192.168.1.78 Fn: 03, len: 5
profi-max commented
Unfortunately, the problem did not solve.