Serial Communication bottleneck

Hi,

I have a serious problem with how the PC is receiving serial data from Arduino. I am trying to send a large amount of data from arduino to pc using serial comm. When have the serial port window open, the data steams nicely and there is no lag between sending and receiving. But when I use a Processing program to read this data stream and store it in an array, there is a huge amount of lag. For example, I am streaming data from arduino for 5 seconds and it takes an additional 13 seconds for the processing program to finish recording data into an array. I am reading the data like this on the processing side:

case 2: // write incomming data to large array
      if( myPort.available() > 1 ) {
        myData = myPort.readStringUntil('\n'); 
      }
      if ( myData == null ) {
        myState = 3; 
        break;
      } else if ( myData != null ) {
        Data[n] = myData; 
        n++; 
        myData = null; 
      }
      
      break;

Someone please tell me what the hell the processing program is doing that it is taking so long to finish this simple task.
Is there a way to make it faster?

Thanks
PS. I know my post is more directed towards processing, but I thought there are more people here too.

Someone please tell me what the hell the processing program is doing

How the hell should we know? You only posted a small portion of it.

Hi Paul,

You can assume the whole processing program is just reading and storing the data into an array (the code). I tried this myself to narrow down where the lag is occurring. The 13 second lag is because of this section.
The Arduino is sending 6 sensor values every 5 ms for 5 seconds and then it stops.

Thanks

You can assume the whole processing program is just reading and storing the data into an array

You could post all of your code, too. I wonder which would work better.

I can't post the code.
this is the only relevant part that I am having problems with.

I can't post the code.

Why not?

If size is an issue, use the Additional Options... link to add attachments.

There are so many possibilities as to what the problem might be that I won't even venture a guess without seeing all of the code.

The code is intellectual property of my company. Thats why...

Let me ask my question another way.
Is there any other way make the comm link between arduino and processing faster (not necessarily serial) ? I need at least 1MB/sec of transfer rate.

Thanks

You could try removing unnecessary code...

case 2: // write incomming data to large array
      if( myPort.available() > 1 ) {
        myData = myPort.readStringUntil('\n');    // ASCII is not a good transfer medium for lots of data, try a binary encoding, especially if you need 1 MB/s.
      }
      if ( myData == null ) {
        myState = 3; 
        break;   // This is not required, if this 'if' statement is true, then the next code block in the 'else' section will not run anyway.
      } else if ( myData != null ) {     // This if statement is not required, the 'else' implies the opposite of the original 'if', you don't need to re-check it.
        Data[n] = myData; 
        n++; 
        myData = null; 
      }
      
      break;

Is there any other way make the comm link between arduino and processing faster (not necessarily serial) ? I need at least 1MB/sec of transfer rate.

The only link between the Arduino and Processing is the serial port. You do not have to send ASCII data, though. You could send binary data. That's faster for the Arduino AND for Processing. You aren't going to get 1Mb/sec, but that number is meaningless anyway.

Thank you guys for the input.

I tested another program to measure the speed of the serial data comming in. Here it is: (it is a modification of the example code on processing website)

import processing.serial.*; 
 
Serial myPort;    // The serial port
PFont myFont;     // The display font
String inString;  // Input string from serial port
int lf = 10;      // ASCII linefeed 
 
void setup() { 
  size(400,200); 
  println(Serial.list()); 
  myPort = new Serial(this, "COM5", 57600); 
  myPort.bufferUntil(lf); 
} 
 
void draw() { 
  background(0); 
  text("received: " + inString, 10,50); 
} 
 
void serialEvent(Serial p) { 
  inString = p.readStringUntil('\n'); 
}

This code displays the data steam as fast as the arduino.
I think the reason that the original code is slow is because of write speed of processing. I am writing the serial data into an array and I think thats why this thing is very slow.
Correct me if I am wrong.
Is there a way to store the data faster into the Data[] array.

Thanks

Is there a way to store the data faster into the Data[] array.

Without knowing the type of Data[], or how many elements are in the array, we'd just be guessing.

Why is it necessary to save the data in an array? What kind of data is it?

 if( myPort.available() > 1 ) {
        myData = myPort.readStringUntil('\n'); 
      }

myPort.readStringUntil('\n'); is blocking!!

you test if there is more than 1 character and you are trying to read until you encounter a \n. If that \n is not in the buffer it blocks until it is.

Solution, read and process one char at a time from serial, or at max the number returned by serial.available()

Hi Rob,

Thank you for taking the time to recognize this. You are absolutely right!!! thanks a lot for that.

The fact is that this line is blocking everything: myPort.readStringUntil('\n');
The 'if' statement has nothing to do with it. I commented out the if statement and it still was lagging.

Now, how do I process each character and achieve the same result as I am trying to do, but much faster?

Thanks

Now, how do I process each character and achieve the same result as I am trying to do, but much faster?

First off, decide whether that blocking is really an issue. If all you are doing is waiting for data, then whether you loop in the draw() function 100 times before the \n arrives, or a 1000 times doesn't matter, does it?

It isn't clear whether your snippet of code is in draw() or in serialEvent(). If it is in draw(), you should move it to serialEvent(). If you don't have a call to myPort.bufferUntil('\n') in setup(), you should have. That way, the serialEvent() method will only be called when the \n arrives.