Improve RTU handling

This commit is contained in:
Daniel Öster 2023-02-27 13:12:18 -08:00 committed by GitHub
parent 2f7e5fb1fa
commit 9c694058cb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 819 additions and 822 deletions

View file

@ -11,9 +11,9 @@
#include "Logging.h"
// Constructor takes Serial reference and optional DE/RE pin
ModbusClientRTU::ModbusClientRTU(HardwareSerial& serial, int8_t rtsPin, uint16_t queueLimit) :
ModbusClientRTU::ModbusClientRTU(int8_t rtsPin, uint16_t queueLimit) :
ModbusClient(),
MR_serial(serial),
MR_serial(nullptr),
MR_lastMicros(micros()),
MR_interval(2000),
MR_rtsPin(rtsPin),
@ -33,9 +33,9 @@ ModbusClientRTU::ModbusClientRTU(HardwareSerial& serial, int8_t rtsPin, uint16_t
}
// Alternative constructor takes Serial reference and RTS callback function
ModbusClientRTU::ModbusClientRTU(HardwareSerial& serial, RTScallback rts, uint16_t queueLimit) :
ModbusClientRTU::ModbusClientRTU(RTScallback rts, uint16_t queueLimit) :
ModbusClient(),
MR_serial(serial),
MR_serial(nullptr),
MR_lastMicros(micros()),
MR_interval(2000),
MTRSrts(rts),
@ -53,29 +53,37 @@ ModbusClientRTU::~ModbusClientRTU() {
end();
}
// begin: start worker task
void ModbusClientRTU::begin(int coreID, uint32_t interval) {
// Only start worker if HardwareSerial has been initialized!
if (MR_serial.baudRate()) {
// Pull down RTS toggle, if necessary
MTRSrts(LOW);
// begin: start worker task - general version
void ModbusClientRTU::begin(Stream& serial, uint32_t baudRate, int coreID) {
MR_serial = &serial;
doBegin(baudRate, coreID);
}
// Set minimum interval time
MR_interval = RTUutils::calculateInterval(MR_serial, interval);
// begin: start worker task - HardwareSerial version
void ModbusClientRTU::begin(HardwareSerial& serial, int coreID) {
MR_serial = &serial;
uint32_t baudRate = serial.baudRate();
serial.setRxFIFOFull(1);
doBegin(baudRate, coreID);
}
// Switch serial FIFO buffer copy threshold to 1 byte (normally is 112!)
RTUutils::UARTinit(MR_serial, 1);
void ModbusClientRTU::doBegin(uint32_t baudRate, int coreID) {
// Task already running? End it in case
end();
// Create unique task name
char taskName[18];
snprintf(taskName, 18, "Modbus%02XRTU", instanceCounter);
// Start task to handle the queue
xTaskCreatePinnedToCore((TaskFunction_t)&handleConnection, taskName, 4096, this, 6, &worker, coreID >= 0 ? coreID : NULL);
// Pull down RTS toggle, if necessary
MTRSrts(LOW);
LOG_D("Worker task %d started. Interval=%d\n", (uint32_t)worker, MR_interval);
} else {
LOG_E("Worker task could not be started! HardwareSerial not initialized?\n");
}
// Set minimum interval time
MR_interval = RTUutils::calculateInterval(baudRate);
// Create unique task name
char taskName[18];
snprintf(taskName, 18, "Modbus%02XRTU", instanceCounter);
// Start task to handle the queue
xTaskCreatePinnedToCore((TaskFunction_t)&handleConnection, taskName, 4096, this, 6, &worker, coreID >= 0 ? coreID : NULL);
LOG_D("Client task %d started. Interval=%d\n", (uint32_t)worker, MR_interval);
}
// end: stop worker task
@ -93,7 +101,7 @@ void ModbusClientRTU::end() {
}
// Kill task
vTaskDelete(worker);
LOG_D("Worker task %d killed.\n", (uint32_t)worker);
LOG_D("Client task %d killed.\n", (uint32_t)worker);
}
}
@ -227,7 +235,7 @@ bool ModbusClientRTU::addToQueue(uint32_t token, ModbusMessage request, bool syn
// This was created in begin() to handle the queue entries
void ModbusClientRTU::handleConnection(ModbusClientRTU *instance) {
// initially clean the serial buffer
while (instance->MR_serial.available()) instance->MR_serial.read();
while (instance->MR_serial->available()) instance->MR_serial->read();
delay(100);
// Loop forever - or until task is killed
@ -240,7 +248,7 @@ void ModbusClientRTU::handleConnection(ModbusClientRTU *instance) {
LOG_D("Pulled request from queue\n");
// Send it via Serial
RTUutils::send(instance->MR_serial, instance->MR_lastMicros, instance->MR_interval, instance->MTRSrts, request.msg, instance->MR_useASCII);
RTUutils::send(*(instance->MR_serial), instance->MR_lastMicros, instance->MR_interval, instance->MTRSrts, request.msg, instance->MR_useASCII);
LOG_D("Request sent.\n");
// HEXDUMP_V("Data", request.msg.data(), request.msg.size());
@ -249,7 +257,8 @@ void ModbusClientRTU::handleConnection(ModbusClientRTU *instance) {
if (request.msg.getServerID() != 0 || ((request.token & 0xFF000000) != 0xBC000000)) {
// This is a regular request, Get the response - if any
ModbusMessage response = RTUutils::receive(
instance->MR_serial,
'C',
*(instance->MR_serial),
instance->MR_timeoutValue,
instance->MR_lastMicros,
instance->MR_interval,