junk on serial port, buffer problem?

Hi,

I'm a beginner at Arduino and serial port programming. I'm trying to communicate with my Uno over USB to read a varying voltage, and gather a bunch of data points of (time, voltage). The sketch just calls Serial.println in loop(), sending the current millis() time, and a voltage. On my laptop I have a C program that opens the serial port, reads the lines. They look like:

1300 450 1302 451 1305 449

This seems to work, except right when the program starts, it sees some lines like:

16375 485 16405 483 138 480 16167 484 0 484 23 483 ... now it's fine ...

The times appear to be high, mixed with junk, and then reset to 0. Does this mean the board is crashing and restarting?

Is there a buffer overflowing somewhere? I'm guessing this isn't the right way to use a serial port. Maybe there has to be back and forth? And one side can only send when the other says it's ready?

thanks, Rob

The times appear to be high, mixed with junk, and then reset to 0. Does this mean the board is crashing and restarting?

The board is probably resetting when the USB serial port is opened.

Is there a buffer overflowing somewhere? I'm guessing this isn't the right way to use a serial port. Maybe there has to be back and forth? And one side can only send when the other says it's ready?

Be nice to see some code, to know what is happening.

Nothing will be sent by the program until the serial port is ready. No handshaking is required to make that happen. The millis() value is increasing, from reset on. It does not take a while to stabilize. Whatever is defining the voltage might.

The only read possibility is in your code, which we can't see.

Okay here is the Arduino code, and the computer’s C code (some non-essentials removed for clarity).

int halfPeriod = 250;  // ms
int curr = LOW; 
int ledPin = 2;
unsigned long lastTime;

void setup()
{
  Serial.begin(57600);
  pinMode(ledPin, OUTPUT);  
  lastTime = millis();
  digitalWrite(ledPin, curr);
}

void loop()
{
  unsigned long currTime = millis();
  int solarVoltage = analogRead(A0);
  long dt = currTime - lastTime;
  if (dt >= halfPeriod) {
     curr = curr == LOW ? HIGH : LOW;
     digitalWrite(ledPin, curr);
     lastTime = currTime;
  }
   
  String out = "";
  out = out + currTime + " " + curr + " " + solarVoltage;
  Serial.println(out); 
}
    int count = 500;
    int *points = (int*)malloc(count * 3 * sizeof(int));

    int fd = open(serial_port, O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd < 0) {
        perror("open port");
        return;
    }

    fcntl(fd, F_SETFL, 0);
    termios opts;
    tcgetattr(fd, &opts);
    //int speed = B115200;
    int speed = B57600;
    cfsetispeed(&opts, speed);
    cfsetospeed(&opts, speed);
    opts.c_cflag |= (CLOCAL | CREAD);
    opts.c_lflag &= !(ICANON | ECHO | ECHOE | ISIG);  // raw mode
    //    opts.c_oflag &= !(OPOST);
    opts.c_cc[VMIN] = 0;
    opts.c_cc[VTIME] = 100;      
    tcsetattr(fd, TCSANOW, &opts);

    for (int i=0; i<count; i++) 
    {
        char buf[64];
        char *p = buf;
        char *end = buf + 64;
        int t, a, b;
        
        // read a line
        while (p < end) 
        {
            int r = read(fd, p, 1);
            if (r != 1) {
                perror("read");
                return;
            }
            if (*p == '\n') {
                *p = 0;
                break;
            }
            p++;
        }
        if (p == end) {
            printf("didn't read newline?\n");
            return;
        }
        
        sscanf(buf, "%d %d %d", &t, &a, &b);
        
        int *point = points + i*3;
        point[0] = t;
        point[1] = a;
        point[2] = b;
    }

    plot_data(points, count);
    close(fd);

Not dived deep into it but I notice you set the baudrate in the C program after the port is opened. Could that be the cause?

Furthermore I noticed in your code there are a few returns that do not close the fd properly.

Finally points = malloc()-ed but never free()-ed .... so there is leaking some memory.

I think in C I have to set the baud rate after it's opened, since I call tcsetattr with the fd and the options that include the baud rate.

points is really a member variable, and that gets free'd. I declared it local for posting this code. I just cleaned up the fd problem you mentioned, but the original problem persists.

try a lower baudrate than - Serial.begin(57600); - The UNO seems to have some trouble with this baudrate

Arduino code: (not THE problem but) curr = !curr; should work too

update: C code fcntl(fd, F_SETFL, 0); returns a value which is not checked.

Are you on linux or PC? (linux) found this one - http://www.comptechdoc.org/os/linux/programming/c/linux_pgcserial.html

Tried a few higher and lower baud rates. Same problem. In one of the runs the laptop read this line from the serial port.

15660 0 48015625 0 480

ie, two lines with a missing \n, with the times in the wrong order. This was in the midst of reading lines perfectly.

Have you tried another PC with a simple terminal program like putty?

Just want to determine if the problem is in Arduino, Cable or C program.

The board is probably resetting when the USB serial port is opened.

This is part or all of my problem. I’ve changed my sketch to do Serial.println("starting") in setup(), and the code on the computer looks for that before reading data. So far it’s working.