1

I'm attempting to read data from the serial line coming from the Arduino and return it as a string. I have found/modified the following code to do so:

        #include <sys/types.h>
        #include <sys/stat.h>
        #include <fcntl.h>
        #include <termios.h>
        #include <stdio.h>
    #include <stdlib.h>

        /* baudrate settings are defined in <asm/termbits.h>, which is
        included by <termios.h> */
        #define BAUDRATE B9600            
        /* change this definition for the correct port */
        #define MODEMDEVICE "/dev/ttyACM0"
        #define _POSIX_SOURCE 1 /* POSIX compliant source */

        #define FALSE 0
        #define TRUE 1

        volatile int STOP=FALSE; 

extern char* readline()
        {
          int fd,c, res;
          struct termios oldtio,newtio;
          char* buf = malloc(255*sizeof(char));
        /* 
          Open modem device for reading and writing and not as controlling tty
          because we don't want to get killed if linenoise sends CTRL-C.
        */
         fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY ); 
         if (fd <0) {perror(MODEMDEVICE); exit(-1); }

         tcgetattr(fd,&oldtio); /* save current serial port settings */
         bzero(&newtio, sizeof(newtio)); /* clear struct for new port settings */

        /* 
          BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
          CRTSCTS : output hardware flow control (only used if the cable has
                    all necessary lines. See sect. 7 of Serial-HOWTO)
          CS8     : 8n1 (8bit,no parity,1 stopbit)
          CLOCAL  : local connection, no modem contol
          CREAD   : enable receiving characters
        */
         newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;

        /*
          IGNPAR  : ignore bytes with parity errors
          ICRNL   : map CR to NL (otherwise a CR input on the other computer
                    will not terminate input)
          otherwise make device raw (no other input processing)
        */
         newtio.c_iflag = IGNPAR | ICRNL;

        /*
         Raw output.
        */
         newtio.c_oflag = 0;

        /*
          ICANON  : enable canonical input
          disable all echo functionality, and don't send signals to calling program
        */
         newtio.c_lflag = ICANON;

        /* 
          initialize all control characters 
          default values can be found in /usr/include/termios.h, and are given
          in the comments, but we don't need them here
        */
         newtio.c_cc[VINTR]    = 0;     /* Ctrl-c */ 
         newtio.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
         newtio.c_cc[VERASE]   = 0;     /* del */
         newtio.c_cc[VKILL]    = 0;     /* @ */
         newtio.c_cc[VEOF]     = 4;     /* Ctrl-d */
         newtio.c_cc[VTIME]    = 0;     /* inter-character timer unused */
         newtio.c_cc[VMIN]     = 1;     /* blocking read until 1 character arrives */
         newtio.c_cc[VSWTC]    = 0;     /* '\0' */
         newtio.c_cc[VSTART]   = 0;     /* Ctrl-q */ 
         newtio.c_cc[VSTOP]    = 0;     /* Ctrl-s */
         newtio.c_cc[VSUSP]    = 0;     /* Ctrl-z */
         newtio.c_cc[VEOL]     = 0;     /* '\0' */
         newtio.c_cc[VREPRINT] = 0;     /* Ctrl-r */
         newtio.c_cc[VDISCARD] = 0;     /* Ctrl-u */
         newtio.c_cc[VWERASE]  = 0;     /* Ctrl-w */
         newtio.c_cc[VLNEXT]   = 0;     /* Ctrl-v */
         newtio.c_cc[VEOL2]    = 0;     /* '\0' */

        /* 
          now clean the modem line and activate the settings for the port
        */
         tcflush(fd, TCIFLUSH);
         tcsetattr(fd,TCSANOW,&newtio);

        /*
          terminal settings done,
        */
              /* loop until we have a terminating condition */
         /* read blocks program execution until a line terminating character is 
            input, even if more than 255 chars are input. If the number
            of characters read is smaller than the number of chars available,
            subsequent reads will return the remaining chars. res will be set
            to the actual number of characters actually read */
            res = read(fd,buf,255); 
            buf[res]=0;             /* set end of string, so we can printf */

         /* restore the old port settings */
         tcsetattr(fd,TCSANOW,&oldtio);
    return buf; 
        }


int main( int argc, const char* argv[] ){
    printf("%s",readline());
    return 42;
}

Note but it seems very error prone, ideally it would sent me the next string until it meets a newline character and then returns it, currently it does return a full line but said line often isn't finished or is even mangled with the following Arduino example code:

int i=0;
void setup(){
  Serial.begin(9600);
}

void loop(){

  Serial.println("abc");
  Serial.println("bcd");
  delay(100);
}

I had following output:

$ ./a.out 
abc
./a.out 
d
./a.out 
abc
./a.out 
bcd
./a.out 
abc
./a.out 
abd

So that means bcd was largely lost we have a bcd which is just mangled data a lone d that should have been part of bcd.

Another problem is that this code takes a long time to realize it if there is no data on the serial line (rather then just return an array of nulls or something like that). As I want to be able to use this code to poll for new data on the serial line this delay is anoying Anyone know how to improve this implementation?

  • Why don't you try and add a pause between each println? It seems like you are printing the output to the linux console. Whichever application you're using to compile the code needs to be configured to use the console you are using. – WickedFan Jan 13 '15 at 17:48
  • 1
    The code you are asking about isn't on the Arduino. I assume it is on Raspberry Pi. If so you should ask there raspberrypi.stackexchange.com/questions – Milliways Jan 14 '15 at 5:45
  • It's on a computer talking with an arduino – Thijser Jan 14 '15 at 8:12
  • "It's on a computer" ... so ask the question on a site devoted to this computer. The Arduino is most likely irrelevant to writing code to receive serial on an undefined computer (presumably 'NIX). I could suggest some code for a Pi. – Milliways Jan 14 '15 at 9:37
  • I have no knowledge of how the arduino's serial data works, are the settings correct? Those are all arduino specific, that is also about 80% of the code so yes 80% of the computer code is arduino specific and the entire arduino code is arduino specific landing at around 90% in total. – Thijser Jan 14 '15 at 9:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.