I am facing a very strange problem, which I wasn't able to solve. I want to read (just read) data collected and sent by a micro-controller via usb as serial port (FTDI) on Mac Os X using c++. The the size of one complete data-sequence is always exactly 10 bytes. However I was using the following code to read the data:
Imported libraries:
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/ioctl.h>
Code:
void init(){
serial = open(port.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK); // 0_RDONLY ?
struct termios options;
//set opt to 115200-8n1
cfsetspeed(&options, B115200);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
tcsetattr(serial, TCSANOW, &options);
if (serial < 0){
//Error
}else{
//run loop
}
}
void serial_loop(){
long bytes_read;
int bytes_available;
unsigned char msg[10];
while(1){
do{
usleep(1000);
ioctl(serial, FIONREAD, &bytes_available);
}while(bytes_available < 10); //wait for the sequence to complete
bytes_read = read(serial, msg, 10);
//do some parsing here
}
}
This code worked a few days ago but now it isn't anymore. The data is reaching the computer perfectly according to the Terminal -> screen -command. I checked the port-file-name which is still correct and the port is opened successfully as well. I narrowed down my issue to the ioctl-command FIONREAD which doesn't write the correct number to the bytes_available-var (anymore). It did work, and I believe, I didn't change anything in the code.
Do you see any problem that could cause this issue? Are there any dangerous passages in my code? Thank you for your help, I'm really stuck here...
EDIT: Thanks to the feedback, I was able to get it running again. Here is the current code:
int serial;
void init(){
serial = open(port.c_str(), O_RDWR | O_NOCTTY); //removed 0_NONBLOCK
struct termios options;
//set opt to 115200-8n1
cfsetspeed(&options, B115200);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); //Non-canonical
options.c_cc[VMIN] = 1; //block read until at least 1 byte was recieved
options.c_lflag = 0;
tcsetattr(serial, TCSANOW, &options);
if (serial < 0){
//Error
}else{
//run loop
}
}
void serial_loop(){
int datalength = 10;
long bytes_read = 0;
int bytes_in_msg = 0;
unsigned char buf[datalength];
unsigned char msg[datalength];
do{
bytes_read = read(serial, buf, datalength-bytes_in_msg);
usleep(1000);
if (bytes_read>0){
memcpy(&msg[bytes_in_msg], &buf, bytes_read);
}
bytes_in_msg += bytes_read;
}while(bytes_in_msg < datalength);
//do some parsing here
}
}
This works, but is there anything left, that could be problematic?
Thank you for your support!