diff --git a/CHANGELOG.md b/CHANGELOG.md index 729da97..5af6799 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # libabbaurora changelog +## v0.2.2 - 2023-11-23 +* add serial read timeout + character read delay ## v0.2.1 - 2022-01-02 * improve debug logging diff --git a/include/ABBAurora.h b/include/ABBAurora.h index 5d7ecc9..e0880a9 100644 --- a/include/ABBAurora.h +++ b/include/ABBAurora.h @@ -1,5 +1,7 @@ #ifndef ABBAurora_h #define ABBAurora_h + +#include #include "ABBAuroraEnums.h" #include "ABBAuroraSerial.h" @@ -79,9 +81,11 @@ class ABBAurora @param device Serial device, i.e. /dev/ttyUSB0 @param baudrate Optional baud rate + @param max_read_iterations Max serial read iterations + @param character_delay Max delay between character reads in microseconds */ - bool Setup(const std::string &device, const speed_t baudrate = B19200); - /** @brief Set serial device address + bool Setup(const std::string &device, const speed_t baudrate, const int &max_read_iterations, const int &character_delay); + /** @brief Set zerial device address Sets a new RS485 serial device address diff --git a/include/ABBAuroraSerial.h b/include/ABBAuroraSerial.h index 38670bd..8d42a1e 100644 --- a/include/ABBAuroraSerial.h +++ b/include/ABBAuroraSerial.h @@ -30,14 +30,17 @@ class ABBAuroraSerial @param device The serial device, i.e. /dev/ttyUSB0 @param baudrate The serial baud rate + @param max_read_iterations Max read iterations to wait for data arrival + @param character_delay Inter character read delay */ - bool Begin(const std::string &device, const speed_t &baudrate); + bool Begin(const std::string &device, const speed_t &baudrate, const int &max_read_iterations, const int &character_delay); /** @brief Read bytes Read bytes available in the input buffer @param buffer Buffer to store the bytes - @param length Number of bytes to read + @param length Number of bytes to read + */ int ReadBytes(uint8_t *buffer, const int &length); /** @brief Write bytes @@ -94,6 +97,8 @@ class ABBAuroraSerial private: int SerialPort; ///< Serial port number + int MaxReadIterations = 1000; ///< Max number of read iterations + int CharacterDelay = 52; ///< Delay between reading characters std::string ErrorMessage; ///< Error message string unsigned char Log; ///< Log level }; diff --git a/src/ABBAurora.cpp b/src/ABBAurora.cpp index 43f6c37..007adea 100644 --- a/src/ABBAurora.cpp +++ b/src/ABBAurora.cpp @@ -28,11 +28,11 @@ void ABBAurora::SetLogLevel(const unsigned char &log_level) Log = log_level; } -bool ABBAurora::Setup(const std::string &device, const speed_t baudrate) +bool ABBAurora::Setup(const std::string &device, const speed_t baudrate, const int &max_read_iterations, const int &character_delay) { ReceiveData = new uint8_t[ABBAurora::ReceiveBufferSize] (); Serial = new ABBAuroraSerial(Log); - if (!Serial->Begin(device, baudrate)) + if (!Serial->Begin(device, baudrate, max_read_iterations, character_delay)) { ErrorMessage = Serial->GetErrorMessage(); return false; diff --git a/src/ABBAuroraSerial.cpp b/src/ABBAuroraSerial.cpp index ece00f5..eb60807 100644 --- a/src/ABBAuroraSerial.cpp +++ b/src/ABBAuroraSerial.cpp @@ -19,14 +19,17 @@ ABBAuroraSerial::~ABBAuroraSerial(void) } } -bool ABBAuroraSerial::Begin(const std::string &device, const speed_t &baudrate) +bool ABBAuroraSerial::Begin(const std::string &device, const speed_t &baudrate, const int &max_read_iterations, const int &character_delay) { if (device.empty()) { ErrorMessage = "Serial device argument empty"; return false; } + MaxReadIterations = max_read_iterations; + CharacterDelay = character_delay; SerialPort = open(device.c_str(), O_RDWR | O_NOCTTY); + if (SerialPort < 0) { ErrorMessage = std::string("Error opening device ") + device + ": " + strerror(errno) + " (" + std::to_string(errno) + ")"; @@ -77,10 +80,9 @@ bool ABBAuroraSerial::Begin(const std::string &device, const speed_t &baudrate) int ABBAuroraSerial::ReadBytes(uint8_t *buffer, const int &length) { int bytes_received, retval, iterations = 0; - const int max_iterations = 1000; - //std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); + //std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); - while (iterations < max_iterations) { + while (iterations < MaxReadIterations) { int bytes_available; retval = ioctl(SerialPort, FIONREAD, &bytes_available); if (retval < 0) { @@ -88,7 +90,7 @@ int ABBAuroraSerial::ReadBytes(uint8_t *buffer, const int &length) return -1; } // intercharacter delay: 1 / baud rate * 1e6 = 52 µs - std::this_thread::sleep_for(std::chrono::microseconds(50)); + std::this_thread::sleep_for(std::chrono::microseconds(CharacterDelay)); if (bytes_available >= length) break; iterations++; @@ -97,7 +99,7 @@ int ABBAuroraSerial::ReadBytes(uint8_t *buffer, const int &length) //std::cout << "Time difference = " << std::chrono::duration_cast(end - begin).count() << "[µs]" << std::endl; //std::cout << "Iterations: " << iterations << std::endl; - if (iterations == max_iterations) + if (iterations == MaxReadIterations) { ErrorMessage = "Timeout, inverter could not be reached"; return -1;