Reputation: 107
I am working on a project that has my computer communicating with an arduino board that reads the sensor output and put it on the serial port only if a "t" was received.the arduino code as shown below is working.
const int inputPin = 0;
void setup(){
Serial.begin(9600);
pinMode(13, OUTPUT);}
void loop(){
if (Serial.available() > 0){
char c=Serial.read();
if(c=='t'){
int value = analogRead(inputPin);
float celsius = (5.0 * value * 100.0)/1024.0;
Serial.println(celsius);
}
}
}
My problem is in the C code when Im trying to read what arduino puts on the serial port. My C code is:
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<unistd.h>
#include<fcntl.h>
int main(){
int STATE_OK=0;
int STATE_WARNING=1;
int STATE_CRITICAL=2;
char tempbuf[10];
int fd=open("/dev/ttyACM0",O_RDWR | O_NOCTTY | O_NONBLOCK);
if(fd == -1){
printf("Unable to open /dev/ttyACM0\n");
return STATE_WARNING;
} else {
fcntl(fd, F_SETFL, FNDELAY);
int w=write(fd, "t", 1);
printf("The number of bytes written to the serial port is %d \n",w);
fprintf(stderr, "fd = %d.\n", fd);
sleep(10);
int n=read(fd,tempbuf,5);
printf("%d,%s \n",n,strerror(errno));
if(n>0){
float temp=atof(tempbuf);
printf("Temperature is: %f Celsius\n", temp);
if (temp>27){
return STATE_CRITICAL;
}else{
printf("The temperature is %f Celsius and checked 10 seconds ago\n",temp);
return STATE_OK;
}
}
}
close(fd);
return 0;
}
n is always=0 and i can't figure out what is the problem. Thanks in advance.
Upvotes: 2
Views: 11007
Reputation: 107
Thank you for your answers. This is my final code:
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<unistd.h>
#include<fcntl.h>
#include<termios.h>
int main() {
int STATE_OK=0;
int STATE_WARNING=1;
int STATE_CRITICAL=2;
char tempbuf[10];
struct termios tty;
int fd=open("/dev/ttyACM1",O_RDWR | O_NOCTTY);
if(fd == -1){
printf("Unable to open /dev/ttyACM1\n");
return STATE_WARNING;
}else {
if(tcgetattr(fd, &tty)!=0){
perror("tcgetatt() error");
}else{
cfsetospeed(&tty, B9600);
cfsetispeed(&tty, B9600);
tty.c_cflag &= ~PARENB;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag &= ~CRTSCTS;
tty.c_cflag |= CLOCAL | CREAD;
tty.c_iflag |= IGNPAR | IGNCR;
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
tty.c_lflag |= ICANON;
tty.c_oflag &= ~OPOST;
tcsetattr(fd, TCSANOW, &tty);
int w=write(fd, "t", 1);/*printf("%d\n",w);
fprintf(stderr, "fd = %d.\n", fd);*/
usleep(1000);
int n=read(fd,tempbuf,8);/*printf("%d \n",n);*/
tempbuf[9]=0;
float temp=atof(tempbuf);
if (temp>27){
printf("CRITICAL: %f celsius\n",temp);
return STATE_CRITICAL;
}else{
printf("Everything is OK and the temperature is %f Celsius\n",temp);
return STATE_OK;
}
}
}
close(fd);
return 0;
}
Upvotes: 0
Reputation: 17047
i can't figure out what is the problem
One big problem is that the C program running on the "computer" is incomplete.
The Arduino's program does a serial port setup of at least the baud rate (and whatever else might be performed by default).
But the "computer's" C program never properly configures the serial port. The serial port will use whatever attributes (baud rate, data length, parity setting, canonical versus raw mode) previously configured, which will cause unpredictable reads and writes. (A loopback test would probably produce a false positive result.)
Use the POSIX Serial Port guide or this answer for sample code.
For canonical mode you probably need to add code like (assuming 8N1):
rc = tcgetattr(fd, &tty);
if (rc < 0) {
/* handle error */
}
savetty = tty; /* preserve original settings for restoration */
spd = B9600;
cfsetospeed(&tty, (speed_t)spd);
cfsetispeed(&tty, (speed_t)spd);
tty.c_cflag &= ~PARENB
tty.c_cflag &= ~CSTOPB
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag &= ~CRTSCTS; /* no HW flow control? */
tty.c_cflag |= CLOCAL | CREAD;
tty.c_iflag |= IGNPAR | IGNCR;
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
tty.c_lflag |= ICANON;
tty.c_oflag &= ~OPOST;
rc = tcsetattr(fd, TCSANOW, &tty);
if (rc < 0) {
/* handle error */
}
You probably should delete the line
fcntl(fd, F_SETFL, FNDELAY);
as well as the O_NONBLOCK
option in the open()
call.
Upvotes: 3
Reputation: 1362
Reading the description of read() (shown below) tells us that n = 0 when you reach the end of file. Since the serial is not sending a \0, the read will continue until the end of file is reached. Therefore I think n==0 is the result you want.
So, maybe your if (n>0)
test should be if (n==0)
Can you see the characters you expect in your buffer using the debugger?
read() #include int read( int handle, void *buffer, int nbyte );
The read() function attempts to read nbytes from the file associated with handle, and places the characters read into buffer. If the file is opened using O_TEXT, it removes carriage returns and detects the end of the file.
The function returns the number of bytes read. On end-of-file, 0 is returned, on error it returns -1, setting errno to indicate the type of error that occurred.
Upvotes: 0
Reputation: 3890
try this
int n=read(fd,&tempbuf,sizeof(tempbuf));
instead of
int n=read(fd,tempbuf,5);
Upvotes: 0