Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: class ModbusRTUDelay allows for calculation of minimum inter-frame breaks. #158

Merged
merged 2 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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