Significant delay with serial communication to Arduino

Hello, I am currently attempting to make a simple bluetooth car controlled by an Arduino. I am attempting to control the car from my computer through the use of a key listener. When I run my code, the key listener works and the car responds, but it responds with a 5-10 second delay. I have read in other posts that there is an internal buffer within the processing IDE that causes this delay, in which case I assume there is no way of fixing the delay and I will have to resort to another Java IDE like Eclipse. However, if there is a way of fixing it, or at least reducing it to a usable amount, I would greatly appreciate it. Below I have posted both my arduino code and processing code (processing on top, arduino code below).

import processing.serial.*;
Serial myPort;
String ledStatus="LED: OFF";

void setup(){
  size(450, 500);
  myPort = new Serial(this, "COM6", 9600); // Starts the serial communication
  myPort.bufferUntil('\n'); // Defines up to which character the data from the serial port will be read. The character '\n' or 'New Line'
}
void serialEvent (Serial myPort){ // Checks for available data in the Serial Port
  ledStatus = myPort.readStringUntil('\n'); //Reads the data sent from the Arduino 
}

void draw(){
  background(237, 240, 241);
  fill(20, 160, 133); // Green Color
  stroke(33);
  strokeWeight(1);
  rect(50, 100, 150, 50, 10);  // Turn ON Button
  rect(250, 100, 150, 50, 10); // Turn OFF Button
  fill(255);
  
  textSize(32);
  text("Forward",60, 135);
  text("Back", 255, 135);
  textSize(24);
  fill(33);
  text("Status:", 180, 200);
  textSize(30);
  textSize(16);
  text("Program made by ", 80, 320);

  text(ledStatus, 155, 240); // Prints the string comming from the Arduino
}

 @Override
 public void keyPressed(KeyEvent e) {
  //keyPressed = Invoked when a physical key is pressed down. Uses KeyCode, int output
  switch(e.getKeyCode()) {
  case 87:myPort.write('W'); // Sends the character 'W'
    // Highlighs the buttons in red color when pressed
    stroke(255,0,0);
    strokeWeight(2);
    noFill();
    rect(50, 100, 150, 50, 10);
   break;
  case 83: myPort.write('S');
  stroke(255,0,0);
    strokeWeight(2);
    noFill();
    rect(250, 100, 150, 50, 10);
    break; 
  }
 }
 
 @Override
 public void keyReleased(KeyEvent e) {
  //keyReleased = called whenever a button is released
  myPort.write('J');
 }

Arduino code:

void loop() {

//char state = Serial.read();


  if(Serial.available() > 0){ // Checks whether data is comming from the serial port
   state = Serial.read(); // Reads the data from the serial port
 }

 if (state == 'J') {
  halt(); // Turn LED OFF
  delay(1000);
  Serial.println("Halt");
 // state = 'J';
 }
 else if (state == 'S') {
  forward();
  delay(1000);
  Serial.println("Back");
 //state = 'J';
 } 
 else if (state == 'W') {
  back();
  delay(1000);
  Serial.println("Forward");
 //state = 'J';
 } 

I have much more Arduino code than this, and the char variable is defined elsewhere, but this was the most relevant. I would appreciate any help, thanks!

Seems to be pretty fast on my Mac after REMming out the delay(1000); calls on the arduino side. You’re also calling the functions before you call Serial.print() if you’re judging Processing by how fast it prints the return from Arduino. Presumably you’re using a motor driver and there could be some lag there. What are you using for Bluetooth?

2 Likes

My gosh you are absolutely right! I did not think the delay functions would have made as large of an impact as they did, but removing them made it run incredibly smooth. Thanks a lot!

Hello @somebody,

You are sending repeating characters on a key press and at the receiving ending waiting 1000ms (blocking for 1 sec) after each character is received and the delays will quickly accumulate.

Consider this code which only sends a single character on a key press:

Processing side:

char lastKey;

void setup()
  {
  size(200, 200);
  }

void draw()
  {
  }

void keyPressed() 
  {
  if(key != lastKey) // Comment this for repeating keys
    {
    println(key);
    lastKey = key;
    }
   }
 
 public void keyReleased() 
   {
   println('!');
   }

I also did something similar for the receiving end so I am only sending one character with Processing and Arduino is responding with one character.

Arduino side:

    if (state != lastState)
      {  
      if (state == 'J') 
        { 
        Serial.println("Halt");
        }
      else if (state == 'S') 
        {
        Serial.println("Back");
        }
      else if (state == 'W') 
        {
        Serial.println("Forward");
        }
      }
    lastState = state;

This way the delay() is what you set and it does not accumulate!

Reference:
https://randomnerdtutorials.com/why-you-shouldnt-always-use-the-arduino-delay-function/

:)