Skip to content

Commit

Permalink
Merge pull request #158 from arduino-libraries/feature/rtu-pre-post-d…
Browse files Browse the repository at this point in the history
…elay

Feature: class ModbusRTUDelay allows for calculation of minimum inter-frame breaks.
  • Loading branch information
aentinger authored Nov 4, 2024
2 parents 5afa436 + f6f9127 commit e0c9b6c
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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!");
Expand Down
4 changes: 4 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#######################################

ArduinoModbus KEYWORD1
ModbusRTUDelay KEYWORD1
ModbusRTUClient KEYWORD1
ModbusRTUServer KEYWORD1
ModbusRTUClient KEYWORD1
Expand All @@ -21,6 +22,9 @@ poll KEYWORD2
end KEYWORD2
setTimeout KEYWORD2

preDelay KEYWORD2
postDelay KEYWORD2

beginTransmission KEYWORD2
write KEYWORD2
endTransmission KEYWORD2
Expand Down
4 changes: 4 additions & 0 deletions src/ModbusRTUClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ extern "C" {

#include "ModbusRTUClient.h"

#include "ModbusRTUDelay.h"

ModbusRTUClientClass::ModbusRTUClientClass() :
ModbusClient(1000)
{
Expand All @@ -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)) {
Expand Down
50 changes: 50 additions & 0 deletions src/ModbusRTUDelay.h
Original file line number Diff line number Diff line change
@@ -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<unsigned long>(pre_delay_us);
}
static unsigned long const postDelay(unsigned long const baudrate)
{
return preDelay(baudrate);
}
};

#endif /* _MODBUS_RTU_DELAY_H_INCLUDED */
5 changes: 5 additions & 0 deletions src/ModbusRTUServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ extern "C" {

#include "ModbusRTUServer.h"

#include "ModbusRTUDelay.h"


ModbusRTUServerClass::ModbusRTUServerClass()
{
}
Expand All @@ -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)) {
Expand Down

0 comments on commit e0c9b6c

Please sign in to comment.