You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: arduino-modbus-rtu-tcp-gateway/02-modbus-tcp.ino
+49-31Lines changed: 49 additions & 31 deletions
Original file line number
Diff line number
Diff line change
@@ -29,38 +29,41 @@
29
29
#defineADDRESS_POS (6 * !localConfig.enableRtuOverTcp) // position of slave address in the incoming TCP/UDP message (0 for Modbus RTU over TCP/UDP and 6 for Modbus RTU over TCP/UDP)
30
30
31
31
enum status : byte {
32
-
STAT_OK,
33
-
STAT_ERROR_0X,
34
-
STAT_ERROR_0A,
35
-
STAT_ERROR_0B,
36
-
STAT_NUM // Number of status flags in this enum. Must be the last element within this enum!!
32
+
STAT_OK, // Slave Responded
33
+
STAT_ERROR_0X, // Slave Responded with Error (Codes 1~8)
34
+
STAT_ERROR_0A, // Gateway Overloaded (Code 10)
35
+
STAT_ERROR_0B, // Slave Failed to Respond (Code 11)
36
+
STAT_ERROR_0B_QUEUE, // Slave Failed to Respond (Code 11) + in Queue
37
+
STAT_NUM // Number of status flags in this enum. Must be the last element within this enum!!
37
38
};
38
39
39
40
// bool arrays for storing Modbus RTU status of individual slaves
40
41
uint8_t stat[STAT_NUM][(maxSlaves + 1 + 7) / 8];
41
42
43
+
// Scan request is in queue
44
+
bool scanInQueue = false;
45
+
42
46
// array for storing error counts
43
47
uint16_t errorCount[STAT_NUM];
44
48
uint16_t errorInvalid;
45
49
46
-
// bool arrays for storing Modbus RTU status (responging or not responding). Array index corresponds to slave address.
byte msgLen; // lenght of Modbus message stored in queuePDUs
57
+
byte msgLen; // lenght of Modbus message stored in queueData
55
58
IPAddress remIP; // remote IP for UDP client (UDP response is sent back to remote IP)
56
59
unsignedint remPort; // remote port for UDP client (UDP response is sent back to remote port)
57
60
byte clientNum; // TCP client who sent the request, UDP_REQUEST (0xFF) designates UDP client
58
61
byte atts; // attempts counter
59
62
} header;
60
63
61
64
// each request is stored in 3 queues (all queues are written to, read and deleted in sync)
62
-
CircularBuffer<header, reqQueueCount> queueHeaders; // queue of requests' headers and metadata (MBAP transaction ID, MBAP unit ID, PDU length, remIP, remPort, TCP client)
63
-
CircularBuffer<byte, reqQueueSize> queuePDUs;// queue of PDU data (function code, data)
65
+
CircularBuffer<header, maxQueueRequests> queueHeaders; // queue of requests' headers and metadata (MBAP transaction ID, MBAP unit ID, PDU length, remIP, remPort, TCP client)
66
+
CircularBuffer<byte, maxQueueData> queueData; // queue of PDU data (function code, data)
64
67
65
68
voidrecvUdp() {
66
69
unsignedint msgLength = Udp.parsePacket();
@@ -81,13 +84,14 @@ void recvUdp() {
81
84
Udp.write(inBuffer, 5);
82
85
Udp.write(0x03);
83
86
}
84
-
Udp.write(inBuffer[ADDRESS_POS]); // address
85
-
Udp.write(inBuffer[ADDRESS_POS + 1] + 0x80); // function + 0x80
87
+
byte addressPos = 6 * !localConfig.enableRtuOverTcp; // position of slave address in the incoming TCP/UDP message (0 for Modbus RTU over TCP/UDP and 6 for Modbus RTU over TCP/UDP)
88
+
Udp.write(inBuffer[addressPos]); // address
89
+
Udp.write(inBuffer[addressPos + 1] + 0x80); // function + 0x80
86
90
Udp.write(errorCode);
87
91
if (localConfig.enableRtuOverTcp) {
88
92
crc = 0xFFFF;
89
-
calculateCRC(inBuffer[ADDRESS_POS]);
90
-
calculateCRC(inBuffer[ADDRESS_POS + 1] + 0x80);
93
+
calculateCRC(inBuffer[addressPos]);
94
+
calculateCRC(inBuffer[addressPos + 1] + 0x80);
91
95
calculateCRC(errorCode);
92
96
Udp.write(lowByte(crc)); // send CRC, low byte first
93
97
Udp.write(highByte(crc));
@@ -120,13 +124,14 @@ void recvTcp() {
120
124
client.write(inBuffer, 5);
121
125
client.write(0x03);
122
126
}
123
-
client.write(inBuffer[ADDRESS_POS]); // address
124
-
client.write(inBuffer[ADDRESS_POS + 1] + 0x80); // function + 0x80
127
+
byte addressPos = 6 * !localConfig.enableRtuOverTcp; // position of slave address in the incoming TCP/UDP message (0 for Modbus RTU over TCP/UDP and 6 for Modbus RTU over TCP/UDP)
128
+
client.write(inBuffer[addressPos]); // address
129
+
client.write(inBuffer[addressPos + 1] + 0x80); // function + 0x80
125
130
client.write(errorCode);
126
131
if (localConfig.enableRtuOverTcp) {
127
132
crc = 0xFFFF;
128
-
calculateCRC(inBuffer[ADDRESS_POS]);
129
-
calculateCRC(inBuffer[ADDRESS_POS + 1] + 0x80);
133
+
calculateCRC(inBuffer[addressPos]);
134
+
calculateCRC(inBuffer[addressPos + 1] + 0x80);
130
135
calculateCRC(errorCode);
131
136
client.write(lowByte(crc)); // send CRC, low byte first
if (localConfig.enableRtuOverTcp) { // check CRC for Modbus RTU over TCP/UDP
185
+
byte addressPos = 6 * !localConfig.enableRtuOverTcp; // position of slave address in the incoming TCP/UDP message (0 for Modbus RTU over TCP/UDP and 6 for Modbus RTU over TCP/UDP)
186
+
if (localConfig.enableRtuOverTcp) { // check CRC for Modbus RTU over TCP/UDP
180
187
if (checkCRC(inBuffer, msgLength) == false) {
181
188
errorInvalid++;
182
-
return0; //reject: do nothing and return no error code
if (queuePDUs[0] == 0x00) { // Modbus broadcast - we do not count attempts and delete immediatelly
63
+
if (queueData[0] == 0x00) { // Modbus broadcast - we do not count attempts and delete immediatelly
64
64
serialState = IDLE;
65
65
deleteRequest();
66
66
} else {
@@ -93,7 +93,7 @@ void recvSerial() {
93
93
// Process Serial data
94
94
// Checks: 1) RTU frame is without errors; 2) CRC; 3) address of incoming packet against first request in queue; 4) only expected responses are forwarded to TCP/UDP
0 commit comments