Unable to update int from serialReadStringUntil while in draw()

please format code with </> button * homework policy * asking questions

Hello!

I am having trouble with communication between Processing and Arduino. I’m trying to run specific functions based on readings the Arduino is outputting. If the Arduino is printing “not initialized” for example, I would like to run a bootScreen() function I previously defined in Processing. I am using a switch/case and if statements to accomplish this.

The problem that I’m running into is that when the Arduino changes what it’s printing to Processing, my program won’t update and run the correct function. I know that draw() is looping, but I don’t know why the if statements aren’t updating the number that controls the switch/case based upon the Arduino’s output.

Processing Code:

import processing.serial.*;
import controlP5.*;
Serial myPort;
ControlP5 bootSc, calSc, mainSc;
int n;

void setup() {
  myPort = new Serial(this, Serial.list() [1], 11520);
  size (480, 320);

  // Sets up screens
  bootSc = new ControlP5(this);
  calSc = new ControlP5(this);
  mainSc = new ControlP5(this);


  // Boot screen buttons
  // Initial calibration button
  int calWidth = 115;
  int calHeight = 50;
  bootSc.addButton("calButt").setSize(calWidth, calHeight)
    .setPosition(int(width/2)-int(calWidth/2), int(height/2)-int(calHeight/2))
    .setCaptionLabel("Calibrate")
    .setColorBackground(color(0, 52, 255))    
    .setFont(createFont("Arial", 20));

  // Screen title name
  String text = "Please Calibrate Before Use";
  int size = 30;
  textSize(size);
  float sw = textWidth(text);
  bootSc.addTextlabel("title").setPosition(int(width/2)-int(sw/2), 10)
    .setText(text)
    .setFont(createFont("Arial", size))
    .setColorValue(color(0));

  // Calibration Screen
  // Calibration Screen title name
  text = "Calibration";
  size = 30;
  textSize(size);
  sw = textWidth(text);
  calSc.addTextlabel("calTitle").setPosition(int(width/2)-int(sw/2), 10)
    .setText(text)
    .setFont(createFont("Arial", size))
    .setColorValue(color(0));

  // Main Screen 
  // Screen title name
  text = "RGB Readings";
  size = 30;
  textSize(size);
  sw = textWidth(text);
  mainSc.addTextlabel("mainTitle").setPosition(int(width/2)-int(sw/2), 10)
    .setText(text)
    .setFont(createFont("Arial", size))
    .setColorValue(color(0));

  // show boot screen
  bootSc.show();  
  // Hides the calibration and main screen
  calSc.hide();
  mainSc.hide();
}



void draw() {
  background(255);
  if (readArduino().equals("not initialized") == true)
    n = 1;
  if (readArduino().equals("white standard") == true || readArduino().equals("black standard") == true)
    n = 2;

  switch(n) {
  case 1:
    bootScreen();
    break;
  case 2:
    cal();
    break;
  default:
    mainScreen();
    break;
  }


  println(readArduino());
  println(n);
}

String readArduino() {
  while (myPort.available() > 0) {
    String readings = trim(myPort.readStringUntil('\n'));
    return readings;
  } 
  return null;
}


// Boot Screen
void bootScreen() {  
  calSc.hide();
  mainSc.hide();
  bootSc.show();
}

// Call Button on boot screen
void calButt() {
  myPort.write("calibrate\n");
}

// Calibration Screen
void cal() {
  bootSc.hide();
  mainSc.hide();
  calSc.show();
}

void mainScreen(){
 bootSc.hide();
 calSc.hide();
 mainSc.show();  
}

Arduino Code:

int n = 1;
String s = "default";
void setup() {
  SerialUSB.begin(115200);
}

void loop() {
  /*If the button is pressed, it sends "calibrate" 
  and the arduino counter updates what message it is 
  sending to Processing.
  */
  while (SerialUSB.available() > 0) {
    s = SerialUSB.readStringUntil('\n');
  if (s == "calibrate")
    n = n +1;
  }

  
  switch (n) {
    case 1:
      SerialUSB.println("not initialized");
      break;
    case 2:
      SerialUSB.println("white standard");
      break;
    case 3:
      SerialUSB.println("black standard");
      break;
    default:
      SerialUSB.println("main screen");
      break;
  }

}

The interesting part is that if I update what the Arduino is printing, close the processing program and open it again, the processing program selects the correct function.

I’m open to any advice on how I can improve this. Thank you for your time.

I found the error in my code. Here’s what I did. I removed the readArduino() function. I moved the while (myPort.available() > 0) loop into the draw() loop. I then had the myPort.readStringUntil('\n') update a String variable.

Here’s the updated Processing code:

import processing.serial.*;
import controlP5.*;
Serial myPort;
ControlP5 bootSc, calSc, mainSc;
int n;
String readings;

void setup() {
  myPort = new Serial(this, Serial.list() [1], 11520);
  size (480, 320);

  // Sets up screens
  bootSc = new ControlP5(this);
  calSc = new ControlP5(this);
  mainSc = new ControlP5(this);


  // Boot screen buttons
  // Initial calibration button
  int calWidth = 115;
  int calHeight = 50;
  bootSc.addButton("calButt").setSize(calWidth, calHeight)
    .setPosition(int(width/2)-int(calWidth/2), int(height/2)-int(calHeight/2))
    .setCaptionLabel("Calibrate")
    .setColorBackground(color(0, 52, 255))    
    .setFont(createFont("Arial", 20));

  // Screen title name
  String text = "Please Calibrate Before Use";
  int size = 30;
  textSize(size);
  float sw = textWidth(text);
  bootSc.addTextlabel("title").setPosition(int(width/2)-int(sw/2), 10)
    .setText(text)
    .setFont(createFont("Arial", size))
    .setColorValue(color(0));

  // Calibration Screen
  // Calibration Screen title name
  text = "Calibration";
  size = 30;
  textSize(size);
  sw = textWidth(text);
  calSc.addTextlabel("calTitle").setPosition(int(width/2)-int(sw/2), 10)
    .setText(text)
    .setFont(createFont("Arial", size))
    .setColorValue(color(0));

  // Main Screen 
  // Screen title name
  text = "RGB Readings";
  size = 30;
  textSize(size);
  sw = textWidth(text);
  mainSc.addTextlabel("mainTitle").setPosition(int(width/2)-int(sw/2), 10)
    .setText(text)
    .setFont(createFont("Arial", size))
    .setColorValue(color(0));

  // show boot screen
  bootSc.show();  
  // Hides the calibration and main screen
  calSc.hide();
  mainSc.hide();
}



void draw() {
  background(255);

  while (myPort.available() > 0) {
    readings = trim(myPort.readStringUntil('\n'));
  }

  if (readings.equals("not initialized") == true)
    n = 1;
  if (readings.equals("white standard") == true || 
    readings.equals("black standard") == true)
    n = 2;

  switch(n) {
  case 1:
    bootScreen();
    break;
  case 2:
    cal();
    break;
  default:
    mainScreen();
    break;
  }


  //println(readArduino());
  //println(n);
}

//String readArduino() {
//  while (myPort.available() > 0) {
//    String readings = trim(myPort.readStringUntil('\n'));
//    return readings;
//  } 
//  return null;
//}


// Boot Screen
void bootScreen() {  
  calSc.hide();
  mainSc.hide();
  bootSc.show();
}

// Call Button on boot screen
void calButt() {
  myPort.write("calibrate\n");
}

// Calibration Screen
void cal() {
  bootSc.hide();
  mainSc.hide();
  calSc.show();
}

void mainScreen() {
  bootSc.hide();
  calSc.hide();
  mainSc.show();
}

I hope this helps anyone who encounters the same problem I was having.