Skip to content

Commit 7d9b766

Browse files
committed
Save error counters to EEPROM
1 parent 7a50bd4 commit 7d9b766

File tree

7 files changed

+218
-229
lines changed

7 files changed

+218
-229
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Change settings of your Arduino-based Modbus RTU to Modbus TCP/UDP gateway via w
3030
- send Modbus request and recieve Modbus response
3131
- scan Modbus slaves on RS485 interface
3232
- queue (buffer) status
33-
- error counts
33+
- error counters (stored in EEPROM)
3434
- content of the Modbus Status page is updated in the background (fetch API), javascript alert is shown if connection is lost
3535
* optimized TCP socket management (web interface and Modbus TCP):
3636
- gateway always listens for new web and Modbus TCP connections
@@ -73,7 +73,7 @@ Change settings of your Arduino-based Modbus RTU to Modbus TCP/UDP gateway via w
7373

7474
**Requests Queue**. Monitors internal request queue (buffer). The limits for bytes and for the number of requests stored in the queue can be configured in advanced settings.
7575

76-
**Modbus Statistics**. Counters for various errors. Insigned longs are used, rollover of counters is synchronized:
76+
**Modbus Statistics**. Counters for various errors. Counters are periodically saved to EEPROM. Insigned longs are used, rollover of counters is synchronized:
7777
* **Slave Responded**. Slave responded with a valid Modbus RTU response within response timeout.
7878
* **Slave Responded with Error (Codes 1~8)**. Slave responded, but with an error. For the list of error codes see https://en.wikipedia.org/wiki/Modbus#Exception_responses.
7979
* **Gateway Overloaded (Code 10)**. Request queue is full (either the number of bytes stored or the number of requests stored). Request was dropped and the gateway responded with an error code 10.

arduino-modbus-rtu-tcp-gateway/01-interfaces.ino

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ void startEthernet() {
8888
digitalWrite(ETH_RESET_PIN, LOW);
8989
delay(25);
9090
digitalWrite(ETH_RESET_PIN, HIGH);
91-
delay(500);
91+
delay(ETH_RESET_DELAY);
9292
}
9393
byte mac[6];
9494
memcpy(mac, MAC_START, 3); // set first 3 bytes
@@ -148,14 +148,11 @@ void maintainUptime() {
148148
bool rollover() {
149149
// synchronize roll-over of run time, data counters and modbus stats to zero, at 0xFFFFFF00
150150
const unsigned long ROLLOVER = 0xFFFFFF00;
151-
for (byte i = 0; i < SLAVE_ERROR_0B_QUEUE; i++) { // there is no counter for SLAVE_ERROR_0B_QUEUE
151+
for (byte i = 0; i < ERROR_LAST; i++) { // there is no counter for SLAVE_ERROR_0B_QUEUE
152152
if (errorCount[i] > ROLLOVER) {
153153
return true;
154154
}
155155
}
156-
if (errorTcpCount > ROLLOVER || errorRtuCount > ROLLOVER || errorTimeoutCount > ROLLOVER) {
157-
return true;
158-
}
159156
#ifdef ENABLE_EXTRA_DIAG
160157
if (seconds > ROLLOVER) {
161158
return true;
@@ -169,9 +166,7 @@ bool rollover() {
169166

170167
void resetStats() {
171168
memset(errorCount, 0, sizeof(errorCount));
172-
errorTcpCount = 0;
173-
errorRtuCount = 0;
174-
errorTimeoutCount = 0;
169+
statsEepromTimer.sleep(0);
175170
#ifdef ENABLE_EXTRA_DIAG
176171
remaining_seconds = -(millis() / 1000);
177172
ethRxCount = 0;
@@ -195,10 +190,10 @@ void generateMac() {
195190

196191

197192
#if MAX_SOCK_NUM == 8
198-
unsigned long lastSocketUse[MAX_SOCK_NUM] = { 0, 0, 0, 0, 0, 0, 0, 0 }; // +rs 03Feb2019 - records last interaction involving each socket to enable detecting sockets unused for longest time period
193+
unsigned long lastSocketUse[MAX_SOCK_NUM] = { 0, 0, 0, 0, 0, 0, 0, 0 };
199194
byte socketInQueue[MAX_SOCK_NUM] = { 0, 0, 0, 0, 0, 0, 0, 0 };
200195
#elif MAX_SOCK_NUM == 4
201-
unsigned long lastSocketUse[MAX_SOCK_NUM] = { 0, 0, 0, 0 }; // +rs 03Feb2019 - records last interaction involving each socket to enable detecting sockets unused for longest time period
196+
unsigned long lastSocketUse[MAX_SOCK_NUM] = { 0, 0, 0, 0 };
202197
byte socketInQueue[MAX_SOCK_NUM] = { 0, 0, 0, 0 };
203198
#endif
204199

@@ -356,7 +351,7 @@ ISR(WDT_vect) {
356351
#elif defined(__MK66FX1M0__)
357352
#define BOARD F("Teensy 3.6")
358353
#else
359-
#error "Unknown board"
354+
#define BOARD F("Unknown Board")
360355
#endif
361356

362357
#else // --------------- Arduino ------------------
@@ -412,7 +407,7 @@ ISR(WDT_vect) {
412407
#elif defined(ARDUINO_ARC32_TOOLS)
413408
#define BOARD F("Arduino 101")
414409
#else
415-
#error "Unknown board"
410+
#define BOARD F("Unknown Board")
416411
#endif
417412

418413
#endif

arduino-modbus-rtu-tcp-gateway/02-modbus-tcp.ino

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,12 @@ byte checkRequest(byte inBuffer[], unsigned int msgLength, const uint32_t remote
152152
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)
153153
if (localConfig.enableRtuOverTcp) { // check CRC for Modbus RTU over TCP/UDP
154154
if (checkCRC(inBuffer, msgLength) == false) {
155-
errorTcpCount++;
155+
errorCount[ERROR_TCP]++;
156156
return 0; // drop request and do not return any error code
157157
}
158158
} else { // check MBAP header structure for Modbus TCP/UDP
159159
if (inBuffer[2] != 0x00 || inBuffer[3] != 0x00 || inBuffer[4] != 0x00 || inBuffer[5] != msgLength - 6) {
160-
errorTcpCount++;
160+
errorCount[ERROR_TCP]++;
161161
return 0; // drop request and do not return any error code
162162
}
163163
}
@@ -220,24 +220,24 @@ void clearQueue() {
220220
scanReqInQueue = false;
221221
priorityReqInQueue = false;
222222
memset(socketInQueue, 0, sizeof(socketInQueue));
223-
memset(stat[SLAVE_ERROR_0B_QUEUE], 0, sizeof(stat[SLAVE_ERROR_0B_QUEUE]));
223+
memset(slaveStatus[SLAVE_ERROR_0B_QUEUE], 0, sizeof(slaveStatus[SLAVE_ERROR_0B_QUEUE]));
224224
sendTimer.sleep(0);
225225
}
226226

227227
bool getSlaveStatus(const uint8_t slave, const byte status) {
228228
if (slave >= MAX_SLAVES) return false; // error
229-
return (stat[status][slave / 8] & masks[slave & 7]) > 0;
229+
return (slaveStatus[status][slave / 8] & masks[slave & 7]) > 0;
230230
}
231231

232232
void setSlaveStatus(const uint8_t slave, byte status, const bool value, const bool isScan) {
233-
if (slave >= MAX_SLAVES) return; // error
233+
if (slave >= MAX_SLAVES || status > SLAVE_ERROR_0B_QUEUE) return; // error
234234
if (value == 0) {
235-
stat[status][slave / 8] &= ~masks[slave & 7];
235+
slaveStatus[status][slave / 8] &= ~masks[slave & 7];
236236
} else {
237-
for (byte i = 0; i < SLAVE_ERROR_LAST; i++) {
238-
stat[i][slave / 8] &= ~masks[slave & 7]; // set all other flags to false
237+
for (byte i = 0; i <= SLAVE_ERROR_0B_QUEUE; i++) {
238+
slaveStatus[i][slave / 8] &= ~masks[slave & 7]; // set all other flags to false, SLAVE_ERROR_0B_QUEUE is the last slave status
239239
}
240-
stat[status][slave / 8] |= masks[slave & 7];
240+
slaveStatus[status][slave / 8] |= masks[slave & 7];
241241
if (status != SLAVE_ERROR_0B_QUEUE && isScan == false) errorCount[status]++; // there is no counter for SLAVE_ERROR_0B_QUEUE, ignor scans in statistics
242242
}
243243
}

arduino-modbus-rtu-tcp-gateway/03-modbus-rtu.ino

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,10 @@ void sendSerial() {
109109
PDU[3] = lowByte(crc); // send CRC, low byte first
110110
PDU[4] = highByte(crc);
111111
sendResponse(MBAP, PDU, 5);
112-
errorTimeoutCount++;
112+
errorCount[ERROR_TIMEOUT]++;
113113
} else {
114114
setSlaveStatus(queueData[0], SLAVE_ERROR_0B_QUEUE, true, false);
115-
errorTimeoutCount++;
115+
errorCount[ERROR_TIMEOUT]++;
116116
} // if (myHeader.atts >= MAX_RETRY)
117117
serialState = 0; // IDLE
118118
}
@@ -130,7 +130,7 @@ void recvSerial() {
130130
if (rxNdx < MODBUS_SIZE) {
131131
serialIn[rxNdx] = b;
132132
rxNdx++;
133-
} // if frame longer than maximum allowed, CRC will fail and errorRtuCount will be recorded down the road
133+
} // if frame longer than maximum allowed, CRC will fail and errorCount[ERROR_RTU] will be recorded down the road
134134
recvTimer.sleep(charTimeOut());
135135
sendTimer.sleep(localConfig.frameDelay * 1000UL); // delay next serial write
136136
}
@@ -155,7 +155,7 @@ void recvSerial() {
155155
sendResponse(MBAP, serialIn, rxNdx);
156156
serialState = IDLE;
157157
} else {
158-
errorRtuCount++;
158+
errorCount[ERROR_RTU]++;
159159
}
160160
#ifdef ENABLE_EXTRA_DIAG
161161
serialRxCount += rxNdx;

arduino-modbus-rtu-tcp-gateway/04-webserver.ino

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -102,26 +102,14 @@ byte requestLen = 0; // Length of the Modbus request sen
102102

103103
// Keys for JSON elements, used in: 1) JSON documents, 2) ID of span tags, 3) Javascript.
104104
enum JSON_type : byte {
105-
JSON_SECS, // Runtime seconds
106-
JSON_MINS, // Runtime minutes
107-
JSON_HOURS, // Runtime hours
108-
JSON_DAYS, // Runtime days
109-
JSON_ERROR, // Modbus status from array errorCount[STAT_ERROR_0B_QUEUE]
110-
JSON_ERROR_1,
111-
JSON_ERROR_2,
112-
JSON_ERROR_3,
113-
JSON_ERROR_TCP,
114-
JSON_ERROR_RTU,
115-
JSON_ERROR_TIMEOUT,
116-
JSON_QUEUE_DATA,
117-
JSON_QUEUE_REQUESTS,
105+
JSON_TIME, // Runtime seconds
106+
JSON_RTU_DATA,
107+
JSON_ETH_DATA,
108+
JSON_RESPONSE,
109+
JSON_STATS, // Modbus statistics from array errorCount[]
110+
JSON_QUEUE,
118111
JSON_TCP_UDP_MASTERS, // list of Modbus TCP/UDP masters separated by <br>
119112
JSON_SLAVES, // list of Modbus RTU slaves separated by <br>
120-
JSON_RTU_TX,
121-
JSON_RTU_RX,
122-
JSON_ETH_TX,
123-
JSON_ETH_RX,
124-
JSON_RESPONSE,
125113
JSON_SOCKETS,
126114
JSON_LAST, // Must be the very last element in this array
127115
};
@@ -362,7 +350,7 @@ void processPost(EthernetClient &client) {
362350
break;
363351
case SCAN:
364352
scanCounter = 1;
365-
memset(&stat, 0, sizeof(stat)); // clear all status flags
353+
memset(&slaveStatus, 0, sizeof(slaveStatus)); // clear all status flags
366354
break;
367355
case CLEAR_REQUEST:
368356
requestLen = 0;
@@ -390,7 +378,7 @@ void processPost(EthernetClient &client) {
390378
// new parameter values received, save them to EEPROM
391379
EEPROM.put(CONFIG_START + 1, localConfig); // it is safe to call, only changed values are updated
392380
#ifdef ENABLE_DHCP
393-
EEPROM.put(CONFIG_START + 1 + sizeof(localConfig), extraConfig);
381+
EEPROM.put(CONFIG_START + 1 + sizeof(localConfig) + sizeof(errorCount), extraConfig);
394382
#endif
395383
}
396384

0 commit comments

Comments
 (0)