Reputation: 851
I want to read data from an Arduino micro controller to my pc running Mac OS X via serial port with the C programming language and the GCC compiler.
The format of my data is A xxxx xxxx xxxx xxxx xxxx xxxx B
, with A is the beginning of the data, B is the end of the data and between the sensor there are 4 space (" ").
The xxxx data vary vary between 0-1023.
I am trying this code:
#include<stdio.h> /* Standard input/output definitions */
#include<stdlib.h>
#include<string.h> /* String function definitions */
#include<unistd.h> /* UNIX standard function definitions */
#include<fcntl.h> /* File control definitions */
#include<errno.h> /* Error number definitions */
#include<termios.h> /* POSIX terminal control definitions */
#include<string.h>
#include<unistd.h>
char *buf;
int fd; /* File descriptor for the port */
int i,n;
char *sensor1, *sensor2, *sensor3, *sensor4, *sensor5, *sensor6,*header, *footer;
int open_port(void)
{
fd = open("/dev/tty.usbmodem1d11", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
perror("cannot open");
}
else
fcntl(fd, F_SETFL, 0);
struct termios options;
tcgetattr(fd, &options);
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
options.c_cflag |= (CLOCAL | CREAD);
tcsetattr(fd, TCSANOW, &options);
options.c_cflag &= ~CSIZE;
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
// options.c_cflag |= (IXON | IXOFF | IXANY); // xon & xoff on
return (fd);
}
int main(int argc, char**argv) {
buf=malloc(4095);
open_port();
free(buf);
while(1){
read(fd,buf,90);
printf("%s\n",buf);
}
close(fd);
}
But the result is not consistent, I mean the length of the data is not the same:
A 1023 1023 1023 1023 1023 B
A
10233 023 1023 1023 B
A 1023 1023 1023 1023 1023 B
A 3 023 1023 1023 B
A 1023 1023 1023 1023 1023 B
A
10233 023 1023 1023 B
A 1023 1023 1023 1023 1023 BA
Any suggestions?
Upvotes: 0
Views: 3807
Reputation: 63481
Examine what you are getting back from each read call:
int nbytes;
while(1) {
nbytes = read(fd,buf,90);
if( nbytes > 0 ) {
buf[nbytes] = 0;
printf( "Read %2d bytes: '%s'\n", nbytes, buf );
}
}
You will need to gather the result into a buffer, and parse it according to your device's format specification. You can't just assume that each read
call will give you a whole record.
To gather the result, you need to keep track of what you have already read - something like this...
int nbytes, nparsed;
int npos = 0;
while(1) {
nbytes = read(fd, &buf[npos], 90-npos);
if( nbytes > 0 )
{
npos += nbytes;
// Parse a line. If successful, move remainder of line to
// start of buffer and continue...
nparsed = parse_line(buf, npos);
if( nparsed > 0 ) {
memmove( buf, &buf[npos], npos-nparsed );
npos -= nparsed;
}
}
}
Depends on your application. It might be even simpler than that.
Upvotes: 2