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=*