By Youmna Habchy


2013-07-16 11:18:24 8 Comments

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.

5 comments

@Youmna Habchy 2013-07-18 10:23:37

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;
}

@sawdust 2013-07-18 18:03:38

The proper thanks would be to "accept" the answer that explains how you got to this final code.

@sawdust 2013-07-17 00:35:31

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 2013-07-17 08:40:31

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 2013-07-17 09:56:55

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 2013-07-17 11:25:07

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 2013-07-17 17:52:48

(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.

@Jeff 2013-07-16 16:37:43

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.

@Youmna Habchy 2013-07-17 08:19:17

Thanks but I always have the same result.

@Serge Bollaerts 2013-07-16 14:00:54

Shouldn't you terminate the data sent with '\0'? Serge

@Aditya Ponkshe 2013-07-16 12:12:27

try this

int n=read(fd,&tempbuf,sizeof(tempbuf));

instead of

int n=read(fd,tempbuf,5);

@Aditya Ponkshe 2013-07-16 12:32:23

remove O_NONBLOCK and see what happens.

@Youmna Habchy 2013-07-16 12:33:49

I still have the same result.

@Aditya Ponkshe 2013-07-16 12:34:59

so in printf("%d,%s \n",n,strerror(errno)); value of n is always zero?

@Youmna Habchy 2013-07-16 12:37:11

Yes the result is: 0,Success

@Aditya Ponkshe 2013-07-16 12:42:18

try this fcntl(fd, F_SETFL, 0);

@Aditya Ponkshe 2013-07-16 12:46:59

then i am out of suggestions, sorry.

Related Questions

Sponsored Content

2 Answered Questions

[SOLVED] How to open, read, and write from serial port in C?

  • 2011-08-04 19:26:17
  • gnychis
  • 413282 View
  • 140 Score
  • 2 Answer
  • Tags:   c linux serial-port

1 Answered Questions

[SOLVED] Writing ESP32 data to Influxdb using InfluxdbV2.h gives NULL error

3 Answered Questions

How to read/write serial port data in C, issues with open function

3 Answered Questions

[SOLVED] Reading and writing to serial port in C on Linux

3 Answered Questions

[SOLVED] How to Read and Write from the Serial Port

  • 2009-08-07 05:43:23
  • CHIENSION
  • 226216 View
  • 48 Score
  • 3 Answer
  • Tags:   c# serial-port

8 Answered Questions

[SOLVED] Virtual Serial Port for Linux

1 Answered Questions

[SOLVED] Writing and reading mutiple serial ports on an Arduino

1 Answered Questions

[SOLVED] Writing over the serial port in C

Sponsored Content