Reputation: 247
I am trying to read lines of datas comming from my arduino using serial.
My arduino code look like that : Serial3.print(Z, 2);Serial3.print(F(";"));Serial3.println(F("END\n"));
And this is my code to read the data on ubuntu :
void setup(){
//set up serial
tcgetattr(dueSerial, &port_options); // Get the current attributes of the Serial port
dueSerial = open("/dev/ttyUSB0", O_RDWR | O_NONBLOCK | O_NOCTTY | O_NDELAY);
if (dueSerial == -1) {
reportFailure("Could not open Arduino");
} else {
port_options.c_cflag &= ~PARENB; // Disables the Parity Enable bit(PARENB),So No Parity
port_options.c_cflag &= ~CSTOPB; // CSTOPB = 2 Stop bits,here it is cleared so 1 Stop bit
port_options.c_cflag &= ~CSIZE; // Clears the mask for setting the data size
port_options.c_cflag |= CS8; // Set the data bits = 8
port_options.c_cflag &= ~CRTSCTS; // No Hardware flow Control
port_options.c_cflag |= (CREAD | CLOCAL); // Enable receiver,Ignore Modem Control lines
port_options.c_iflag &= ~(IXON | IXOFF | IXANY); // Disable XON/XOFF flow control both input & output
port_options.c_lflag &= ~(ECHO | ECHONL | IEXTEN | ISIG); // no echo
port_options.c_iflag |= ICANON; //Enable canonical
port_options.c_iflag |= ICRNL; //map CR to NL
//port_options.c_oflag &= ~OPOST; // No Output Processing
//port_options.c_lflag = 0; // enable raw input instead of canonical,
/*
initialize all control characters
default values can be found in /usr/include/termios.h, and are given
in the comments, but we don't need them here
*/
port_options.c_cc[VINTR] = 0; /* Ctrl-c */
port_options.c_cc[VQUIT] = 0; /* Ctrl-\ */
port_options.c_cc[VERASE] = 0; /* del */
port_options.c_cc[VKILL] = 0; /* @ */
port_options.c_cc[VEOF] = 4; /* Ctrl-d */
port_options.c_cc[VTIME] = 0; /* inter-character timer unused */
port_options.c_cc[VMIN] = 0; /* blocking read until 1 character arrives */
port_options.c_cc[VSWTC] = 0; /* '\0' */
port_options.c_cc[VSTART] = 0; /* Ctrl-q */
port_options.c_cc[VSTOP] = 0; /* Ctrl-s */
port_options.c_cc[VSUSP] = 0; /* Ctrl-z */
port_options.c_cc[VEOL] = 0; /* '\0' */
port_options.c_cc[VREPRINT] = 0; /* Ctrl-r */
port_options.c_cc[VDISCARD] = 0; /* Ctrl-u */
port_options.c_cc[VWERASE] = 0; /* Ctrl-w */
port_options.c_cc[VLNEXT] = 0; /* Ctrl-v */
port_options.c_cc[VEOL2] = 0; /* '\0' */
cfsetispeed( & port_options, BAUDRATE); // Set Read Speed
cfsetospeed( & port_options, BAUDRATE); // Set Write Speed
tcflush(dueSerial, TCIFLUSH);
tcflush(dueSerial, TCIOFLUSH);
int att = tcsetattr(dueSerial, TCSANOW, & port_options);
if (att != 0) {
reportFailure("ERROR in Setting Arduino port attributes");
} else {
LOG_INFO("SERIAL DUE Port Good to Go");
}
}
}
void UART::tick() {
//Arduino msg = "IMU;LAX;LAY;LAZ;AVX;AVY;AVZ;AY;AP;AR;END"
// rx_buffer[0] = '0';
memset(&rx_buffer, '\0', sizeof(rx_buffer));
// tcflush(dueSerial, TCIOFLUSH);
rx_length = read(dueSerial, &rx_buffer,255);
if (rx_length < 0) {
LOG_INFO("Error reading");
}else{
LOG_INFO("Read %i bytes. Received message: %s", rx_length, rx_buffer);
}
}
But when I try this code I get many lines at a time so my output look like this :
2020-11-15 09:13:09.491 INFO packages/skeleton_pose_estimation/apps/usb/UART.cpp@87: Read 0 bytes. Received message:
2020-11-15 09:13:09.496 INFO packages/skeleton_pose_estimation/apps/usb/UART.cpp@87: Read 255 bytes. Received message: 0.01;0.00;0.00;0.00;0.00;0.00;0.00;END
IMU;-0.00;0.02;0.03;0.00;0.00;0.00;0.00;0.00;0.00;END
IMU;-0.00;0.02;0.03;0.00;-0.00;0.00;0.00;0.00;0.00;END
IMU;-0.00;0.02;-0.02;0.00;-0.00;0.00;0.00;0.00;0.00;END
IMU;-0.00;0.02;-0.02;-0.00;0.00;0.00;0.00;0.00;
2020-11-15 09:13:09.501 INFO packages/skeleton_pose_estimation/apps/usb/UART.cpp@87: Read 241 bytes. Received message: 0.00;END
IMU;-0.01;-0.02;-0.01;-0.00;0.00;0.00;0.00;0.00;0.00;END
IMU;-0.01;-0.02;-0.01;-0.00;-0.00;0.00;0.00;0.00;0.00;END
IMU;-0.01;-0.02;0.03;-0.00;-0.00;0.00;0.00;0.00;0.00;END
IMU;-0.01;-0.02;0.03;0.00;0.00;0.00;0.00;0.00;0.00;END
2020-11-15 09:13:09.506 INFO packages/skeleton_pose_estimation/apps/usb/UART.cpp@87: Read 0 bytes. Received message:
2020-11-15 09:13:09.511 INFO packages/skeleton_pose_estimation/apps/usb/UART.cpp@87: Read 0 bytes. Received message:
But I want it to read only one line per read() function call. I believe that I either set a wrong parameter making the conanical mode unused or maybe it's ignoring my \n and \r but don't know why....
Please help me to find why. Thank you a ton !
Upvotes: 1
Views: 368
Reputation: 17047
But I want it to read only one line per read() function call. I believe that I either set a wrong parameter making the conanical mode unused ...
Your program does not behave as expected because canonical mode is never actually set.
The statement
port_options.c_iflag |= ICANON; //Enable canonical
is incorrect. ICANON
is in the c_lflag
member, and not in c_iflag
.
Your code has additional issues.
(1) The variable dueSerial
is used uninitialized:
void setup(){
//set up serial
tcgetattr(dueSerial, &port_options); // Get the current attributes of the Serial port
dueSerial = open(...);
...
The file descriptor needs to be obtained and validated before it can be used in the tcgetattr() call.
The proper ordering of statements is:
void setup(){
//set up serial
dueSerial = open(...);
if (dueSerial == -1) {
/* abort */
}
tcgetattr(dueSerial, &port_options);
...
(2) Numerous input conversions are left unspecified in your termios initialization.
Canonical mode enables various options to convert certain input characters, and most of these options need to be disabled for reading by a program (versus an interactive terminal).
Typically INPCK
(enable input parity checking), IUCLC
(map uppercase characters to lowercase), and IMAXBEL
(ring bell when input queue is full) are disabled.
You need to review whether you also want IGNCR
(preserve or ignore carriage return), INLCR
(translate newline to carriage return), and ICRNL
(translate carriage return to newline unless IGNCR
is set) to also be disabled.
(3) Use of nonblocking mode is questionable.
Since you want "to read only one line per read() function call", then blocking mode is the proper way to obtain that result.
If you insist on using nonblocking mode, then the read() syscall will always return "immediately" and may not return any data at all.
Upvotes: 1