Skip to content

Commit b7aeef0

Browse files
committed
ModbusTCP to ModbusRTU example added
1 parent 861f0d9 commit b7aeef0

File tree

3 files changed

+148
-5
lines changed

3 files changed

+148
-5
lines changed

examples/Bridge/README.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
# Bridge functions
22

3-
## Basic
3+
## [Basic](basic/basic.ino)
44

55
Basic 'Bridge'. Indeed this sample pulling data from Modbus Server and stores it to local registers. Local registers can be accessed via Modbus Client instance that running aside.
66

7-
## True
7+
## [ModbusRTU to ModbusTCP bridge](true/true.ino)
88

99
Fullfunctional ModbusRTU to ModbusTCP bridge.
1010

11-
## MultipeServerID
11+
## [Multiple Server ID](MultipeServerID/MultipeServerID.ino)
1212

1313
Respond for multiple ModbusRTU IDs from single device
1414

15+
## [ModbusTCP to Modbus RTU Simulator](TCP-to-RTU-Simulator/TCP-to-RTU-Simulator.ino)
16+
17+
Fullfunctional ModbusTCP to ModbusRTU bridge with on-device ModbusRTU simulator
18+
1519
```c
1620
uint16_t rawRequest(id_ip, uint8_t* data, uint16_t len, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT);
1721
uint16_t rawResponce(id_ip, uint8_t* data, uint16_t len, uint8_t unit = MODBUSIP_UNIT);
@@ -22,7 +26,12 @@ uint16_t errorResponce(id_ip, Modbus::FunctionCode fn, Modbus::ResultCode excode
2226
- `len` Byte count to send
2327
- `unit` UnitId (ModbusTCP/TLS only)
2428
- `fn` function code in responce
25-
- `excode` Exceprion code in responce
29+
- `excode` Exception code in responce
30+
31+
```c
32+
uint16_t setTransactionId(uint16_t id);
33+
```
34+
- `id` Value to replace transaction id sequence (ModbusTCP/TLS only)
2635

2736
```c
2837
union frame_arg_t {
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
ModbusRTU ESP8266/ESP32
3+
ModbusTCP to ModbusRTU bridge with on-device ModbusRTU simulator
4+
*/
5+
#ifdef ESP8266
6+
#include <ESP8266WiFi.h>
7+
#else //ESP32
8+
#include <WiFi.h>
9+
#endif
10+
#include <ModbusTCP.h>
11+
#include <ModbusRTU.h>
12+
//#include <SoftwareSerial.h>
13+
//SoftwareSerial S(13, 15);
14+
#include <StreamBuf.h>
15+
#define BSIZE 1024
16+
uint8_t buf1[BSIZE];
17+
uint8_t buf2[BSIZE];
18+
StreamBuf S1(buf1, BSIZE);
19+
StreamBuf S2(buf2, BSIZE);
20+
DuplexBuf P1(&S1, &S2);
21+
DuplexBuf P2(&S2, &S1);
22+
ModbusRTU sym;
23+
24+
int DE_RE = 2;
25+
26+
ModbusRTU rtu;
27+
ModbusTCP tcp;
28+
29+
IPAddress srcIp;
30+
31+
32+
uint16_t transRunning = 0; // Currently executed ModbusTCP transaction
33+
uint8_t slaveRunning = 0; // Current request slave
34+
35+
bool cbTcpTrans(Modbus::ResultCode event, uint16_t transactionId, void* data) { // Modbus Transaction callback
36+
if (event != Modbus::EX_SUCCESS) // If transaction got an error
37+
Serial.printf("Modbus result: %02X, Mem: %d\n", event, ESP.getFreeHeap()); // Display Modbus error code (222527)
38+
if (event == Modbus::EX_TIMEOUT) { // If Transaction timeout took place
39+
tcp.disconnect(tcp.eventSource()); // Close connection
40+
}
41+
return true;
42+
}
43+
44+
bool cbRtuTrans(Modbus::ResultCode event, uint16_t transactionId, void* data) {
45+
if (event != Modbus::EX_SUCCESS) // If transaction got an error
46+
Serial.printf("Modbus result: %02X, Mem: %d\n", event, ESP.getFreeHeap()); // Display Modbus error code (222527)
47+
return true;
48+
}
49+
50+
51+
// Callback receives raw data
52+
Modbus::ResultCode cbTcpRaw(uint8_t* data, uint8_t len, void* custom) {
53+
auto src = (Modbus::frame_arg_t*) custom;
54+
55+
Serial.print("TCP IP: ");
56+
Serial.print(IPAddress(src->ipaddr));
57+
Serial.printf(" Fn: %02X, len: %d \n\r", data[0], len);
58+
59+
if (transRunning) { // Note that we can't process new requests from TCP-side while waiting for responce from RTU-side.
60+
tcp.setTransactionId(transRunning); // Set transaction id as per incoming request
61+
tcp.errorResponce(src->ipaddr, (Modbus::FunctionCode)data[0], Modbus::EX_SLAVE_DEVICE_BUSY);
62+
return Modbus::EX_SLAVE_DEVICE_BUSY;
63+
}
64+
65+
rtu.rawRequest(slaveRunning, data, len, cbRtuTrans);
66+
67+
if (src->unitId) {
68+
tcp.setTransactionId(transRunning); // Set transaction id as per incoming request
69+
70+
//uint16_t succeed = tcp.rawResponce(src->ipaddr, data, len, slaveRunning);
71+
72+
tcp.errorResponce(src->ipaddr, (Modbus::FunctionCode)data[0], Modbus::EX_ACKNOWLEDGE);
73+
return Modbus::EX_ACKNOWLEDGE;
74+
}
75+
76+
srcIp = src->ipaddr;
77+
78+
slaveRunning = src->slaveId;
79+
80+
transRunning = src->transactionId;
81+
82+
return Modbus::EX_SUCCESS;
83+
84+
}
85+
86+
87+
// Callback receives raw data from ModbusTCP and sends it on behalf of slave (slaveRunning) to master
88+
Modbus::ResultCode cbRtuRaw(uint8_t* data, uint8_t len, void* custom) {
89+
auto src = (Modbus::frame_arg_t*) custom;
90+
tcp.setTransactionId(transRunning); // Set transaction id as per incoming request
91+
uint16_t succeed = tcp.rawResponce(srcIp, data, len, slaveRunning);
92+
if (!succeed){
93+
Serial.print("fail");
94+
}
95+
Serial.printf("RTU Slave: %d, Fn: %02X, len: %d, ", src->slaveId, data[0], len);
96+
Serial.print("Response TCP IP: ");
97+
Serial.println(srcIp);
98+
99+
transRunning = 0;
100+
slaveRunning = 0;
101+
return Modbus::EX_PASSTHROUGH;
102+
}
103+
104+
105+
void setup() {
106+
Serial.begin(115000);
107+
WiFi.begin("E2", "*****");
108+
while (WiFi.status() != WL_CONNECTED) {
109+
delay(1000);
110+
Serial.print(".");
111+
}
112+
Serial.println("");
113+
Serial.println("IP address: ");
114+
Serial.println(WiFi.localIP());
115+
116+
tcp.server(); // Initialize ModbusTCP to pracess as server
117+
tcp.onRaw(cbTcpRaw); // Assign raw data processing callback
118+
119+
//S.begin(19200, SWSERIAL_8E1);
120+
//rtu.begin(&S, DE_RE); // Specify RE_DE control pin
121+
sym.begin((Stream*)&P2);
122+
sym.slave(1);
123+
sym.addHreg(1, 100);
124+
rtu.begin((Stream*)&P1); // Specify RE_DE control pin
125+
rtu.master(); // Initialize ModbusRTU as master
126+
rtu.onRaw(cbRtuRaw); // Assign raw data processing callback
127+
}
128+
129+
void loop() {
130+
sym.task();
131+
rtu.task();
132+
tcp.task();
133+
yield();
134+
}

examples/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Examples of using callback functions.
2424

2525
Modbus file operations examples.
2626

27-
## [Modbus RTU to Modbus TCP bridge](bridge)
27+
## [ModbusRTU to ModbusTCP bridge and related functions](bridge)
2828

2929
Very basic example of accessing ModbusRTU slave device connected to ESP8266/ESP32 via ModbusTCP server.
3030

0 commit comments

Comments
 (0)