Reading from a serial port after writing on it

10,265

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.

Share:
10,265
Youmna Habchy
Author by

Youmna Habchy

Updated on June 04, 2022

Comments

  • Youmna Habchy
    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
    Aditya Ponkshe almost 11 years
    remove O_NONBLOCK and see what happens.
  • Youmna Habchy
    Youmna Habchy almost 11 years
    I still have the same result.
  • Aditya Ponkshe
    Aditya Ponkshe almost 11 years
    so in printf("%d,%s \n",n,strerror(errno)); value of n is always zero?
  • Youmna Habchy
    Youmna Habchy almost 11 years
    Yes the result is: 0,Success
  • Aditya Ponkshe
    Aditya Ponkshe almost 11 years
    try this fcntl(fd, F_SETFL, 0);
  • Aditya Ponkshe
    Aditya Ponkshe almost 11 years
    then i am out of suggestions, sorry.
  • Youmna Habchy
    Youmna Habchy almost 11 years
    Thanks but I always have the same result.
  • Youmna Habchy
    Youmna Habchy almost 11 years
    Thank 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
    sawdust almost 11 years
    There'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
    Youmna Habchy almost 11 years
    After 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
    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 from tc[gs]etattr() need to be tested. (4) You didn't remove the fcntl(), and added O_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 the read() logic.
  • sawdust
    sawdust almost 11 years
    The proper thanks would be to "accept" the answer that explains how you got to this final code.