diff --git a/IO_Modbus.cpp b/IO_Modbus.cpp index 490992a..c7fd24c 100644 --- a/IO_Modbus.cpp +++ b/IO_Modbus.cpp @@ -211,14 +211,110 @@ void Modbus::_loop(unsigned long currentMicros) { if (_currentMicros - _cycleStartTime < _cycleTime) return; _cycleStartTime = _currentMicros; if (_currentNode == NULL) return; - const char* errorStrings[16] = { "success", "invalid id", "invalid buffer", "invalid quantity", "response timeout", "frame error", "crc error", "unknown comm error", "unexpected id", "exception response", "unexpected function code", "unexpected response length", "unexpected byte count", "unexpected address", "unexpected value", "unexpected quantity" }; - + bool flagOK = true; #if defined(MODBUS_STM_COMM) ArduinoPins::fastWriteDigital(MODBUS_STM_COMM,HIGH); #endif +if (taskCnt > 0) { + // run through tasks + int* taskData[25]; + getNextTask(taskData); + switch((int) taskData[0]) { + case 0: + // protection for pulling empty task + break; + case 1: // configure pin + if (taskData[4] == (int*) CONFIGURE_INPUT) { + uint8_t pullup = (uint8_t) taskData[6]; + uint8_t outBuffer[6] = {EXIODPUP, (uint8_t) taskData[0], (uint8_t)taskData[3], pullup}; + uint8_t responseBuffer[3]; + updateCrc(outBuffer,sizeof(outBuffer)-2); + if (_txPin != VPIN_NONE) ArduinoPins::fastWriteDigital(_txPin, HIGH); + _serialD->write(outBuffer, sizeof(outBuffer)); + _serialD->flush(); + if (_txPin != VPIN_NONE) ArduinoPins::fastWriteDigital(_txPin, LOW); + unsigned long startMillis = millis(); + if (!_serialD->available()) { + if (waitReceive == true && _waitCounter > _waitA) { + } + if (millis() - startMillis >= 500) return; + } + uint16_t len = 0; + unsigned long startMicros = micros(); + do { + if (_serialD->available()) { + startMicros = micros(); + responseBuffer[len] = _serialD->read(); + len++; + } + } while (micros() - startMicros <= 500 && len < 256); + if (crcGood(responseBuffer,sizeof(responseBuffer)-2)) { + if (responseBuffer[0] == EXIORDY) { + } else { + DIAG(F("EXIOMB Vpin %u cannot be used as a digital input pin"), (int)taskData[2]); + } + } + } else if (taskData[3] == (int*) CONFIGURE_ANALOGINPUT) { + // TODO: Consider moving code from _configureAnalogIn() to here and remove _configureAnalogIn + // from IODevice class definition. Not urgent, but each virtual function defined + // means increasing the RAM requirement of every HAL device driver, whether it's relevant + // to the driver or not. + } + break; + case 2: // configure analog in + uint8_t commandBuffer[5] = {EXIOENAN, (uint8_t) taskData[0], (uint8_t) taskData[3]}; + uint8_t responseBuffer[3]; + updateCrc(commandBuffer,sizeof(commandBuffer)-2); + if (_txPin != VPIN_NONE) ArduinoPins::fastWriteDigital(_txPin, HIGH); + _serialD->write(commandBuffer, sizeof(commandBuffer)); + _serialD->flush(); + if (_txPin != VPIN_NONE) ArduinoPins::fastWriteDigital(_txPin, LOW); + unsigned long startMillis = millis(); + if (!_serialD->available()) { + if (waitReceive == true && _waitCounter > _waitA) { + + } + if (millis() - startMillis >= 500) return; + } + uint16_t len = 0; + unsigned long startMicros = micros(); + do { + if (_serialD->available()) { + startMicros = micros(); + responseBuffer[len] = _serialD->read(); + len++; + } + } while (micros() - startMicros <= 500 && len < 256); + + if (crcGood(responseBuffer,sizeof(responseBuffer)-2)) { + if (responseBuffer[0] != EXIORDY) { + DIAG(F("EX-IOExpanderMB: Vpin %u on node %d cannot be used as an analogue input pin"), (int) taskData[2], (int) taskData[0]); + } + } + break; + case 3: // write pin + uint8_t digitalOutBuffer[6]; + uint8_t responseBuffer[3]; + digitalOutBuffer[0] = EXIOWRD; + digitalOutBuffer[1] = (uint8_t) taskData[0]; + digitalOutBuffer[2] = (uint8_t) taskData[3]; + digitalOutBuffer[3] = value; + uint8_t status = I2CManager.read(_I2CAddress, responseBuffer, 1, digitalOutBuffer, 3); + if (status != I2C_STATUS_OK) { + reportError(status); + } else { + if (responseBuffer[0] != EXIORDY) { + DIAG(F("Vpin %u cannot be used as a digital output pin"), (int)vpin); + } + } + } +} else { + // receive states + +} if (error == MODBUS_RTU_MASTER_WAITING) { if (_waitCounter > _waitA) { // retry after 10 cycles of waiting, or user setting waitA. diff --git a/IO_Modbus.h b/IO_Modbus.h index d3a4da7..790767d 100644 --- a/IO_Modbus.h +++ b/IO_Modbus.h @@ -53,7 +53,6 @@ #define IO_MODBUS_H #include "IODevice.h" -#include uint16_t div8RndUp(uint16_t value); @@ -298,7 +297,7 @@ public: } uint8_t receiveBuffer[5]; uint8_t commandBuffer[7] = {EXIOINIT, _nodeID, (uint8_t)_nPins, (uint8_t)(_firstVpin & 0xFF), (uint8_t)(_firstVpin >> 8)}; - mb->updateCrc(commandBuffer,sizeof(commandBuffer)); + mb->updateCrc(commandBuffer,sizeof(commandBuffer)-2); if (mb->_txPin != VPIN_NONE) ArduinoPins::fastWriteDigital(mb->_txPin, HIGH); mb->_serialD->write(commandBuffer, sizeof(commandBuffer)); mb->_serialD->flush(); @@ -367,7 +366,7 @@ public: return; } commandBuffer[0] = EXIOINITA; - mb->updateCrc(commandBuffer,sizeof(commandBuffer)); + mb->updateCrc(commandBuffer,sizeof(commandBuffer)-2); if (mb->_txPin != VPIN_NONE) ArduinoPins::fastWriteDigital(mb->_txPin, HIGH); mb->_serialD->write(commandBuffer, sizeof(commandBuffer)); mb->_serialD->flush(); @@ -392,7 +391,7 @@ public: } uint8_t versionBuffer[5]; commandBuffer[0] = EXIOVER; - mb->updateCrc(commandBuffer,sizeof(commandBuffer)); + mb->updateCrc(commandBuffer,sizeof(commandBuffer)-2); if (mb->_txPin != VPIN_NONE) ArduinoPins::fastWriteDigital(mb->_txPin, HIGH); mb->_serialD->write(commandBuffer, sizeof(commandBuffer)); mb->_serialD->flush(); @@ -551,7 +550,7 @@ private: int _operationCount = 0; static Modbus *_busList; // linked list of defined bus instances - + bool waitReceive = false; int _waitCounter = 0; int _waitCounterB = 0; int _waitA; @@ -590,26 +589,62 @@ private: EXIOERR = 0xEF, // Flag we've received an error }; int tasks[255][25]; - int taskCnt = 0; + + void _moveTasks() { + // used one in lead, so move forward + for (int i = 0; i < taskCnt-1; i++) { + for (int j = 0; j < 25; j++) { + tasks[i][j] = tasks[i+1][j+1]; + } + } + taskCnt--; + } public: - void addTask(int taskNum, int paranCnt, int *param[]) { - tasks[taskCnt][0] = taskNum; + int taskCnt = 0; + void addTask(int nodeID, int taskNum, int paramCnt, int *param[]) { + taskCnt++; + tasks[taskCnt][0] = nodeID; + tasks[taskCnt][1] = taskNum; + tasks[taskCnt][2] = paramCnt; switch(taskNum) { - case 0: // configure pin - tasks[taskNum][1] = param[0]; // pin - tasks[taskNum][2] = param[1]; // configtype - tasks[taskNum][3] = param[2]; // paramcount - for (int i=0; i < param[2]; i++) { - tasks[taskNum][i+4] = param[i+3]; // params + case 0: + // empty task + case 1: // configure pin + tasks[taskCnt][3] = (int) param[0]; // pin + tasks[taskCnt][4] = (int) param[1]; // configtype + tasks[taskCnt][5] = (int) param[2]; // paramcount + for (int i=0; i < (int) param[2]; i++) { + tasks[taskCnt][i+6] = (int) param[i+3]; // params } break; - case 1: // configure analog in - tasks[taskNum][1] = param[0]; // pin + case 2: // configure analog in + tasks[taskCnt][3] = (int) param[0]; // pin + break; + case 3: // write pin + tasks[taskCnt][3] = (int) param[0]; // pin + tasks[taskCnt][4] = (int) param[1]; // value + break; + case 4: // write analog + tasks[taskCnt][3] = (int) param[0]; // pin + tasks[taskCnt][4] = (int) param[1]; // value + tasks[taskCnt][5] = (int) param[2]; // profile + tasks[taskCnt][6] = (int) param[3]; // duration break; - - } } + + int getNextTask(int *buf[]) { + int paramCnt = 0; + for (int i = 0; i < 25; i++) { + if (i == 0) buf[i] = (int*) tasks[0][i]; // NodeID + if (i == 1) buf[i] = (int*) tasks[0][i]; // tasknum + else if (i == 2) paramCnt = tasks[0][i]; // paramcnt + else { + buf[i-1] = (int*) tasks[0][i]; + } + } + _moveTasks(); + } int8_t _txPin; uint8_t *rtu = _adu + 6;