1 |
|
|
/** |
2 |
|
|
* @file serial_reader.cpp |
3 |
|
|
* @author Julian Viereck |
4 |
|
|
* \brief Wrapper for reading new-line terminated list of values from serial port. |
5 |
|
|
* @date 2020-01-24 |
6 |
|
|
* |
7 |
|
|
* @copyright Copyright (c) 2018 |
8 |
|
|
* |
9 |
|
|
*/ |
10 |
|
|
|
11 |
|
|
#include "blmc_drivers/serial_reader.hpp" |
12 |
|
|
#include <stdexcept> |
13 |
|
|
#include <errno.h> |
14 |
|
|
#include <fcntl.h> |
15 |
|
|
#include <string.h> |
16 |
|
|
#include <termios.h> |
17 |
|
|
#include <unistd.h> |
18 |
|
|
|
19 |
|
|
#include <iostream> |
20 |
|
|
#include <unistd.h> |
21 |
|
|
#include <fstream> |
22 |
|
|
|
23 |
|
|
namespace rt = real_time_tools; |
24 |
|
|
|
25 |
|
|
namespace blmc_drivers |
26 |
|
|
{ |
27 |
|
|
|
28 |
|
|
SerialReader::SerialReader(const std::string &serial_port, const int &num_values) |
29 |
|
|
{ |
30 |
|
|
std::string serial_port_try; |
31 |
|
|
for (int i=0; i < 4; i++) { |
32 |
|
|
// HACK: Ignore the provided serial port and |
33 |
|
|
if (i == 0) { |
34 |
|
|
serial_port_try = "/dev/ttyACM"; |
35 |
|
|
} else if (i == 1) { |
36 |
|
|
serial_port_try = "/dev/ttyACM0"; |
37 |
|
|
} else if (i == 2) { |
38 |
|
|
serial_port_try = "/dev/ttyACM1"; |
39 |
|
|
} else { |
40 |
|
|
std::cerr << "Unable to open serial port"; |
41 |
|
|
has_error_ = true; |
42 |
|
|
return; |
43 |
|
|
} |
44 |
|
|
std::cout << "Try to open serial port at " << serial_port_try << std::endl; |
45 |
|
|
fd_ = open(serial_port_try.c_str(), O_RDWR | O_NOCTTY | O_NDELAY); |
46 |
|
|
if (fd_ != -1) { |
47 |
|
|
std::cout << "Opened serial port at " << serial_port_try << std::endl; |
48 |
|
|
break; |
49 |
|
|
} |
50 |
|
|
} |
51 |
|
|
|
52 |
|
|
struct termios options; |
53 |
|
|
|
54 |
|
|
fcntl(fd_, F_SETFL, FNDELAY); // Open the device in nonblocking mode |
55 |
|
|
|
56 |
|
|
// Set parameters |
57 |
|
|
tcgetattr(fd_, &options); // Get the current options of the port |
58 |
|
|
bzero(&options, sizeof(options)); // Clear all the options |
59 |
|
|
speed_t Speed = B115200; |
60 |
|
|
cfsetispeed(&options, Speed); // Set the baud rate at 115200 bauds |
61 |
|
|
cfsetospeed(&options, Speed); |
62 |
|
|
options.c_cflag |= ( CLOCAL | CREAD | CS8); // Configure the device : 8 bits, no parity, no control |
63 |
|
|
options.c_iflag |= ( IGNPAR | IGNBRK ); |
64 |
|
|
options.c_cc[VTIME]=0; // Timer unused |
65 |
|
|
options.c_cc[VMIN]=0; // At least on character before satisfy reading |
66 |
|
|
tcsetattr(fd_, TCSANOW, &options); // Activate the settings |
67 |
|
|
|
68 |
|
|
latest_values_.resize(num_values); |
69 |
|
|
|
70 |
|
|
has_error_ = false; |
71 |
|
|
is_active_ = false; |
72 |
|
|
is_loop_active_ = true; |
73 |
|
|
// Launch the main processing loop. |
74 |
|
|
rt_thread_.create_realtime_thread(&SerialReader::loop, this); |
75 |
|
|
} |
76 |
|
|
|
77 |
|
|
void SerialReader::loop() |
78 |
|
|
{ |
79 |
|
|
int i = 0; |
80 |
|
|
int j = 0; |
81 |
|
|
|
82 |
|
|
int byte_read; |
83 |
|
|
int buffer_size = 128; |
84 |
|
|
char buffer[buffer_size]; |
85 |
|
|
char line[buffer_size]; |
86 |
|
|
int line_index = 0; |
87 |
|
|
|
88 |
|
|
static int c = 0; |
89 |
|
|
is_active_ = true; |
90 |
|
|
while (is_loop_active_) { |
91 |
|
|
int byte_consumed = 0; |
92 |
|
|
byte_read = read(fd_, buffer, buffer_size); |
93 |
|
|
while (byte_consumed < byte_read) { |
94 |
|
|
line[line_index++] = buffer[byte_consumed++]; |
95 |
|
|
if (buffer[byte_consumed - 1] == '\n') { |
96 |
|
|
// Ignore the "\r\n" in the string. |
97 |
|
|
line[line_index - 1] = '\0'; |
98 |
|
|
line[line_index - 2] = '\0'; |
99 |
|
|
line_index -= 2; |
100 |
|
|
|
101 |
|
|
// Read the actual numbers from the line. |
102 |
|
|
int bytes_scanned_total = 0; |
103 |
|
|
int bytes_scanned; |
104 |
|
|
int number; |
105 |
|
|
mutex_.lock(); |
106 |
|
|
for (int i = 0; i < latest_values_.size(); i++) { |
107 |
|
|
sscanf(line + bytes_scanned_total, "%d %n", &number, &bytes_scanned); |
108 |
|
|
if (bytes_scanned_total >= line_index) { |
109 |
|
|
break; |
110 |
|
|
} |
111 |
|
|
bytes_scanned_total += bytes_scanned; |
112 |
|
|
latest_values_[i] = number; |
113 |
|
|
} |
114 |
|
|
new_data_counter_ += 1; |
115 |
|
|
mutex_.unlock(); |
116 |
|
|
|
117 |
|
|
line_index = 0; |
118 |
|
|
} |
119 |
|
|
} |
120 |
|
|
usleep(100); |
121 |
|
|
} |
122 |
|
|
} |
123 |
|
|
|
124 |
|
|
SerialReader::~SerialReader() |
125 |
|
|
{ |
126 |
|
|
is_loop_active_ = false; |
127 |
|
|
rt_thread_.join(); |
128 |
|
|
close(fd_); |
129 |
|
|
} |
130 |
|
|
|
131 |
|
|
int SerialReader::fill_vector(std::vector<int>& values) |
132 |
|
|
{ |
133 |
|
|
mutex_.lock(); |
134 |
|
|
if (new_data_counter_ == 0) { |
135 |
|
|
missed_data_counter_ += 1; |
136 |
|
|
} else { |
137 |
|
|
missed_data_counter_ = 0; |
138 |
|
|
} |
139 |
|
|
new_data_counter_ = 0; |
140 |
|
|
values = latest_values_; |
141 |
|
|
mutex_.unlock(); |
142 |
|
|
|
143 |
|
|
return missed_data_counter_; |
144 |
|
|
} |
145 |
|
|
|
146 |
✓✗✓✗
|
3 |
} // namespace blmc_drivers |