Can't read Arduino printings in C/C++ (Linux)

Hello there.

Arduino is printing some data on serial, and I just want to "read" it in C/C++. However, I've tried pretty much everything, and can't get it working.

Screen is able to listen the port just as Arduino's IDE Serial Monitor does.

However, even after configuring the port using the stty command as described here the tail command couldn't listen it.

LibSerial doesn't work also; and this program returns garbage data.

I don't know any other way to do this, and I also tried the entire tutorial from combustory.com. Tail returns nothing at all.

I'll be very grateful if anyone can help me. I just want to "read" the values into a C/C++ (doesn't matter which) program.

Thank you very much.

@2stl

Tail returns nothing at all.

Well, let's get started with something simple just to make sure things are connected and to see whether the port is working.

Here's my sketch:

void setup()
{
    Serial.begin(9600);
}

void loop()
{
    Serial.print("Hello from Arduino at ");
    Serial.println(millis());
    
    delay(1000);
}

I uploaded the sketch to my (homebrew) ATmega328p board. I pressed and held the Reset button on the '328p board and entered the following from a Linux command line (Centos 5.5):


stty -F /dev/ttyUSB0 9600;tail -f /dev/ttyUSB0


I released the Reset button and here's what I saw:


Hello from Arduino at 20
Hello from Arduino at 1045
Hello from Arduino at 2072
Hello from Arduino at 3099
Hello from Arduino at 4126
Hello from Arduino at 5153
Hello from Arduino at 6180
.
. (Similar stuff until I hit Ctrl-C on the workstation.)
.

Note that I always start at the fairly low speed of 9600 bits/sec. Then I go for 115200 bits/sec. (It still works for this.)

Regards,

Dave

Footnote:
Instead of manual reset, I can can do stty hupcl to toggle the port's DTR signal to reset the Arduino. This may or may not work for other systems, so I would just stick to the manual way for now.

Once you have verified that the port connection works, you can write a simple C program for your Linux workstation to read from the Arduino:

/*
   Simple read-only program for ttyUSB0 at 9600 bits/sec
   Non-printing characters are shown in <hex>.

   ---davekw7x---

*/

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main()
{
    char *inname = "/dev/ttyUSB0";
    int baud = 9600;
    FILE *infile = fopen(inname, "r");
    char inbuf[80];

    /*
       Instead of all of the "usual" stuff to set up
       the input port, I'll just cheat with stty
    */
    sprintf(inbuf, "stty -F %s %d raw", inname, baud);
    system(inbuf);
    if (!infile) {
        fprintf(stderr, "Can't open %s for reading.\n", inname);
        exit(EXIT_FAILURE);
    }
    printf("Opened %s for reading\n.", inname);
    while (1) {
        int inchar;
        inchar = (unsigned int) getc(infile);
        if (isprint(inchar)) {
            printf("%c", inchar);
        }
        else {
            printf("<%02x>", inchar);
            if (inchar == '\n') {
                printf("\n");
            }
        }

    }
    /* It's an infinite loop: Use ctrl-c to quit the program */
}

With this I get


.Hello from Arduino at 20<0d><0a>
Hello from Arduino at 1045<0d><0a>
Hello from Arduino at 2072<0d><0a>
Hello from Arduino at 3099<0d><0a>
Hello from Arduino at 4126<0d><0a>
Hello from Arduino at 5153<0d><0a>
Hello from Arduino at 6180<0d><0a>
.
. (Similar stuff until I hit Ctrl-C on the workstation)
.

I'm thinking that information for additional steps (for the workstation) beyond this would be for some place other than the "Arduino Syntax and Programs" board.

Bottom line: Once you have determined that the port can be configured to listen to the Arduino, the rest is "just software." (Famous last words.)

You can write a simple sketch to make the Arduino listen to the port and echo what it sees. Then you can write a simple C program to send something and see if it gets it back. Etc.

Then you may be ready to use OPC (you know, Other People's Code---that you copy from the Web) to do something more interesting. (Or, even more interesting: write your own code to do something even more interesting.)

Anyhow, here's a possible starting point.

Regards,

Dave

Footnote:
After you have been mucking around with the port, sometimes it is left in some state that the command-line stuff (like tail) doesn't give the same results unless you reset everything about the port. The "right" thing to do is not to use stty (in a program or from a command line), but stty may be the easiest way to get started. (By the "right" way, I mean to use low level open() instead of fopen() then use tcsetattr() and/or tcsetraw() to define specific port attributes and use read() to get the bytes. Stuff like that.)

Yes man! It's working! I didn't know it was necessary to hold the reset.

Now... is it okay to keep calling "tail" to get the data?

Thank you very much Dave! :slight_smile:

is it okay to...

A major part of my philosophy in life came from my dear old granny: "Pretty is as pretty does."

If it's working, it's pretty.

If it meets your needs, use it. If you need something more 'sophisticated' you at least have a starting point that shows that 'something' is happening on the port and that allows you to see something about what the Arduino is writing.

Regards,

Dave

Footnote:
Another part of my philosophy is that one of the major keys to happiness is: Expectations Management.

That came from my drunken uncle, who was known to say stuff like, "You can't fall out of bed if you sleep on the floor!"