diff --git a/examples/RTU/ModbusRTUClientParameters/ModbusRTUClientParameters.ino b/examples/RTU/ModbusRTUClientParameters/ModbusRTUClientParameters.ino index 91b9ec4..ec30e0d 100644 --- a/examples/RTU/ModbusRTUClientParameters/ModbusRTUClientParameters.ino +++ b/examples/RTU/ModbusRTUClientParameters/ModbusRTUClientParameters.ino @@ -16,24 +16,12 @@ constexpr auto baudrate { 19200 }; -// Calculate preDelay and postDelay in microseconds as per Modbus RTU Specification -// -// MODBUS over serial line specification and implementation guide V1.02 -// Paragraph 2.5.1.1 MODBUS Message RTU Framing -// https://modbus.org/docs/Modbus_over_serial_line_V1_02.pdf -constexpr auto bitduration { 1.f / baudrate }; -constexpr auto wordlen { 9.6f }; // try also with 10.0f -constexpr auto preDelayBR { bitduration * wordlen * 3.5f * 1e6 }; -constexpr auto postDelayBR { bitduration * wordlen * 3.5f * 1e6 }; - void setup() { Serial.begin(9600); while (!Serial); Serial.println("Modbus RTU Client Toggle w/ Parameters"); - RS485.setDelays(preDelayBR, postDelayBR); - // start the Modbus RTU client in 8E1 mode if (!ModbusRTUClient.begin(baudrate, SERIAL_8E1)) { Serial.println("Failed to start Modbus RTU Client!"); diff --git a/keywords.txt b/keywords.txt index 845bdb3..b30c910 100644 --- a/keywords.txt +++ b/keywords.txt @@ -7,6 +7,7 @@ ####################################### ArduinoModbus KEYWORD1 +ModbusRTUDelay KEYWORD1 ModbusRTUClient KEYWORD1 ModbusRTUServer KEYWORD1 ModbusRTUClient KEYWORD1 @@ -21,6 +22,9 @@ poll KEYWORD2 end KEYWORD2 setTimeout KEYWORD2 +preDelay KEYWORD2 +postDelay KEYWORD2 + beginTransmission KEYWORD2 write KEYWORD2 endTransmission KEYWORD2 diff --git a/src/ModbusRTUClient.cpp b/src/ModbusRTUClient.cpp index 2b35227..9e31a27 100644 --- a/src/ModbusRTUClient.cpp +++ b/src/ModbusRTUClient.cpp @@ -26,6 +26,8 @@ extern "C" { #include "ModbusRTUClient.h" +#include "ModbusRTUDelay.h" + ModbusRTUClientClass::ModbusRTUClientClass() : ModbusClient(1000) { @@ -42,6 +44,8 @@ ModbusRTUClientClass::~ModbusRTUClientClass() int ModbusRTUClientClass::begin(unsigned long baudrate, uint16_t config) { + _rs485->setDelays(ModbusRTUDelay::preDelay(baudrate), ModbusRTUDelay::postDelay(baudrate)); + modbus_t* mb = modbus_new_rtu(_rs485, baudrate, config); if (!ModbusClient::begin(mb, 0x00)) { diff --git a/src/ModbusRTUDelay.h b/src/ModbusRTUDelay.h new file mode 100644 index 0000000..929e287 --- /dev/null +++ b/src/ModbusRTUDelay.h @@ -0,0 +1,50 @@ +/* + This file is part of the ArduinoModbus library. + Copyright (c) 2018 Arduino SA. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _MODBUS_RTU_DELAY_H_INCLUDED +#define _MODBUS_RTU_DELAY_H_INCLUDED + +class ModbusRTUDelay +{ +public: + /* Do not allow construction or copying. */ + ModbusRTUDelay() = delete; + ModbusRTUDelay(ModbusRTUDelay const &) = delete; + + /* Calculate __minimum__ preDelay and postDelay in + * microseconds as per Modbus RTU Specification. + * + * MODBUS over serial line specification and implementation guide V1.02 + * Paragraph 2.5.1.1 MODBUS Message RTU Framing + * https://modbus.org/docs/Modbus_over_serial_line_V1_02.pdf + */ + static unsigned long const preDelay(unsigned long const baudrate) + { + double const bit_duration = 1. / baudrate; + double const word_len = 9.6f; // try also with 10.0f + double const pre_delay_us = bit_duration * word_len * 3.5f * 1e6; + return static_cast(pre_delay_us); + } + static unsigned long const postDelay(unsigned long const baudrate) + { + return preDelay(baudrate); + } +}; + +#endif /* _MODBUS_RTU_DELAY_H_INCLUDED */ diff --git a/src/ModbusRTUServer.cpp b/src/ModbusRTUServer.cpp index 95cc0b8..836ba7b 100644 --- a/src/ModbusRTUServer.cpp +++ b/src/ModbusRTUServer.cpp @@ -26,6 +26,9 @@ extern "C" { #include "ModbusRTUServer.h" +#include "ModbusRTUDelay.h" + + ModbusRTUServerClass::ModbusRTUServerClass() { } @@ -40,6 +43,8 @@ ModbusRTUServerClass::~ModbusRTUServerClass() int ModbusRTUServerClass::begin(int id, unsigned long baudrate, uint16_t config) { + _rs485->setDelays(ModbusRTUDelay::preDelay(baudrate), ModbusRTUDelay::postDelay(baudrate)); + modbus_t* mb = modbus_new_rtu(_rs485, baudrate, config); if (!ModbusServer::begin(mb, id)) {