From 72e2ec54331ebfbe0d0a1172792f87f7fccf1ea7 Mon Sep 17 00:00:00 2001 From: travis-farmer Date: Sun, 1 Dec 2024 00:40:04 -0500 Subject: [PATCH] IO_Modbus: Trying to improve error recovery --- IO_Modbus.cpp | 21 ++++++++++++--------- IO_Modbus.h | 13 ++++++++----- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/IO_Modbus.cpp b/IO_Modbus.cpp index d1fd185..c13658b 100644 --- a/IO_Modbus.cpp +++ b/IO_Modbus.cpp @@ -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(); diff --git a/IO_Modbus.h b/IO_Modbus.h index 5b08f5c..1a42c16 100644 --- a/IO_Modbus.h +++ b/IO_Modbus.h @@ -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: