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

View File

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