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 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" - ] -} 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" - } -} diff --git a/IO_EXIOExpander.h b/IO_EXIOExpander.h index 0296c93..84433b7 100644 --- a/IO_EXIOExpander.h +++ b/IO_EXIOExpander.h @@ -154,12 +154,30 @@ 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; - _command1Buffer[0] = EXIORDD; - I2CManager.read(_i2cAddress, _digitalInputStates, _digitalPinBytes, _command1Buffer, 1, &_i2crb); - _command1Buffer[0] = EXIORDAN; - I2CManager.read(_i2cAddress, _analogueInputStates, _analoguePinBytes, _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) { + 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 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; + } else { + DIAG(F("EX-IOExpander I2C:%s Error:%d %S"), _I2CAddress.toString(), status, I2CManager.getErrorMessage(status)); + _deviceState = DEVSTATE_FAILED; + } } // Obtain the correct analogue input value @@ -191,9 +209,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); + } } } @@ -211,9 +234,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); + } } } @@ -243,6 +271,11 @@ private: byte _servoBuffer[7]; uint8_t* _analoguePinMap; I2CRB _i2crb; + bool _commandFlag = 1; + unsigned long _lastDigitalRead = 0; + unsigned long _lastAnalogueRead = 0; + 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 { 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