From 0cc07ed1dff8afd1d9727bb911bf9e3b957698ed Mon Sep 17 00:00:00 2001 From: peteGSX Date: Mon, 13 Mar 2023 05:29:22 +1000 Subject: [PATCH 01/10] Starting on driver feedback --- IO_EXIOExpander.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/IO_EXIOExpander.h b/IO_EXIOExpander.h index 0296c93..da01ae7 100644 --- a/IO_EXIOExpander.h +++ b/IO_EXIOExpander.h @@ -156,10 +156,15 @@ private: void _loop(unsigned long currentMicros) override { (void)currentMicros; // remove warning if (_deviceState == DEVSTATE_FAILED) return; - _command1Buffer[0] = EXIORDD; - I2CManager.read(_i2cAddress, _digitalInputStates, _digitalPinBytes, _command1Buffer, 1, &_i2crb); - _command1Buffer[0] = EXIORDAN; - I2CManager.read(_i2cAddress, _analogueInputStates, _analoguePinBytes, _command1Buffer, 1, &_i2crb); + if (_i2crb.isBusy()) return; + if (_commandFlag) { + _command1Buffer[0] = EXIORDD; + I2CManager.read(_i2cAddress, _digitalInputStates, _digitalPinBytes, _command1Buffer, 1, &_i2crb); + } else { + _command1Buffer[0] = EXIORDAN; + I2CManager.read(_i2cAddress, _analogueInputStates, _analoguePinBytes, _command1Buffer, 1, &_i2crb); + } + _commandFlag = !_commandFlag; } // Obtain the correct analogue input value @@ -243,6 +248,7 @@ private: byte _servoBuffer[7]; uint8_t* _analoguePinMap; I2CRB _i2crb; + bool _commandFlag = 0; // EX-IOExpander protocol flags enum { From 95d01202045dceda8babb746dfa2015a28aabf7a Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Mon, 13 Mar 2023 08:38:28 +1000 Subject: [PATCH 02/10] Implement status checks --- IO_EXIOExpander.h | 49 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/IO_EXIOExpander.h b/IO_EXIOExpander.h index da01ae7..ddcdf56 100644 --- a/IO_EXIOExpander.h +++ b/IO_EXIOExpander.h @@ -155,16 +155,25 @@ private: // Main loop, collect both digital and analogue pin states continuously (faster sensor/input reads) void _loop(unsigned long currentMicros) override { (void)currentMicros; // remove warning - if (_deviceState == DEVSTATE_FAILED) return; - if (_i2crb.isBusy()) return; - if (_commandFlag) { - _command1Buffer[0] = EXIORDD; - I2CManager.read(_i2cAddress, _digitalInputStates, _digitalPinBytes, _command1Buffer, 1, &_i2crb); + if (_deviceState == DEVSTATE_FAILED) return; // If device failed, return + uint8_t status = _i2crb.status; + if (status == I2C_STATUS_PENDING) return; // If device busy, return + if (status == I2C_STATUS_OK) { // If device ok, read input data + if (_commandFlag) { + _command1Buffer[0] = EXIORDD; + I2CManager.read(_i2cAddress, _digitalInputStates, _digitalPinBytes, _command1Buffer, 1, &_i2crb); + } else { + _command1Buffer[0] = EXIORDAN; + byte _tempAnalogue[_analoguePinBytes]; // Setup temp buffer so reads come from known state + I2CManager.read(_i2cAddress, _tempAnalogue, _analoguePinBytes, _command1Buffer, 1, &_i2crb); + memcpy(_analogueInputStates, _tempAnalogue, _analoguePinBytes); // Copy temp buffer to states + } + _commandFlag = !_commandFlag; + // Need to delay here: digital in IO_Base 4000UL, analogue in IO_AnalogueInputs 10000UL (fast) or 1000000UL(slow) } else { - _command1Buffer[0] = EXIORDAN; - I2CManager.read(_i2cAddress, _analogueInputStates, _analoguePinBytes, _command1Buffer, 1, &_i2crb); + DIAG(F("EX-IOExpander I2C:%s Error:%d %S"), _I2CAddress.toString(), status, I2CManager.getErrorMessage(status)); + _deviceState = DEVSTATE_FAILED; } - _commandFlag = !_commandFlag; } // Obtain the correct analogue input value @@ -196,9 +205,14 @@ private: _digitalOutBuffer[0] = EXIOWRD; _digitalOutBuffer[1] = pin; _digitalOutBuffer[2] = value; - I2CManager.read(_i2cAddress, _command1Buffer, 1, _digitalOutBuffer, 3, &_i2crb); - if (_command1Buffer[0] != EXIORDY) { - DIAG(F("Vpin %d cannot be used as a digital output pin"), (int)vpin); + uint8_t status = I2CManager.read(_i2cAddress, _command1Buffer, 1, _digitalOutBuffer, 3); + if (status != I2C_STATUS_OK) { + DIAG(F("EX-IOExpander I2C:%s Error:%d %S"), _I2CAddress.toString(), status, I2CManager.getErrorMessage(status)); + _deviceState = DEVSTATE_FAILED; + } else { + if (_command1Buffer[0] != EXIORDY) { + DIAG(F("Vpin %d cannot be used as a digital output pin"), (int)vpin); + } } } @@ -216,9 +230,14 @@ private: _servoBuffer[4] = profile; _servoBuffer[5] = duration & 0xFF; _servoBuffer[6] = duration >> 8; - I2CManager.read(_i2cAddress, _command1Buffer, 1, _servoBuffer, 7, &_i2crb); - if (_command1Buffer[0] != EXIORDY) { - DIAG(F("Vpin %d cannot be used as a servo/PWM pin"), (int)vpin); + uint8_t status = I2CManager.read(_i2cAddress, _command1Buffer, 1, _servoBuffer, 7); + if (status != I2C_STATUS_OK) { + DIAG(F("EX-IOExpander I2C:%s Error:%d %S"), _I2CAddress.toString(), status, I2CManager.getErrorMessage(status)); + _deviceState = DEVSTATE_FAILED; + } else { + if (_command1Buffer[0] != EXIORDY) { + DIAG(F("Vpin %d cannot be used as a servo/PWM pin"), (int)vpin); + } } } @@ -248,7 +267,7 @@ private: byte _servoBuffer[7]; uint8_t* _analoguePinMap; I2CRB _i2crb; - bool _commandFlag = 0; + bool _commandFlag = 1; // EX-IOExpander protocol flags enum { From df3eb11eb9e0d0f721c22937b03af6c9f0cb4d11 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Tue, 14 Mar 2023 07:19:20 +1000 Subject: [PATCH 03/10] Add read refresh delays --- .vscode/settings.json | 3 ++- IO_EXIOExpander.h | 23 ++++++++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index ffa498a..6f7d828 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,5 +8,6 @@ "string_view": "cpp", "initializer_list": "cpp", "cstdint": "cpp" - } + }, + "cmake.configureOnOpen": false } diff --git a/IO_EXIOExpander.h b/IO_EXIOExpander.h index ddcdf56..9efe8f9 100644 --- a/IO_EXIOExpander.h +++ b/IO_EXIOExpander.h @@ -154,19 +154,24 @@ private: // Main loop, collect both digital and analogue pin states continuously (faster sensor/input reads) void _loop(unsigned long currentMicros) override { - (void)currentMicros; // remove warning if (_deviceState == DEVSTATE_FAILED) return; // If device failed, return uint8_t status = _i2crb.status; if (status == I2C_STATUS_PENDING) return; // If device busy, return if (status == I2C_STATUS_OK) { // If device ok, read input data if (_commandFlag) { - _command1Buffer[0] = EXIORDD; - I2CManager.read(_i2cAddress, _digitalInputStates, _digitalPinBytes, _command1Buffer, 1, &_i2crb); + if (currentMicros - _lastDigitalRead > _digitalRefresh) { // Delay 10ms for digital read refresh + _lastDigitalRead = currentMicros; + _command1Buffer[0] = EXIORDD; + I2CManager.read(_i2cAddress, _digitalInputStates, _digitalPinBytes, _command1Buffer, 1, &_i2crb); + } } else { - _command1Buffer[0] = EXIORDAN; - byte _tempAnalogue[_analoguePinBytes]; // Setup temp buffer so reads come from known state - I2CManager.read(_i2cAddress, _tempAnalogue, _analoguePinBytes, _command1Buffer, 1, &_i2crb); - memcpy(_analogueInputStates, _tempAnalogue, _analoguePinBytes); // Copy temp buffer to states + if (currentMicros - _lastAnalogueRead > _analogueRefresh) { // Delay 50ms for analogue read refresh + _lastAnalogueRead = currentMicros; + _command1Buffer[0] = EXIORDAN; + byte _tempAnalogue[_analoguePinBytes]; // Setup temp buffer so reads come from known state + I2CManager.read(_i2cAddress, _tempAnalogue, _analoguePinBytes, _command1Buffer, 1, &_i2crb); + memcpy(_analogueInputStates, _tempAnalogue, _analoguePinBytes); // Copy temp buffer to states + } } _commandFlag = !_commandFlag; // Need to delay here: digital in IO_Base 4000UL, analogue in IO_AnalogueInputs 10000UL (fast) or 1000000UL(slow) @@ -268,6 +273,10 @@ private: uint8_t* _analoguePinMap; I2CRB _i2crb; bool _commandFlag = 1; + unsigned long _lastDigitalRead = 0; + unsigned long _lastAnalogueRead = 0; + const unsigned long _digitalRefresh = 10000UL; + const unsigned long _analogueRefresh = 50000UL; // EX-IOExpander protocol flags enum { From c83741d2b4a29e1dfa71dfb7184a617b1e270eec Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Tue, 14 Mar 2023 07:20:27 +1000 Subject: [PATCH 04/10] Add read refresh delays --- IO_EXIOExpander.h | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/IO_EXIOExpander.h b/IO_EXIOExpander.h index ddcdf56..9efe8f9 100644 --- a/IO_EXIOExpander.h +++ b/IO_EXIOExpander.h @@ -154,19 +154,24 @@ private: // Main loop, collect both digital and analogue pin states continuously (faster sensor/input reads) void _loop(unsigned long currentMicros) override { - (void)currentMicros; // remove warning if (_deviceState == DEVSTATE_FAILED) return; // If device failed, return uint8_t status = _i2crb.status; if (status == I2C_STATUS_PENDING) return; // If device busy, return if (status == I2C_STATUS_OK) { // If device ok, read input data if (_commandFlag) { - _command1Buffer[0] = EXIORDD; - I2CManager.read(_i2cAddress, _digitalInputStates, _digitalPinBytes, _command1Buffer, 1, &_i2crb); + if (currentMicros - _lastDigitalRead > _digitalRefresh) { // Delay 10ms for digital read refresh + _lastDigitalRead = currentMicros; + _command1Buffer[0] = EXIORDD; + I2CManager.read(_i2cAddress, _digitalInputStates, _digitalPinBytes, _command1Buffer, 1, &_i2crb); + } } else { - _command1Buffer[0] = EXIORDAN; - byte _tempAnalogue[_analoguePinBytes]; // Setup temp buffer so reads come from known state - I2CManager.read(_i2cAddress, _tempAnalogue, _analoguePinBytes, _command1Buffer, 1, &_i2crb); - memcpy(_analogueInputStates, _tempAnalogue, _analoguePinBytes); // Copy temp buffer to states + if (currentMicros - _lastAnalogueRead > _analogueRefresh) { // Delay 50ms for analogue read refresh + _lastAnalogueRead = currentMicros; + _command1Buffer[0] = EXIORDAN; + byte _tempAnalogue[_analoguePinBytes]; // Setup temp buffer so reads come from known state + I2CManager.read(_i2cAddress, _tempAnalogue, _analoguePinBytes, _command1Buffer, 1, &_i2crb); + memcpy(_analogueInputStates, _tempAnalogue, _analoguePinBytes); // Copy temp buffer to states + } } _commandFlag = !_commandFlag; // Need to delay here: digital in IO_Base 4000UL, analogue in IO_AnalogueInputs 10000UL (fast) or 1000000UL(slow) @@ -268,6 +273,10 @@ private: uint8_t* _analoguePinMap; I2CRB _i2crb; bool _commandFlag = 1; + unsigned long _lastDigitalRead = 0; + unsigned long _lastAnalogueRead = 0; + const unsigned long _digitalRefresh = 10000UL; + const unsigned long _analogueRefresh = 50000UL; // EX-IOExpander protocol flags enum { From ca2e5e6ce3c956af843357e4dd594c175089a5c4 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Tue, 14 Mar 2023 07:21:55 +1000 Subject: [PATCH 05/10] Undo vscode change --- .vscode/settings.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 6f7d828..ffa498a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,6 +8,5 @@ "string_view": "cpp", "initializer_list": "cpp", "cstdint": "cpp" - }, - "cmake.configureOnOpen": false + } } From 5fc925bfc6d6431f90a072219e2d14e3dcd56979 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Tue, 14 Mar 2023 07:23:42 +1000 Subject: [PATCH 06/10] Delete extensions.json --- .vscode/extensions.json | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 .vscode/extensions.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 080e70d..0000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - // See http://go.microsoft.com/fwlink/?LinkId=827846 - // for the documentation about the extensions.json format - "recommendations": [ - "platformio.platformio-ide" - ], - "unwantedRecommendations": [ - "ms-vscode.cpptools-extension-pack" - ] -} From a51cefbdeb60d1bdabebfa234f1c5378878b0760 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Tue, 14 Mar 2023 07:23:55 +1000 Subject: [PATCH 07/10] Delete settings.json --- .vscode/settings.json | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index ffa498a..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "files.associations": { - "array": "cpp", - "deque": "cpp", - "string": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "string_view": "cpp", - "initializer_list": "cpp", - "cstdint": "cpp" - } -} From 42bddb587ed7500de89eb37110c68cf03695c70a Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Tue, 14 Mar 2023 07:25:30 +1000 Subject: [PATCH 08/10] Update .gitignore --- .gitignore | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.gitignore b/.gitignore index 8f01818..6237359 100644 --- a/.gitignore +++ b/.gitignore @@ -7,16 +7,9 @@ Release/* .pio/ .vscode/ config.h -.vscode/* -# mySetup.h mySetup.cpp myHal.cpp -# myAutomation.h myFilter.cpp -# myAutomation.h -# myLayout.h my*.h !my*.example.h -.vscode/extensions.json -.vscode/extensions.json compile_commands.json From 25676aab6b50a480807f7339672a4853245129ea Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Tue, 14 Mar 2023 07:32:08 +1000 Subject: [PATCH 09/10] Update comments --- IO_EXIOExpander.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/IO_EXIOExpander.h b/IO_EXIOExpander.h index 9efe8f9..84433b7 100644 --- a/IO_EXIOExpander.h +++ b/IO_EXIOExpander.h @@ -159,13 +159,13 @@ private: if (status == I2C_STATUS_PENDING) return; // If device busy, return if (status == I2C_STATUS_OK) { // If device ok, read input data if (_commandFlag) { - if (currentMicros - _lastDigitalRead > _digitalRefresh) { // Delay 10ms for digital read refresh + if (currentMicros - _lastDigitalRead > _digitalRefresh) { // Delay for digital read refresh _lastDigitalRead = currentMicros; _command1Buffer[0] = EXIORDD; I2CManager.read(_i2cAddress, _digitalInputStates, _digitalPinBytes, _command1Buffer, 1, &_i2crb); } } else { - if (currentMicros - _lastAnalogueRead > _analogueRefresh) { // Delay 50ms for analogue read refresh + if (currentMicros - _lastAnalogueRead > _analogueRefresh) { // Delay for analogue read refresh _lastAnalogueRead = currentMicros; _command1Buffer[0] = EXIORDAN; byte _tempAnalogue[_analoguePinBytes]; // Setup temp buffer so reads come from known state @@ -174,7 +174,6 @@ private: } } _commandFlag = !_commandFlag; - // Need to delay here: digital in IO_Base 4000UL, analogue in IO_AnalogueInputs 10000UL (fast) or 1000000UL(slow) } else { DIAG(F("EX-IOExpander I2C:%s Error:%d %S"), _I2CAddress.toString(), status, I2CManager.getErrorMessage(status)); _deviceState = DEVSTATE_FAILED; @@ -275,8 +274,8 @@ private: bool _commandFlag = 1; unsigned long _lastDigitalRead = 0; unsigned long _lastAnalogueRead = 0; - const unsigned long _digitalRefresh = 10000UL; - const unsigned long _analogueRefresh = 50000UL; + const unsigned long _digitalRefresh = 10000UL; // Delay refreshing digital inputs for 10ms + const unsigned long _analogueRefresh = 50000UL; // Delay refreshing analogue inputs for 50ms // EX-IOExpander protocol flags enum { From 48cd567bda87482d7e5e5287d9290ca0c96a98eb Mon Sep 17 00:00:00 2001 From: peteGSX Date: Tue, 14 Mar 2023 19:04:08 +1000 Subject: [PATCH 10/10] Update version after testing --- version.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/version.h b/version.h index 8afe38a..21f8e5e 100644 --- a/version.h +++ b/version.h @@ -4,7 +4,11 @@ #include "StringFormatter.h" -#define VERSION "4.2.25" +#define VERSION "4.2.26" +// 4.2.26 - EX-IOExpander device driver enhancements +// - Enhance I2C error checking +// - Introduce delays to _loop to allow room for other I2C device comms +// - Improve analogue read reliability // 4.2.25 - Bugfix SAMD21 Exrail odd byte boundary // 4.2.24 - Bugfix Ethernet shield: Static IP now possible // 4.2.23 - Bugfix signalpin2 was not set up in shadow port