Pages: [1]   Go Down
Author Topic: PC <-> Arduino serial problems  (Read 739 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 86
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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, smiley-cool; // 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!
Logged

Forum Administrator
Cambridge, MA
Offline Offline
Faraday Member
*****
Karma: 9
Posts: 3538
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 86
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

mmm can you explain it with more detail?
Logged

Forum Administrator
Cambridge, MA
Offline Offline
Faraday Member
*****
Karma: 9
Posts: 3538
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

There's some more info here: http://www.arduino.cc/en/Tutorial/Bootloader
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 86
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

0
Offline Offline
Faraday Member
**
Karma: 7
Posts: 2526
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 86
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

0
Offline Offline
Faraday Member
**
Karma: 7
Posts: 2526
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 86
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 86
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
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;
}
Logged

Pages: [1]   Go Up
Jump to: