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:
parent
f1217bf92f
commit
72e2ec5433
@ -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();
|
||||||
|
13
IO_Modbus.h
13
IO_Modbus.h
@ -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:
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user