From 9e611e326b7abb066ec4373e6fc4f58f71bbd55f Mon Sep 17 00:00:00 2001
From: Doc Walker <4-20ma@wvfans.net>
Date: Sat, 23 May 2015 21:42:55 -0500
Subject: [PATCH] Fix #17 Pass Stream object to ModbusMaster
- BREAK: This is a breaking change to the interface. ModbusMaster now takes a
serial object which has been initialized with the appropriate baud rate.
Any Stream object may be used, including SoftwareSerial.
- As a byproduct of these changes, the library should now be able to be used
on other architectures besides AVR and SAM.
---
ModbusMaster.cpp | 107 +++---------------
ModbusMaster.h | 10 +-
README.md | 14 ++-
examples/Basic/Basic.pde | 15 +--
.../PhoenixContact_nanoLC.pde | 13 ++-
keywords.txt | 1 -
library.properties | 2 +-
7 files changed, 41 insertions(+), 121 deletions(-)
diff --git a/ModbusMaster.cpp b/ModbusMaster.cpp
index fb6347b..35b6c77 100644
--- a/ModbusMaster.cpp
+++ b/ModbusMaster.cpp
@@ -33,120 +33,39 @@ Arduino library for communicating with Modbus slaves over RS232/485 (via RTU pro
/* _____GLOBAL VARIABLES_____________________________________________________ */
-#if defined(ARDUINO_ARCH_AVR)
- HardwareSerial* MBSerial = &Serial; ///< Pointer to Serial class object
-#elif defined(ARDUINO_ARCH_SAM)
- UARTClass* MBSerial = &Serial; ///< Pointer to Serial class object
-#else
- #error "This library only supports boards with an AVR or SAM processor. Please open an issue at https://github.com/4-20ma/ModbusMaster/issues and indicate which processor/platform you're using."
-#endif
/* _____PUBLIC FUNCTIONS_____________________________________________________ */
/**
Constructor.
-Creates class object using default serial port 0, Modbus slave ID 1.
+Creates class object; initialize it using ModbusMaster::begin().
@ingroup setup
*/
ModbusMaster::ModbusMaster(void)
{
- _u8SerialPort = 0;
- _u8MBSlave = 1;
-}
-
-
-/**
-Constructor.
-
-Creates class object using default serial port 0, specified Modbus slave ID.
-
-@overload void ModbusMaster::ModbusMaster(uint8_t u8MBSlave)
-@param u8MBSlave Modbus slave ID (1..255)
-@ingroup setup
-*/
-ModbusMaster::ModbusMaster(uint8_t u8MBSlave)
-{
- _u8SerialPort = 0;
- _u8MBSlave = u8MBSlave;
-}
-
-
-/**
-Constructor.
-
-Creates class object using specified serial port, Modbus slave ID.
-
-@overload void ModbusMaster::ModbusMaster(uint8_t u8SerialPort, uint8_t u8MBSlave)
-@param u8SerialPort serial port (Serial, Serial1..Serial3)
-@param u8MBSlave Modbus slave ID (1..255)
-@ingroup setup
-*/
-ModbusMaster::ModbusMaster(uint8_t u8SerialPort, uint8_t u8MBSlave)
-{
- _u8SerialPort = (u8SerialPort > 3) ? 0 : u8SerialPort;
- _u8MBSlave = u8MBSlave;
-}
-
-
-/**
-Initialize class object.
-
-Sets up the serial port using default 19200 baud rate.
-Call once class has been instantiated, typically within setup().
-
-@ingroup setup
-*/
-void ModbusMaster::begin(void)
-{
- begin(19200);
}
/**
Initialize class object.
-Sets up the serial port using specified baud rate.
+Assigns the Modbus slave ID and serial port.
Call once class has been instantiated, typically within setup().
-@overload ModbusMaster::begin(uint16_t u16BaudRate)
-@param u16BaudRate baud rate, in standard increments (300..115200)
+@param slave Modbus slave ID (1..255)
+@param &serial reference to serial port object (Serial, Serial1, ... Serial3)
@ingroup setup
*/
-void ModbusMaster::begin(uint16_t u16BaudRate)
+void ModbusMaster::begin(uint8_t slave, Stream &serial)
{
// txBuffer = (uint16_t*) calloc(ku8MaxBufferSize, sizeof(uint16_t));
+ _u8MBSlave = slave;
+ _serial = &serial;
_u8TransmitBufferIndex = 0;
u16TransmitBufferLength = 0;
- switch(_u8SerialPort)
- {
-#if defined(UBRR1H)
- case 1:
- MBSerial = &Serial1;
- break;
-#endif
-
-#if defined(UBRR2H)
- case 2:
- MBSerial = &Serial2;
- break;
-#endif
-
-#if defined(UBRR3H)
- case 3:
- MBSerial = &Serial3;
- break;
-#endif
-
- case 0:
- default:
- MBSerial = &Serial;
- break;
- }
-
- MBSerial->begin(u16BaudRate);
#if __MODBUSMASTER_DEBUG__
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
@@ -750,31 +669,31 @@ uint8_t ModbusMaster::ModbusMasterTransaction(uint8_t u8MBFunction)
u8ModbusADU[u8ModbusADUSize] = 0;
// flush receive buffer before transmitting request
- while (MBSerial->read() != -1);
+ while (_serial->read() != -1);
// transmit request
for (i = 0; i < u8ModbusADUSize; i++)
{
#if defined(ARDUINO) && ARDUINO >= 100
- MBSerial->write(u8ModbusADU[i]);
+ _serial->write(u8ModbusADU[i]);
#else
- MBSerial->print(u8ModbusADU[i], BYTE);
+ _serial->print(u8ModbusADU[i], BYTE);
#endif
}
u8ModbusADUSize = 0;
- MBSerial->flush(); // flush transmit buffer
+ _serial->flush(); // flush transmit buffer
// loop until we run out of time or bytes, or an error occurs
u32StartTime = millis();
while (u8BytesLeft && !u8MBStatus)
{
- if (MBSerial->available())
+ if (_serial->available())
{
#if __MODBUSMASTER_DEBUG__
digitalWrite(4, true);
#endif
- u8ModbusADU[u8ModbusADUSize++] = MBSerial->read();
+ u8ModbusADU[u8ModbusADUSize++] = _serial->read();
u8BytesLeft--;
#if __MODBUSMASTER_DEBUG__
digitalWrite(4, false);
diff --git a/ModbusMaster.h b/ModbusMaster.h
index e52843f..1cee4d7 100644
--- a/ModbusMaster.h
+++ b/ModbusMaster.h
@@ -75,11 +75,8 @@ class ModbusMaster
{
public:
ModbusMaster();
- ModbusMaster(uint8_t);
- ModbusMaster(uint8_t, uint8_t);
- void begin();
- void begin(uint16_t);
+ void begin(uint8_t, Stream &serial);
void idle(void (*)());
// Modbus exception codes
@@ -224,9 +221,8 @@ class ModbusMaster
uint8_t readWriteMultipleRegisters(uint16_t, uint16_t);
private:
- uint8_t _u8SerialPort; ///< serial port (0..3) initialized in constructor
- uint8_t _u8MBSlave; ///< Modbus slave (1..255) initialized in constructor
- uint16_t _u16BaudRate; ///< baud rate (300..115200) initialized in begin()
+ Stream* _serial; ///< reference to serial port object
+ uint8_t _u8MBSlave; ///< Modbus slave (1..255) initialized in begin()
static const uint8_t ku8MaxBufferSize = 64; ///< size of response/transmit buffers
uint16_t _u16ReadAddress; ///< slave register from which to read
uint16_t _u16ReadQty; ///< quantity of words to read
diff --git a/README.md b/README.md
index 1898c84..dc37096 100755
--- a/README.md
+++ b/README.md
@@ -88,22 +88,24 @@ The library contains a few sketches that demonstrate use of the ModbusMaster lib
along with ModbusMaster. If not, see .
Written by Doc Walker (Rx)
- Copyright © 2009-2013 Doc Walker <4-20ma at wvfans dot net>
+ Copyright © 2009-2015 Doc Walker <4-20ma at wvfans dot net>
*/
#include
-// instantiate ModbusMaster object as slave ID 2
-// defaults to serial port 0 since no port was specified
-ModbusMaster node(2);
+// instantiate ModbusMaster object
+ModbusMaster node;
void setup()
{
- // initialize Modbus communication baud rate
- node.begin(19200);
+ // use Serial (port 0); initialize Modbus communication baud rate
+ Serial.begin(19200);
+
+ // communicate with Modbus slave ID 2 over Serial (port 0)
+ node.begin(2, Serial);
}
diff --git a/examples/Basic/Basic.pde b/examples/Basic/Basic.pde
index 0a4b452..c699abe 100644
--- a/examples/Basic/Basic.pde
+++ b/examples/Basic/Basic.pde
@@ -18,22 +18,24 @@
along with ModbusMaster. If not, see .
Written by Doc Walker (Rx)
- Copyright © 2009-2013 Doc Walker <4-20ma at wvfans dot net>
+ Copyright © 2009-2015 Doc Walker <4-20ma at wvfans dot net>
*/
#include
-// instantiate ModbusMaster object as slave ID 2
-// defaults to serial port 0 since no port was specified
-ModbusMaster node(2);
+// instantiate ModbusMaster object
+ModbusMaster node;
void setup()
{
- // initialize Modbus communication baud rate
- node.begin(19200);
+ // use Serial (port 0); initialize Modbus communication baud rate
+ Serial.begin(19200);
+
+ // communicate with Modbus slave ID 2 over Serial (port 0)
+ node.begin(2, Serial);
}
@@ -66,4 +68,3 @@ void loop()
}
}
}
-
diff --git a/examples/PhoenixContact_nanoLC/PhoenixContact_nanoLC.pde b/examples/PhoenixContact_nanoLC/PhoenixContact_nanoLC.pde
index 7fdb6de..5603184 100644
--- a/examples/PhoenixContact_nanoLC/PhoenixContact_nanoLC.pde
+++ b/examples/PhoenixContact_nanoLC/PhoenixContact_nanoLC.pde
@@ -19,7 +19,7 @@
along with ModbusMaster. If not, see .
Written by Doc Walker (Rx)
- Copyright © 2009-2013 Doc Walker <4-20ma at wvfans dot net>
+ Copyright © 2009-2015 Doc Walker <4-20ma at wvfans dot net>
*/
@@ -46,14 +46,17 @@
#define NANO_AI(n) (0x0000 + 2 * n) ///< returns nanoLC analog input address
-// instantiate ModbusMaster object, serial port 0, Modbus slave ID 1
-ModbusMaster nanoLC(0, 1);
+// instantiate ModbusMaster object
+ModbusMaster nanoLC;
void setup()
{
- // initialize Modbus communication baud rate
- nanoLC.begin(19200);
+ // use Serial (port 0); initialize Modbus communication baud rate
+ Serial.begin(19200);
+
+ // communicate with Modbus slave ID 1 over Serial (port 0)
+ nanoLC.begin(1, Serial);
}
diff --git a/keywords.txt b/keywords.txt
index 47f17ea..cf50a0a 100644
--- a/keywords.txt
+++ b/keywords.txt
@@ -7,7 +7,6 @@
#######################################
ModbusMaster KEYWORD1
-MBSerial KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
diff --git a/library.properties b/library.properties
index 5da042f..e4a048f 100644
--- a/library.properties
+++ b/library.properties
@@ -6,4 +6,4 @@ sentence=Enlighten your Arduino to be a Modbus master.
paragraph=Enables communication with Modbus slaves over RS232/485 (via RTU protocol). Requires an RS232/485 transceiver.
category=Communication
url=https://github.com/4-20ma/ModbusMaster
-architectures=avr,sam
+architectures=*