1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2025-01-11 13:21:01 +01:00

Remove blocking behaviour?

This commit is contained in:
travis-farmer 2024-11-30 05:41:29 -05:00
parent 9e5b864055
commit a85fa6d9c2
No known key found for this signature in database
GPG Key ID: 0BC296791D14CB35
2 changed files with 54 additions and 36 deletions

View File

@ -222,9 +222,17 @@ void ModbusRTUComm::setTimeout(unsigned long timeout) {
ModbusRTUCommError ModbusRTUComm::readAdu(ModbusADU& adu) {
adu.setRtuLen(0);
unsigned long startMillis = millis();
while (!_serial.available()) {
if (millis() - startMillis >= _readTimeout) return MODBUS_RTU_COMM_TIMEOUT;
if (!_serial.available()) {
//if (millis() - startMillis >= _readTimeout) return MODBUS_RTU_COMM_TIMEOUT;
_waiting_for_read = true;
if (millis() - startMillis >= _readTimeout) {
return MODBUS_RTU_COMM_TIMEOUT;
} else {
return MODBUS_RTU_COMM_WAITING;
}
}
_waiting_for_read = false;
uint16_t len = 0;
unsigned long startMicros = micros();
do {
@ -323,7 +331,7 @@ ModbusRTUMasterError Modbus::writeMultipleCoils(uint8_t id, uint16_t startAddres
bitClear(adu.data[5 + (i >> 3)], i & 7);
}
adu.setDataLen(5 + byteCount);
_rtuComm.writeAdu(adu);
if (_rtuComm._waiting_for_read == false) _rtuComm.writeAdu(adu);
if (id == 0) return MODBUS_RTU_MASTER_SUCCESS;
ModbusRTUCommError commError = _rtuComm.readAdu(adu);
if (commError) return _translateCommError(commError);
@ -355,7 +363,7 @@ ModbusRTUMasterError Modbus::writeMultipleHoldingRegisters(uint8_t id, uint16_t
adu.setDataRegister(5 + (i * 2), buf[i]);
}
adu.setDataLen(5 + byteCount);
_rtuComm.writeAdu(adu);
if (_rtuComm._waiting_for_read == false) _rtuComm.writeAdu(adu);
if (id == 0) return MODBUS_RTU_MASTER_SUCCESS;
ModbusRTUCommError commError = _rtuComm.readAdu(adu);
if (commError) return _translateCommError(commError);
@ -389,7 +397,7 @@ ModbusRTUMasterError Modbus::_readValues(uint8_t id, uint8_t functionCode, uint1
adu.setDataRegister(0, startAddress);
adu.setDataRegister(2, quantity);
adu.setDataLen(4);
_rtuComm.writeAdu(adu);
if (_rtuComm._waiting_for_read == false) _rtuComm.writeAdu(adu);
ModbusRTUCommError commError = _rtuComm.readAdu(adu);
if (commError) return _translateCommError(commError);
if (adu.getUnitId() != id) return MODBUS_RTU_MASTER_UNEXPECTED_ID;
@ -417,7 +425,7 @@ ModbusRTUMasterError Modbus::_readValues(uint8_t id, uint8_t functionCode, uint1
adu.setDataRegister(0, startAddress);
adu.setDataRegister(2, quantity);
adu.setDataLen(4);
_rtuComm.writeAdu(adu);
if (_rtuComm._waiting_for_read == false) _rtuComm.writeAdu(adu);
ModbusRTUCommError commError = _rtuComm.readAdu(adu);
if (commError) return _translateCommError(commError);
if (adu.getUnitId() != id) return MODBUS_RTU_MASTER_UNEXPECTED_ID;
@ -443,7 +451,7 @@ ModbusRTUMasterError Modbus::_writeSingleValue(uint8_t id, uint8_t functionCode,
adu.setDataRegister(0, address);
adu.setDataRegister(2, value);
adu.setDataLen(4);
_rtuComm.writeAdu(adu);
if (_rtuComm._waiting_for_read == false) _rtuComm.writeAdu(adu);
if (id == 0) return MODBUS_RTU_MASTER_SUCCESS;
ModbusRTUCommError commError = _rtuComm.readAdu(adu);
if (commError) return _translateCommError(commError);
@ -471,6 +479,8 @@ ModbusRTUMasterError Modbus::_translateCommError(ModbusRTUCommError commError) {
return MODBUS_RTU_MASTER_FRAME_ERROR;
case MODBUS_RTU_COMM_CRC_ERROR:
return MODBUS_RTU_MASTER_CRC_ERROR;
case MODBUS_RTU_COMM_WAITING:
return MODBUS_RTU_MASTER_WAITING;
default:
return MODBUS_RTU_MASTER_UNKNOWN_COMM_ERROR;
}
@ -521,31 +531,36 @@ void Modbus::_loop(unsigned long currentMicros) {
#endif
uint8_t error;
// send reads and writes, DIAG on errors other than 0 (Success), or 3 (Invalid Quantity)
error = writeMultipleHoldingRegisters(_currentNode->getNodeID(), 0, (uint16_t*) _currentNode->holdingRegisters, _currentNode->getNumHoldingRegisters());
if (error != 0 && error != 3) DIAG(F("ModbusHR: T%d F%d N%d %s"), _currentNode->getNodeID(), 0, _currentNode->getNumHoldingRegisters(), errorStrings[error]);
#ifdef DIAG_IO
if (error == 0) DIAG(F("ModbusHR: T%d Success!"), _currentNode->getNodeID());
#endif
if (error != 0 && error != 3) flagOK = false;
error = writeMultipleCoils(_currentNode->getNodeID(), 0, (int*) _currentNode->coils, _currentNode->getNumCoils());
if (error != 0 && error != 3) DIAG(F("ModbusMC: T%d F%d N%d %s"), _currentNode->getNodeID(), 0, _currentNode->getNumCoils(), errorStrings[error]);
#ifdef DIAG_IO
if (error == 0) DIAG(F("ModbusMC: T%d Success!"), _currentNode->getNodeID());
#endif
if (error != 0 && error != 3) flagOK = false;
error = readDiscreteInputs(_currentNode->getNodeID(), 0, (int*) _currentNode->discreteInputs, _currentNode->getNumDiscreteInputs());
if (error != 0 && error != 3) DIAG(F("ModbusDI: T%d F%d N%d %s"), _currentNode->getNodeID(), 0, _currentNode->getNumDiscreteInputs(), errorStrings[error]);
#ifdef DIAG_IO
if (error == 0) DIAG(F("ModbusDI: T%d Success!"), _currentNode->getNodeID());
#endif
if (error != 0 && error != 3) flagOK = false;
error = readInputRegisters(_currentNode->getNodeID(), 0, (uint16_t*) _currentNode->inputRegisters, _currentNode->getNumInputRegisters());
if (error != 0 && error != 3) DIAG(F("ModbusIR: T%d F%d N%d %s"), _currentNode->getNodeID(), 0, _currentNode->getNumInputRegisters(), errorStrings[error]);
#ifdef DIAG_IO
if (error == 0) DIAG(F("ModbusIR: T%d Success!"), _currentNode->getNodeID());
#endif
if (error != 0 && error != 3) flagOK = false;
switch (_operationCount) {
case 0:
error = writeMultipleHoldingRegisters(_currentNode->getNodeID(), 0, (uint16_t*) _currentNode->holdingRegisters, _currentNode->getNumHoldingRegisters());
if (error != 0 && error != 3) DIAG(F("ModbusHR: T%d F%d N%d %s"), _currentNode->getNodeID(), 0, _currentNode->getNumHoldingRegisters(), errorStrings[error]);
if (error != 0 && error != 3) flagOK = false;
break;
case 1:
error = writeMultipleCoils(_currentNode->getNodeID(), 0, (int*) _currentNode->coils, _currentNode->getNumCoils());
if (error != 0 && error != 3) DIAG(F("ModbusMC: T%d F%d N%d %s"), _currentNode->getNodeID(), 0, _currentNode->getNumCoils(), errorStrings[error]);
if (error != 0 && error != 3) flagOK = false;
break;
case 2:
error = readDiscreteInputs(_currentNode->getNodeID(), 0, (int*) _currentNode->discreteInputs, _currentNode->getNumDiscreteInputs());
if (error != 0 && error != 3) DIAG(F("ModbusDI: T%d F%d N%d %s"), _currentNode->getNodeID(), 0, _currentNode->getNumDiscreteInputs(), errorStrings[error]);
if (error != 0 && error != 3) flagOK = false;
break;
case 3:
error = readInputRegisters(_currentNode->getNodeID(), 0, (uint16_t*) _currentNode->inputRegisters, _currentNode->getNumInputRegisters());
if (error != 0 && error != 3) DIAG(F("ModbusIR: T%d F%d N%d %s"), _currentNode->getNodeID(), 0, _currentNode->getNumInputRegisters(), errorStrings[error]);
if (error != 0 && error != 3) flagOK = false;
break;
}
if (error != MODBUS_RTU_MASTER_WAITING) {
if (_operationCount < 3) {
_operationCount++;
} else {
_operationCount = 0;
_currentNode = _currentNode->getNext();
}
}
#if defined(MODBUS_STM_OK)
if (flagOK == true) {
ArduinoPins::fastWriteDigital(MODBUS_STM_OK,HIGH);
@ -563,7 +578,7 @@ void Modbus::_loop(unsigned long currentMicros) {
#if defined(MODBUS_STM_COMM)
ArduinoPins::fastWriteDigital(MODBUS_STM_COMM,LOW);
#endif
_currentNode = _currentNode->getNext();
}
// Link to chain of Modbus instances

View File

@ -102,7 +102,8 @@ enum ModbusRTUCommError : uint8_t {
MODBUS_RTU_COMM_SUCCESS = 0,
MODBUS_RTU_COMM_TIMEOUT = 1,
MODBUS_RTU_COMM_FRAME_ERROR = 2,
MODBUS_RTU_COMM_CRC_ERROR = 3
MODBUS_RTU_COMM_CRC_ERROR = 3,
MODBUS_RTU_COMM_WAITING = 4
};
class ModbusRTUComm {
@ -111,6 +112,7 @@ class ModbusRTUComm {
void begin(unsigned long baud, uint32_t config = SERIAL_8N1);
void setTimeout(unsigned long timeout);
ModbusRTUCommError readAdu(ModbusADU& adu);
bool _waiting_for_read = false;
void writeAdu(ModbusADU& adu);
void clearRxBuffer();
Stream& _serial;
@ -140,7 +142,8 @@ enum ModbusRTUMasterError : uint8_t {
MODBUS_RTU_MASTER_UNEXPECTED_BYTE_COUNT = 12,
MODBUS_RTU_MASTER_UNEXPECTED_ADDRESS = 13,
MODBUS_RTU_MASTER_UNEXPECTED_VALUE = 14,
MODBUS_RTU_MASTER_UNEXPECTED_QUANTITY = 15
MODBUS_RTU_MASTER_UNEXPECTED_QUANTITY = 15,
MODBUS_RTU_MASTER_WAITING = 16
};
@ -307,7 +310,7 @@ private:
unsigned long _currentMicros; // last value of micros() from _loop function.
unsigned long _postDelay; // delay time after transmission before switching off transmitter (in us)
unsigned long _byteTransmitTime; // time in us for transmission of one byte
int _operationCount = 0;
static Modbus *_busList; // linked list of defined bus instances
ModbusRTUMasterError _readValues(uint8_t id, uint8_t functionCode, uint16_t startAddress, int buf[], uint16_t quantity);
ModbusRTUMasterError _readValues(uint8_t id, uint8_t functionCode, uint16_t startAddress, uint16_t buf[], uint16_t quantity);