1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2025-01-28 21:23:06 +01:00

IO_Modbus: Trying to improve error recovery

This commit is contained in:
travis-farmer 2024-12-01 00:40:04 -05:00
parent f1217bf92f
commit 72e2ec5433
No known key found for this signature in database
GPG Key ID: 0BC296791D14CB35
2 changed files with 20 additions and 14 deletions

View File

@ -222,10 +222,11 @@ void ModbusRTUComm::setTimeout(unsigned long timeout) {
ModbusRTUCommError ModbusRTUComm::readAdu(ModbusADU& adu) { ModbusRTUCommError ModbusRTUComm::readAdu(ModbusADU& adu) {
adu.setRtuLen(0); adu.setRtuLen(0);
unsigned long startMillis = millis(); unsigned long startMillis = millis();
if (_startTimeout == 0UL) _startTimeout = startMillis;
if (!_serial.available()) { if (!_serial.available()) {
//if (millis() - startMillis >= _readTimeout) return MODBUS_RTU_COMM_TIMEOUT; //if (millis() - startMillis >= _readTimeout) return MODBUS_RTU_COMM_TIMEOUT;
_waiting_for_read = true; _waiting_for_read = true;
if (millis() - startMillis >= _readTimeout) { if (millis() - _startTimeout >= _readTimeout) {
//_serial.flush(); //_serial.flush();
return MODBUS_RTU_COMM_TIMEOUT; return MODBUS_RTU_COMM_TIMEOUT;
} else { } else {
@ -234,6 +235,7 @@ ModbusRTUCommError ModbusRTUComm::readAdu(ModbusADU& adu) {
} }
_waiting_for_read = false; _waiting_for_read = false;
_startTimeout = 0UL;
uint16_t len = 0; uint16_t len = 0;
unsigned long startMicros = micros(); unsigned long startMicros = micros();
do { do {
@ -493,14 +495,15 @@ ModbusRTUMasterError Modbus::_translateCommError(ModbusRTUCommError commError) {
// Constructor for Modbus // Constructor for Modbus
Modbus::Modbus(uint8_t busNo, HardwareSerial &serial, unsigned long baud, uint16_t cycleTimeMS, int8_t txPin) : _rtuComm(serial, txPin) { Modbus::Modbus(uint8_t busNo, HardwareSerial &serial, unsigned long baud, uint16_t cycleTimeMS, int8_t txPin, int waitA, int waitB) : _rtuComm(serial, txPin) {
_baud = baud; _baud = baud;
_serialD = &serial; _serialD = &serial;
_txPin = txPin; _txPin = txPin;
_rtuComm.setTimeout(500); _rtuComm.setTimeout(500);
_busNo = busNo; _busNo = busNo;
_cycleTime = cycleTimeMS * 1000UL; // convert from milliseconds to microseconds. _cycleTime = cycleTimeMS * 1000UL; // convert from milliseconds to microseconds.
_waitA = waitA;
_waitB = waitB;
// Add device to HAL device chain // Add device to HAL device chain
IODevice::addDevice(this); IODevice::addDevice(this);
@ -555,14 +558,14 @@ void Modbus::_loop(unsigned long currentMicros) {
break; break;
} }
if (error == MODBUS_RTU_MASTER_WAITING) { if (error == MODBUS_RTU_MASTER_WAITING) {
if (_waitCounter > 10) { // retry after 10 cycles of waiting. if (_waitCounter > _waitA) { // retry after 10 cycles of waiting, or user setting waitA.
_resetWaiting(); _resetWaiting(); // reset Waiting flag so it retries.
_waitCounter = 0; _waitCounter = 0;
_waitCounterB++; _waitCounterB++;
} else { } else {
_waitCounter++; _waitCounter++;
} }
if (_waitCounterB > 10) { // move on to next node if fails 10 times. if (_waitCounterB > _waitB) { // move on to next node if fails 10 times, or user setting waitB.
_waitCounter = 0; _waitCounter = 0;
_waitCounterB = 0; _waitCounterB = 0;
_operationCount = 0; _operationCount = 0;
@ -573,9 +576,9 @@ void Modbus::_loop(unsigned long currentMicros) {
_waitCounterB = 0; _waitCounterB = 0;
} }
if (error != MODBUS_RTU_MASTER_WAITING) { if (error == MODBUS_RTU_MASTER_SUCCESS) { // should have the effect of retrying same opperation until success
if (_operationCount < 3) { if (_operationCount < 3) { // unless it fails waitB and moves on to next node. may even
_operationCount++; _operationCount++; // improve error recovery...
} else { } else {
_operationCount = 0; _operationCount = 0;
_currentNode = _currentNode->getNext(); _currentNode = _currentNode->getNext();

View File

@ -122,8 +122,9 @@ class ModbusRTUComm {
unsigned long _charTimeout; unsigned long _charTimeout;
unsigned long _frameTimeout; unsigned long _frameTimeout;
unsigned long _postDelay = 0; unsigned long _postDelay = 0UL;
unsigned long _readTimeout = 0; unsigned long _readTimeout = 0UL;
unsigned long _startTimeout = 0UL;
}; };
enum ModbusRTUMasterError : uint8_t { enum ModbusRTUMasterError : uint8_t {
@ -317,13 +318,15 @@ private:
ModbusRTUMasterError _writeSingleValue(uint8_t id, uint8_t functionCode, uint16_t address, uint16_t value); ModbusRTUMasterError _writeSingleValue(uint8_t id, uint8_t functionCode, uint16_t address, uint16_t value);
int _waitCounter = 0; int _waitCounter = 0;
int _waitCounterB = 0; int _waitCounterB = 0;
int _waitA;
int _waitB;
void _resetWaiting() { void _resetWaiting() {
_rtuComm._waiting_for_read = false; _rtuComm._waiting_for_read = false;
} }
public: public:
static void create(uint8_t busNo, HardwareSerial& serial, unsigned long baud, uint16_t cycleTimeMS=500, int8_t txPin=-1) { static void create(uint8_t busNo, HardwareSerial& serial, unsigned long baud, uint16_t cycleTimeMS=500, int8_t txPin=-1, int waitA=10, int waitB=10) {
new Modbus(busNo, serial, baud, cycleTimeMS, txPin); new Modbus(busNo, serial, baud, cycleTimeMS, txPin, waitA, waitB);
} }
HardwareSerial *_serialD; HardwareSerial *_serialD;
ModbusRTUComm _rtuComm; ModbusRTUComm _rtuComm;
@ -388,7 +391,7 @@ public:
} }
protected: protected:
Modbus(uint8_t busNo, HardwareSerial &serial, unsigned long baud, uint16_t cycleTimeMS, int8_t txPin); Modbus(uint8_t busNo, HardwareSerial &serial, unsigned long baud, uint16_t cycleTimeMS, int8_t txPin, int waitA, int waitB);
public: public: