Go Down

Topic: PC <-> Arduino serial problems (Read 1 time) previous topic - next topic

tigrezno

I'm having serious issues when interfacion arduino with C code on my linux box.

the code on the linux box is like this:

a loop
 write(fd, "get", 3); // tell arduino to send data
 read(fd, &buffer, 8); // read 8 bytes;
end of loop

the first time i read, it returns crap.
the second time too.
the third time starts working.

I can solve it with a sleep(1) before reading, but it's not desired.
I've coded too, a loop with a select call for polling the file descriptor for incoming data, and i get a timeout for the first and second time.

I really don't know whats happening, i need help!

mellis

What kind of crap?  

What kind of Arduino?  If it's a Diecimila, opening the serial port will reset the board, meaning that your first few bytes will go to the bootloader.  That might be the data you're seeing.

tigrezno

mmm can you explain it with more detail?

mellis


tigrezno

but that is not my problem, since i can wait a minute before sending data, and it generates the same error.
my problem is that when i do a write, and then a read, i will get random data. If i put a sleep(1) between write and read, i get a good result.

kg4wsv

read() is not guaranteed to return the number of bytes you ask for, and I see you aren't checking the return status to find out how many bytes are actually read.

My guess is that your sub-optimal use of read() combined with the much greater speed of the desktop is causing the problem.  Put read() in a loop to get characters until you have the buffer full, then go on to the next step in the program.

-j


tigrezno

i tried using a loop with select calls, and i got always 1-2 timeouts. After that, i got good results.
also, the sleep(1) is incredible, since it removes the error always.

kg4wsv

sleep() only hides the problem, it doesn't fix it.

IIRC, select() only tells you if the fd has data available for reading, not how many characters are available.

Good programming practice dictates that you should pay attention to the number of bytes that read() actually reports being read and fill your input buffer until the desired number of bytes have been read, especially when there is such a speed difference between the devices (e.g. your desktop screaming along at 3GHz connected to the Arduino running at 16MHz).

-j


tigrezno

mmm i'll try that, thanks for the tip.  ::)

tigrezno

ahhh thanks for the tips, finally i did it.
here is the working function:

Code: [Select]
int fdread(int fd, void *buffer, int size, int timeout) {  // timeout in milliseconds
 char *ptr = (char*)buffer;
 int received = 0;
 long int tout;
 struct timespec current;

 clock_gettime(CLOCK_REALTIME, &current);
 tout = current.tv_nsec + (timeout*1000000);
     
 while((received < size) && (tout > current.tv_nsec)) {
   if (read(fd, ptr, 1) == 1) {
     ptr++;
     received++;
   }
   clock_gettime(CLOCK_REALTIME, &current);
 }
 return received;
}

Go Up