Skip to content

- Enum-based TX enable mode #300

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
6 changes: 3 additions & 3 deletions documentation/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ bool removeIreg(uint16_t offset, uint16_t numregs = 1);
### Modbus RTU Specific API

```c
bool begin(SoftwareSerial* port, int16_t txEnablePin=-1, bool txEnableDirect=true);
bool begin(HardwareSerial* port, int16_t txEnablePin=-1, bool txEnableDirect=true);
bool begin(SoftwareSerial* port, int16_t txEnablePin=-1, ModbusRTUTxEnableMode txEnableMode=TxEnableHigh);
bool begin(HardwareSerial* port, int16_t txEnablePin=-1, ModbusRTUTxEnableMode txEnableMode=TxEnableHigh);
bool begin(Stream* port);
```

Assing Serial port. txEnablePin controls transmit enable for MAX-485. Pass txEnableDirect=false if txEnablePin uses inverse logic.
Assign Serial port. `txEnablePin` controls transmit enable for MAX-485. Use `txEnableMode = TxEnableLow` if `txEnablePin` uses inverse logic (low when transmitting).

```c
void setBaudrte(uint32 baud);
Expand Down
6 changes: 3 additions & 3 deletions examples/RTU/README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ This example introduces how to use the library for ModbusRTU (typicaly over RS-4
## Modbus RTU Specific API

```c
bool begin(SoftwareSerial* port, int16_t txEnablePin=-1, bool txEnableDirect=true);
bool begin(HardwareSerial* port, int16_t txEnablePin=-1, bool txEnableDirect=true);
bool begin(SoftwareSerial* port, int16_t txEnablePin=-1, ModbusRTUTxEnableMode txEnableMode=TxEnableHigh);
bool begin(HardwareSerial* port, int16_t txEnablePin=-1, ModbusRTUTxEnableMode txEnableMode=TxEnableHigh);
bool begin(Stream* port);
```

- `port` Pointer to Serial port
- `txEnablePin` RX/TX control pin. Not assigned (assume auto RX/TX) by default
- `txEnableDirect` Direct (true, default) or inverse (false) RX/TX pin control.
- `txEnablePin` controls transmit enable for MAX-485. Use `txEnableMode = TxEnableLow` if `txEnablePin` uses inverse logic (low when transmitting).

Assign Serial port. txEnablePin controls transmit enable for MAX-485.

Expand Down
18 changes: 9 additions & 9 deletions src/ModbusRTU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,17 +109,17 @@ void ModbusRTUTemplate::setInterFrameTime(uint32_t t_us) {
_t = t_us;
}

bool ModbusRTUTemplate::begin(Stream* port, int16_t txEnablePin, bool txEnableDirect) {
bool ModbusRTUTemplate::begin(Stream* port, int16_t txEnablePin, ModbusRTUTxEnableMode txEnableMode) {
_port = port;
_t = 1750UL;
#if defined(MODBUSRTU_FLUSH_DELAY)
_t1 = charSendTime(0);
#endif
if (txEnablePin >= 0) {
_txEnablePin = txEnablePin;
_direct = txEnableDirect;
_txEnableMode = txEnableMode;
pinMode(_txEnablePin, OUTPUT);
digitalWrite(_txEnablePin, _direct?LOW:HIGH);
digitalWrite(_txEnablePin, _txEnableMode == TxEnableHigh ? LOW : HIGH);
}
return true;
}
Expand All @@ -136,16 +136,16 @@ bool ModbusRTUTemplate::rawSend(uint8_t slaveId, uint8_t* frame, uint8_t len) {
#if defined(MODBUSRTU_REDE)
if (_txEnablePin >= 0 || _rxPin >= 0) {
if (_txEnablePin >= 0)
digitalWrite(_txEnablePin, _direct?HIGH:LOW);
digitalWrite(_txEnablePin, _txEnableMode == TxEnableHigh ? HIGH : LOW);
if (_rxPin >= 0)
digitalWrite(_rxPin, _direct?HIGH:LOW);
digitalWrite(_rxPin, _txEnableMode == TxEnableHigh ? HIGH : LOW);
#if !defined(ESP32)
delayMicroseconds(MODBUSRTU_REDE_SWITCH_US);
#endif
}
#else
if (_txEnablePin >= 0) {
digitalWrite(_txEnablePin, _direct?HIGH:LOW);
digitalWrite(_txEnablePin, _txEnableMode == TxEnableHigh ? HIGH : LOW);
#if !defined(ESP32)
delayMicroseconds(MODBUSRTU_REDE_SWITCH_US);
#endif
Expand All @@ -165,16 +165,16 @@ bool ModbusRTUTemplate::rawSend(uint8_t slaveId, uint8_t* frame, uint8_t len) {
delayMicroseconds(_t1 * MODBUSRTU_FLUSH_DELAY);
#endif
if (_txEnablePin >= 0)
digitalWrite(_txEnablePin, _direct?LOW:HIGH);
digitalWrite(_txEnablePin, _txEnableMode == TxEnableHigh ? LOW : HIGH);
if (_rxPin >= 0)
digitalWrite(_rxPin, _direct?LOW:HIGH);
digitalWrite(_rxPin, _txEnableMode == TxEnableHigh ? LOW : HIGH);
}
#else
if (_txEnablePin >= 0) {
#if defined(MODBUSRTU_FLUSH_DELAY)
delayMicroseconds(_t1 * MODBUSRTU_FLUSH_DELAY);
#endif
digitalWrite(_txEnablePin, _direct?LOW:HIGH);
digitalWrite(_txEnablePin, _txEnableMode == TxEnableHigh ? LOW : HIGH);
}
#endif
return true;
Expand Down
55 changes: 45 additions & 10 deletions src/ModbusRTU.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,29 @@
#pragma once
#include "ModbusAPI.h"

/**
* When the TX enable pin is used, specifies the logical level to enable the TX
*/
enum ModbusRTUTxEnableMode {
/**
* The TX enable pin should be high when transmitting
*/
TxEnableHigh,

/**
* The TX enable pin should be low when transmitting
*/
TxEnableLow
};

class ModbusRTUTemplate : public Modbus {
protected:
Stream* _port;
int16_t _txEnablePin = -1;
#if defined(MODBUSRTU_REDE)
int16_t _rxPin = -1;
#endif
bool _direct = true; // Transmit control logic (true=txEnableDirect, false=inverse)
ModbusRTUTxEnableMode _txEnableMode = TxEnableHigh; // Transmit control logic
uint32_t _t; // inter-frame delay in uS
#if defined(MODBUSRTU_FLUSH_DELAY)
uint32_t _t1; // char send time
Expand Down Expand Up @@ -46,13 +61,33 @@ class ModbusRTUTemplate : public Modbus {
uint32_t calculateMinimumInterFrameTime(uint32_t baud, uint8_t char_bits = 11);
void setInterFrameTime(uint32_t t_us);
uint32_t charSendTime(uint32_t baud, uint8_t char_bits = 11);

// Use `ModbusRTUTxEnableMode` overload instead
template <class T>
bool begin(T* port, int16_t txEnablePin = -1, bool txEnableDirect = true);
[[deprecated]]
bool begin(T* port, int16_t txEnablePin = -1, bool txEnableDirect = true) {
return begin(port, txEnablePin, txEnableDirect ? TxEnableHigh : TxEnableLow);
}
template <class T>
bool begin(T* port, int16_t txEnablePin = -1, ModbusRTUTxEnableMode txEnableMode = TxEnableHigh);

#if defined(MODBUSRTU_REDE)
// Use `ModbusRTUTxEnableMode` overload instead
template <class T>
bool begin(T* port, int16_t txEnablePin, int16_t rxEnablePin, bool txEnableDirect);
[[deprecated]]
bool begin(T* port, int16_t txEnablePin, int16_t rxEnablePin, bool txEnableDirect) {
return begin(port, txEnablePin, rxEnablePin, txEnableDirect ? TxEnableHigh : TxEnableLow);
}
template <class T>
bool begin(T* port, int16_t txEnablePin, int16_t rxEnablePin, ModbusRTUTxEnableMode txEnableMode);
#endif
bool begin(Stream* port, int16_t txEnablePin = -1, bool txEnableDirect = true);
// Use `ModbusRTUTxEnableMode` overload instead
[[deprecated]]
bool begin(Stream* port, int16_t txEnablePin = -1, bool txEnableDirect = true) {
return begin(port, txEnablePin, txEnableDirect ? TxEnableHigh : TxEnableLow);
}
bool begin(Stream* port, int16_t txEnablePin = -1, ModbusRTUTxEnableMode txEnableMode = TxEnableHigh);

void task();
void client() { isMaster = true; };
inline void master() {client();}
Expand All @@ -64,7 +99,7 @@ class ModbusRTUTemplate : public Modbus {
};

template <class T>
bool ModbusRTUTemplate::begin(T* port, int16_t txEnablePin, bool txEnableDirect) {
bool ModbusRTUTemplate::begin(T* port, int16_t txEnablePin, ModbusRTUTxEnableMode txEnableMode) {
uint32_t baud = 0;
#if defined(ESP32) || defined(ESP8266) // baudRate() only available with ESP32+ESP8266
baud = port->baudRate();
Expand All @@ -78,20 +113,20 @@ bool ModbusRTUTemplate::begin(T* port, int16_t txEnablePin, bool txEnableDirect)
_port = port;
if (txEnablePin >= 0) {
_txEnablePin = txEnablePin;
_direct = txEnableDirect;
_txEnableMode = txEnableMode;
pinMode(_txEnablePin, OUTPUT);
digitalWrite(_txEnablePin, _direct?LOW:HIGH);
digitalWrite(_txEnablePin, _txEnableMode == TxEnableHigh ? LOW : HIGH);
}
return true;
}
#if defined(MODBUSRTU_REDE)
template <class T>
bool ModbusRTUTemplate::begin(T* port, int16_t txEnablePin, int16_t rxEnablePin, bool txEnableDirect) {
begin(port, txEnablePin, txEnableDirect);
bool ModbusRTUTemplate::begin(T* port, int16_t txEnablePin, int16_t rxEnablePin, ModbusRTUTxEnableMode txEnableMode) {
begin(port, txEnablePin, txEnableMode);
if (rxEnablePin > 0) {
_rxPin = rxEnablePin;
pinMode(_rxPin, OUTPUT);
digitalWrite(_rxPin, _direct?LOW:HIGH);
digitalWrite(_rxPin, _txEnableMode == TxEnableHigh ? LOW : HIGH);
}
}
#endif
Expand Down