Pausing/Unpausing Serial comm btwn Processing and Arduino

I've got a question about stopping and starting serial communication. I've written some code to pass five numbers between processing (on my mac) and an Arduino (a Sparkfun redboard). Here's my processing:

import processing.serial.*;
Serial arduinoPort;
int incremental = 0;
int incre = 0;
boolean paused = true;
 
void setup() {
   size(400, 600);  
   arduinoPort = new Serial(this,Serial.list()[2], 9600); //change to correct port number
   delay(1000);
   arduinoPort.write("0,0,0,0,65,");
}
 
void draw(){ 
}
 
void serialEvent(Serial arduinoPort) { 
  String answer = arduinoPort.readStringUntil('\n');
  if (answer != null) {
    println("returned: "+answer);
    if (!paused){
      String[] fromArduino = split(answer, ' ');
      if(fromArduino[4].equals("65") == true) {
        incremental++;
      } else {
        delay(1000);
      }
      arduinoPort.write(incremental+",25,26,"+incre+",65,");
   
    }
  } 
}
 
void keyPressed() {
 // if paused == true make it false
 if(paused == true) {
  paused = false; 
  println("go"); 
  arduinoPort.write("0,0,0,"+incre+",65,"); //ending comma important to stop arduino searching. 
  incre++;   
 } else {
  paused = true;
  println("stop");
 }
}

Where "incremental" is a variable that simply counts up from 0 for each sent packet, and "incre" is a variable that only counts up after each pause cycle. The other numbers sent are just static place holders for future data, and the last number, "65," is for handshaking. Basically, processing sends a string of numbers and commas to the Arduino.

And here's my Arduino code:

const int NUMBER_OF_FIELDS = 5; // how many comma-separated fields we expect
int fieldIndex = 0;             // the current field being received
int values[NUMBER_OF_FIELDS];   // array holding values for all the fields
 
int ledPin = 13;
 
void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT); 
}
 
void loop() {
}
 
void serialEvent() {
  while (Serial.available() == 0) {  }
  if( Serial.available()) {
    for(fieldIndex = 0; fieldIndex < 5; fieldIndex ++){
      values[fieldIndex] = Serial.parseFloat(); // get a numeric value
    }
    fieldIndex = 0; //reset index
     
    if(values[4] == 65){
      //do stuff, run motors, etc.
      digitalWrite(ledPin, HIGH);

    Serial.print(values[0]);
    Serial.print(" ");
    Serial.print(values[1]);
    Serial.print(" ");
    Serial.print(values[2]);
    Serial.print(" ");
    Serial.print(values[3]);
    Serial.print(" ");
    Serial.print(values[4]);
    Serial.println(" "); //println important. processing looks for line return
    }else{
      digitalWrite(ledPin, LOW);
      Serial.println("0 0 0 0 0");
    }
  values[0] = 0; //clear array
  values[1] = 0;
  values[2] = 0;
  values[3] = 0;
  values[4] = 0;
  }
}

Where the Arduino parses in a set of five float numbers into an index. If the last number is "65" then it turns on an LED at pin 13, sends back to processing what it received and clears out all the information (in the future it would run motors or do something else also).

Timeline:

  1. Processing sends "0,0,0,0,65," to Arduino in its setup.
  2. Arduino listens for a serialevent, then reads the five numbers into an array.
  3. If the last number is "65" (a static number), then the Arduino mirrors back to processing the info it received (with spaces instead of commas and a line break at the end).
  4. Processing listens with serialevent for incoming data and buffers until the line break.
  5. Processing chops the received string into an array. If the last value equals "65" it increments and sends data. Etc.
  6. Processing, listening for a keypressed event (any key press), can pause this communication. If it pauses, data is no longer sent to the Arduino.
  7. On a second keypressed event, the loop is unpaused, "incre" is incremented, and data continues to be sent.

My question:

On a pause, data stops being sent. If I pause and unpause quickly, it takes 4-5 seconds for proper data to resume. If I pause, wait longer than 4-5 seconds, and then unpause, no issues. Before I had the "Serial.println("0 0 0 0 0");" in the Arduino code, I could see that the numbers were getting mixed up somewhere. The 65 wasn't always received last. What is going on here? is this a buffer issue with the Arduino? There is something going on with the serial communication? I'm trying to make a fairly robust handshake serial connection between the two devices. Can someone point me to how I can make this so that I can pause/unpause this communication without issue?

Here's a sample processing readout (mid flow during a pause/unpause event):

returned: 261 25 26 4 65
 
returned: 262 25 26 4 65
 
stop
returned: 263 25 26 4 65
 
go
returned: 0 0 0 0 0
 
returned: 0 0 0 0 0
 
returned: 0 0 0 0 0
 
returned: 0 0 0 0 0
 
returned: 0 0 0 0 0
 
returned: 263 25 26 5 65
 
returned: 263 25 26 5 65
 
returned: 264 25 26 5 65

I know it's kind of long and complex, but I've narrowed down the code as much as I could to describe the issue. I've only been using Processing and Arduino about a month and I'd really appreciate any help or pointers. Thanks, Blake

Here is some alternate Arduino code that returns the mixed up serial data to Processing instead of "0 0 0 0 0". In this case, the serial communication does not recover after 4-5 seconds, it just continues to be scrambled. To fix, one must pause again, wait for five seconds, and unpause.

Arduino (uses same Processing code as above):

const int NUMBER_OF_FIELDS = 5; // how many comma-separated fields we expect
int fieldIndex = 0;             // the current field being received
int values[NUMBER_OF_FIELDS];   // array holding values for all the fields

int ledPin = 13;

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
pinMode(ledPin, OUTPUT); 

}

void loop() {
  // put your main code here, to run repeatedly:

}

void serialEvent() {
  while (Serial.available() == 0) {  }
  
  if( Serial.available()) {
    for(fieldIndex = 0; fieldIndex < 5; fieldIndex ++){
      values[fieldIndex] = Serial.parseFloat(); // get a numeric value
    }
    fieldIndex = 0; //reset index
    
    if(values[4] == 65){
      //do stuff, run motors
    digitalWrite(ledPin, HIGH);
      
    Serial.print(values[0]);
    Serial.print(" ");
    Serial.print(values[1]);
    Serial.print(" ");
    Serial.print(values[2]);
    Serial.print(" ");
    Serial.print(values[3]);
    Serial.print(" ");
    Serial.print(values[4]);
    Serial.println(" "); //println important. processing looks for line return
    }else{
    digitalWrite(ledPin, LOW);
    
    Serial.print(values[0]);
    Serial.print(" ");
    Serial.print(values[1]);
    Serial.print(" ");
    Serial.print(values[2]);
    Serial.print(" ");
    Serial.print(values[3]);
    Serial.print(" ");
    Serial.print(values[4]);
    Serial.println(" "); //println important. processing looks for line return
    //Serial.println("0 0 0 0 0");
    }
  values[0] = 0;
  values[1] = 0;
  values[2] = 0;
  values[3] = 0;
  values[4] = 0;
  }
}

And returned to Processing readout:

returned: 33 25 26 2 65 

returned: 34 25 26 2 65 

returned: 35 25 26 2 65 

returned: 36 25 26 2 65 

returned: 37 25 26 2 65 

returned: 38 25 26 2 65 

stop
returned: 39 25 26 2 65 

go
returned: 0 0 0 0 2 

returned: 65 39 25 26 3 

returned: 65 39 25 26 3 

returned: 65 39 25 26 3 

returned: 65 39 25 26 3 

returned: 65 39 25 26 3 

returned: 65 39 25 26 3 

returned: 65 39 25 26 3 

returned: 65 39 25 26 3 

stop
returned: 65 39 25 26 3 

returned: 65 0 0 0 0 

go
returned: 0 0 0 3 65 

returned: 40 25 26 4 65 

returned: 41 25 26 4 65 

returned: 42 25 26 4 65 

returned: 43 25 26 4 65 

returned: 44 25 26 4 65 

returned: 45 25 26 4 65

Thanks,
Blake

Your Arduino code is not troubling to figure out when the data starts or ends, and the parseInt() function blocks until its timeout is reached.

Serial.available() would return true even if there is only one character in the buffer and the Arduino would normally be finished processing that long before another character arrives.

Have a look at the examples in serial input basics (especially the 3rd example) which receive the data without blocking. It receives all the data before doing anything else. There is also a parse example.

...R

Thanks so much. I've read through your examples and tried out some of the code, and will continue to work towards a resolution. Thanks again.

Blake