Reading from a serial port after writing on it
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.
Youmna Habchy
Updated on June 04, 2022Comments
-
Youmna Habchy almost 2 years
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.
-
Aditya Ponkshe almost 11 yearsremove O_NONBLOCK and see what happens.
-
Youmna Habchy almost 11 yearsI still have the same result.
-
Aditya Ponkshe almost 11 yearsso in printf("%d,%s \n",n,strerror(errno)); value of n is always zero?
-
Youmna Habchy almost 11 yearsYes the result is: 0,Success
-
Aditya Ponkshe almost 11 yearstry this fcntl(fd, F_SETFL, 0);
-
Aditya Ponkshe almost 11 yearsthen i am out of suggestions, sorry.
-
Youmna Habchy almost 11 yearsThanks but I always have the same result.
-
Youmna Habchy almost 11 yearsThank you for your answer but honestly I didn't understand the code, there isn't another way to solve the problem without serial programming? Thanks in advance.
-
sawdust almost 11 yearsThere's the
stty
command, but that is not 100% reliable like coding the configuration in the program. You need to read the POSIX Serial Port guide and/or this answer for sample code. -
Youmna Habchy almost 11 yearsAfter reading the POSIX Serial Port guide, I edit my code(as you suggested) and I still have n=0 and c=� , I'll post my new code in an answer.
-
sawdust almost 11 years(1) You should post the revised code as an "edit" to your question, not as an answer. (2) Your revised code has the
tcsetattr()
in the wrong place to be effective, so of course there is no improvement. (3) Return codes fromtc[gs]etattr()
need to be tested. (4) You didn't remove thefcntl()
, and addedO_NODELAY
which is probably wrong. (5) You made more edits than necessary, and changed the program from reading a whole line to reading just one char at a time. You need to choose canonical mode or raw mode, and make the attributes consistent with theread()
logic. -
sawdust almost 11 yearsThe proper thanks would be to "accept" the answer that explains how you got to this final code.