3

I'm testing the following code as a bridge between https://sourceforge.net/projects/qmodmaster/ and https://pypi.org/project/pyModSlave/.

As hardware, I'm using a NodeMCU 1.0 and a USB/TTL converter.

The Modbus library is https://github.com/emelianov/modbus-esp8266.

#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 = (8 + 3) * 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);

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("modbusRTU transaction result: %02X\n\r", event); 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("received a TCP request from "); 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;

debug_serial.printf("received RTU response from %d-> Fn: %02X, len: %d\n\r", src->slaveId, data[0], len);

tcp.setTransactionId(transRunning); uint16_t succeed = tcp.rawResponce(srcIp, data, len, slaveRunning); if (!succeed) { debug_serial.print("failed to"); }

debug_serial.print("respond to TCP: "); debug_serial.println(srcIp);

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

void print_log(const 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 process_from_to(Stream from_s, Stream to_s, unsigned delay_us = 0) { while(from_s->available()) {

char c = from_s-&gt;read();

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

if(delay_us != 0)
  delayMicroseconds(delay_us);

}

while(com_sbuf.available()) to_s->write(com_sbuf.read()); }

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()) {

process_from_to(&amp;Serial, &amp;serial_db, chtimeus &lt;&lt; 1);

print_log(&quot;received response from RTU&quot;);

}

if(serial_db.available()) {

process_from_to(&amp;serial_db, &amp;Serial);

print_log(&quot;sent request to RTU&quot;);

}

}

qModMaster has the following configs:

  • Modbus Mode: TCP
  • Slave Addr: 1
  • Scan Rate: 5 s
  • Function Code: 0x03
  • Start Address: 0x00
  • Register Number: 10
  • Slave IP: my ESP's IP in the network
  • Slave Port: 502

pyModSlave has the following configs:

  • Modbus Mode: RTU
  • Slave Address: 1
  • SimCycle: 5 s
  • Port: my ESP's Serial's USB port
  • Baudrate: 19200
  • Data Bits: 8
  • Stop Bits: 1
  • Parity: None

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

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 <5ms, but the timeout occurs.

An external monitor (a Uno with the Rx of a SoftwareSerial connected to the NodeMCU hardware Rx pin) shows that the correct data reaches the ESP:

rtu monitor:

[RTU]>Rx > 18:21:37:626 - 01 03 00 00 00 0A C5 CD 
[RTU]>Tx > 18:21:37:626 - 01 03 14 9D AC D8 0D 61 1A 29 7B 0E 7D 19 15 62 01 C2 F1 9E CF 41 C6 3C D4 
[RTU]>Rx > 18:21:47:674 - 01 03 00 00 00 0A C5 CD 
[RTU]>Tx > 18:21:47:675 - 01 03 14 A7 EE 7E F2 5D 43 66 D7 4B 73 3A 0A D2 B6 23 BB F0 E4 AB D0 CD 9E 
[RTU]>Rx > 18:21:57:590 - 01 03 00 00 00 0A C5 CD 
[RTU]>Tx > 18:21:57:590 - 01 03 14 D0 31 DC 14 E7 A2 84 49 C6 3A 1D 13 BD 7E DD DF E1 C7 02 89 F0 80 
[RTU]>Rx > 18:22:07:638 - 01 03 00 00 00 0A C5 CD 
[RTU]>Tx > 18:22:07:639 - 01 03 14 71 26 FE 5B 12 23 A7 F4 39 0A 55 12 F9 E4 63 27 90 0C 18 11 00 51 
[RTU]>Rx > 18:22:17:682 - 01 03 00 00 00 0A C5 CD 
[RTU]>Tx > 18:22:17:683 - 01 03 14 1C 9D A1 68 11 71 A4 96 1D BF D4 C3 86 B1 B2 42 68 C4 72 BD C6 A3 
[RTU]>Rx > 18:22:27:722 - 01 03 00 00 00 0A C5 CD 
[RTU]>Tx > 18:22:27:724 - 01 03 14 93 6B 28 A4 F2 DD 3D E1 C3 29 61 82 EF CC E3 37 99 AA 32 04 3A 56 

external monitor:

response: 1 3 14 9D AC D8 D 61 1A 29 7B E 7D 19 15 62 1 C2 F1 9E CF 41 C6 3C D4
response: 1 3 14 A7 EE 7E F2 5D 43 66 D7 4B 73 3A A D2 B6 23 BB F0 E4 AB D0 CD 9E
response: 1 3 14 D0 31 DC 14 E7 A2 84 49 C6 3A 1D 13 BD 7E DD DF E1 C7 2 89 F0 80
response: 1 3 14 71 26 FE 5B 12 23 A7 F4 39 A 55 12 F9 E4 63 27 90 C 18 11 0 51
response: 1 3 14 1C 9D A1 68 11 71 A4 96 1D BF D4 C3 86 B1 B2 42 68 C4 72 BD C6 A3
response: 1 3 14 93 6B 28 A4 F2 DD 3D E1 C3 29 61 82 EF CC E3 37 99 AA 32 4 3A 56

bridge monitor:

received a TCP request from 192.168.1.12-> Fn: 03, len: 5
sent request to RTU: 1 3 0 0 0 A C5 CD 
received response from RTU: 1 20 51 C6 C3 D 58 A3 69 39 7D 46 91 5 C2 7C F6 41 1C A2 
received a TCP request from 192.168.1.12-> Fn: 03, len: 5
modbusRTU transaction result: E4

received a TCP request from 192.168.1.12-> Fn: 03, len: 5 sent request to RTU: 1 3 0 0 0 A C5 CD received response from RTU: 1 20 D1 73 7E BE 35 99 D7 A9 E9 A 3A DB DA F0 DE D D7 9E

received a TCP request from 192.168.1.12-> Fn: 03, len: 5 modbusRTU transaction result: E4

received a TCP request from 192.168.1.12-> Fn: 03, len: 5 sent request to RTU: 1 3 0 0 0 A C5 CD received response from RTU: 1 20 11 17 E2 14 9E 23 49 9C EA 13 6F 75 DF 78 9C 89 80 received a TCP request from 192.168.1.12-> Fn: 03, len: 5 modbusRTU transaction result: E4

received a TCP request from 192.168.1.12-> Fn: 03, len: 5 sent request to RTU: 1 3 0 0 0 A C5 CD received response from RTU: 1 20 51 99 FE 2B 34 3A F4 4E A1 95 94 E4 AC 12 C6 18 44 51 received a TCP request from 192.168.1.12-> Fn: 03, len: 5 modbusRTU transaction result: E4

received a TCP request from 192.168.1.12-> Fn: 03, len: 5 sent request to RTU: 1 3 0 0 0 A C5 CD received response from RTU: 1 20 11 D4 A1 2B 14 91 96 47 A3 C3 58 93 42 8B 72 6F DC FF received a TCP request from 192.168.1.12-> Fn: 03, len: 5 modbusRTU transaction result: E4

received a TCP request from 192.168.1.12-> Fn: 03, len: 5 sent request to RTU: 1 3 0 0 0 A C5 CD received response from RTU: 1 20 D1 B6 A1 A4 BE D7 A C3 4A 9 EF 6E 37 66 35 22 3A F5 received a TCP request from 192.168.1.12-> Fn: 03, len: 5 modbusRTU transaction result: E4

tcp monitor

[TCP]>Tx > 18:21:37:517 - 00  16  00  00  00  06  01  03  00  00  00  0A  
Sys > 18:21:38:031 - Error : Timeout
[TCP]>Tx > 18:21:42:523 - 00  17  00  00  00  06  01  03  00  00  00  0A  
[TCP]>Rx > 18:21:42:649 - 00  17  00  00  00  03  FF  83  06  
Sys > 18:21:42:649 - Error : Slave device or server is busy
[TCP]>Tx > 18:21:47:524 - 00  18  00  00  00  06  01  03  00  00  00  0A  
Sys > 18:21:48:039 - Error : Timeout
[TCP]>Tx > 18:21:52:525 - 00  19  00  00  00  06  01  03  00  00  00  0A  
[TCP]>Rx > 18:21:52:684 - 00  19  00  00  00  03  FF  83  06  
Sys > 18:21:52:684 - Error : Slave device or server is busy
[TCP]>Tx > 18:21:57:521 - 00  1A  00  00  00  06  01  03  00  00  00  0A  
Sys > 18:21:58:027 - Error : Timeout
[TCP]>Tx > 18:22:02:536 - 00  1B  00  00  00  06  01  03  00  00  00  0A  
[TCP]>Rx > 18:22:02:595 - 00  1B  00  00  00  03  FF  83  06  
Sys > 18:22:02:595 - Error : Slave device or server is busy
[TCP]>Tx > 18:22:07:543 - 00  1C  00  00  00  06  01  03  00  00  00  0A  
Sys > 18:22:08:044 - Error : Timeout
[TCP]>Tx > 18:22:12:539 - 00  1D  00  00  00  06  01  03  00  00  00  0A  
[TCP]>Rx > 18:22:12:633 - 00  1D  00  00  00  03  FF  83  06  
Sys > 18:22:12:633 - Error : Slave device or server is busy
[TCP]>Tx > 18:22:17:542 - 00  1E  00  00  00  06  01  03  00  00  00  0A  
Sys > 18:22:18:047 - Error : Timeout
[TCP]>Tx > 18:22:22:531 - 00  1F  00  00  00  06  01  03  00  00  00  0A  
[TCP]>Rx > 18:22:22:577 - 00  1F  00  00  00  03  FF  83  06  
Sys > 18:22:22:577 - Error : Slave device or server is busy
[TCP]>Tx > 18:22:27:536 - 00  20  00  00  00  06  01  03  00  00  00  0A  
Sys > 18:22:28:041 - Error : Timeout
[TCP]>Tx > 18:22:32:534 - 00  21  00  00  00  06  01  03  00  00  00  0A  
[TCP]>Rx > 18:22:32:595 - 00  21  00  00  00  03  FF  83  06  
Sys > 18:22:32:595 - Error : Slave device or server is busy

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

0 Answers0