Sending Serial data from Arduino to C program

Hi,

I'm having problems getting a C program to accurately read bytes from Arduino serial output. (Sending data from the C program to the Arduino works fine.) I eventually want to send a byte from C to tell Arduino to start a measurement, wait for the measurement to finish, and then read a float from the Arduino. I'm running this on an Ubuntu 12.

Arduino code:

void setup() {                  
  Serial.begin(9600);
}

void loop() {
  if(Serial.available()){
    int byteRead = Serial.read()-48;
    Serial.println(byteRead);
    
    Serial.write('a');
    Serial.write('b');
    Serial.write('c');
    Serial.write('d');
    Serial.write('1');
    Serial.write('2');
    Serial.write('3');
    Serial.write('4');
    Serial.write('\n');
  }
}

C code:

#include <stdio.h>   /* Standard input/output definitions */
#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 <time.h>
#include <sys/types.h>

#include <stdlib.h> 
#include <stdint.h>   /* Standard types */
#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 <sys/ioctl.h>
#include <getopt.h>

int main(){
	printf("Hello World\n");	
	
	// Method 1
	//Open communication with arduino	
	int portName = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
	
	struct termios options;
	tcgetattr(portName, &options);
	cfsetispeed(&options, B9600);
	cfsetospeed(&options, B9600);
	options.c_cflag |= (CLOCAL | CREAD);
	tcsetattr(portName, TCSANOW, &options);
	//8 bit characters	
	options.c_cflag &= ~CSIZE; /* Mask the character size bits */
	options.c_cflag |= CS8;    /* Select 8 data bits */
	//No parity
	options.c_cflag &= ~PARENB;
	options.c_cflag &= ~CSTOPB;
	
	//Send Take Sample command to arduino
	char num[] = "3";
		
	write(portName, num, 1);
	printf("%s\n",num);
	
	//Read Hb answer
	unsigned char Hb[9];
	int pos = 0;
	while( pos < 10 ) {
		read(portName, Hb+pos, 1);
		if( Hb[pos] == '\n' ) break;
		printf("%i ",pos);		
		printf("%x\n",Hb[pos]);
		pos++;
	}
	printf("%i\n",pos);
	
	Hb[4]='\0';
	
	printf("Goodbye World\n");
	
	//Close communication
	close(portName);

	return 0;
}

The expected output would be:
Hello World
3
0 61
1 62
2 63
3 64
4 31
5 32
6 33
7 34
8
8
Goodbye World

The current output is
Hello World
3
0 b7
1 0
2 0
3 0
4 0
5 e9
6 88
7 4
8 8
9 0
10
Goodbye World

Any suggestions? I'm sure this is a solved problem, but I haven't been able to figure it out. Thank you for the help!

	unsigned char Hb[9];
	int pos = 0;
	while( pos < 10 ) {
		read(portName, Hb+pos, 1);

I'm a little troubled that you are reading up to 10 bytes into a 9-character array.

First BOTH programs are in C/C++.

Try working with a simple echo program running on the Arduino. Use that to sort out what is going on with your PC program.

If you get that working and the problem persists then take a look at the Arduino side of things.

Mark

Looking at the man page for "read" I see:

On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number. It is not an error if this number is smaller than the number of bytes requested; this may happen for example because fewer bytes are actually available right now ...

Probably you are trying to read faster than the Arduino is sending.

A simple test would be to check for zero bytes on the read, eg.

if (read(portName, Hb+pos, 1) == 0)
   continue;

I'm not saying that will fix it, but it seems a reasonable precaution to take.

close(portName);

I suspect this (from your PC code) is the problem.

When the PC program opens the serial port the Arduino will reset. Your PC program must allow time for that and it must open the port once and keep it open until it is completely finished with the PC.

See how things are managed in this Python demo. The same principals apply in any language.

...R

Nick - that was the key. Thank you so much!