Do something based on serial data

My Arduino is sending serial data whenever a button is pushed or flicked. These are things like "3High", "3Low", "4High", etc. Each one on a new line.

I need processing to do something based on this serial data, probably with an if statement. EG when button 3 is pushed, serial.print sends "3High" then processing should read that and trigger something.

I have absolutely no idea how to do it :frowning:

So far I have this, but need some help:

import processing.serial.*;

Serial myPort;  // Create object from Serial class
String val;     // Data received from the serial port

void setup() 
{
    size(600, 600);
// Open whatever port is the one you're using.
String portName = Serial.list()[1]; //change the 0 to a 1 or 2 etc. to match your port
myPort = new Serial(this, portName, 9600); 
}

void draw()
{
  if ( myPort.available() > 0) 
  {  // If data is available,
  val = myPort.readStringUntil('\n');         // read it and store it in val
  } 
println(val); //print it out in the console


  if (val == "3High"){
    DO SOMETHING
  }
  if (val == "3Low"){
    DO SOMETHING   
  }


}

Your first problem is that serial I/O is not something to be done in draw(). Unlike loop() on the Arduino, draw is not called over and over again as fast as possible. It is called over and over again, but with deliberate delays between calls to match the frame rate requested.

There is a serialEvent() method that does nothing. You need to overload it, by providing an implementation that actually does something.

Your second problem is that you didn't show the Arduino code. You should not be sending "3High". You should be sending "3High\n\r" (using Serial.println() to send "3High", not Serial.print()).

In setup(), you need to add a call to myPort.bufferUntil() to tell the Serial class not to call the serialEvent() method until some character has arrived - the \n or \r are good candidates.

In the serialEvent() method, then, you need to use myPort.readBytesUntil() to get the serial data up to the buffer until character. Then you need to strip off the other character (the line feed if you buffer to the carriage return or the carriage return if you buffer until the line feed). The character to strip may be on either end, or may not be there at all. You need to strip off the delimiting character, too. Fortunately, trim() strips white space from both ends of the String.

After that, the rest of your code that deals with what was read is correct. You just need to define what you want to have happen. We can't help you with that part.

Thanks but I’m totally confused… I’m struggling to grasp the Processing side of things.

Also, is it possible to only send serial data WHEN a button changes state? I’m planning to have at least 30 buttons so I guess the serial data feed will be busy with constant data.

Here’s my Arduino code:

int switchPin3 = 3;                       // Switch connected to pin 4

void setup() {

  pinMode(switchPin3, INPUT);             // Set pin 0 as an input
  Serial.begin(9600);                    // Start serial communication at 9600 bps
}

void loop() {

  
  if (digitalRead(switchPin3) == HIGH) {  // If switch is ON,
    Serial.println("3High\n\r");               // send 1 to Processing
  } else {                               // If the switch is not ON,
    Serial.println("3Low\n\r");               // send 0 to Processing
  }
  
  delay(1000);                            // Wait 100 milliseconds
}

Also, is it possible to only send serial data WHEN a button changes state?

Yes, like I said in your other thread.

Thanks for the help so far Paul, I feel like I'm almost there (despite being amazingly overwhelmed) :slight_smile:

So, now I have Arduino sending lines of data via serial ("3High", etc).

I just need Processing to work with the if statements. I tried the advice above but I'm stumped.

Here's what I'm working with so far, I can see the data in the serial window but can't do anything with it:

import processing.serial.*;

Serial myPort;  // Create object from Serial class
String val;     // Data received from the serial port

void setup() 
{
    size(600, 600);
// Open whatever port is the one you're using.
String portName = Serial.list()[1]; //change the 0 to a 1 or 2 etc. to match your port
myPort = new Serial(this, portName, 9600); 
}

void draw()
{
  if ( myPort.available() > 0) 
  {  // If data is available,
  val = myPort.readStringUntil('\n');         // read it and store it in val
  } 
println(val); //print it out in the console


  if ("3High".equals(val)) {
    fill(255,200,200);
    ellipse(60,20,100,100);
  }
  if ("3Low".equals(val)) {
    fill(155,100,100);
    ellipse(60,20,500,500);
  }
}
  if ("3High".equals(val)) {

I'm surprised that that even compiles.

Since val is a String, I'd be using

  if (val.equals("3High") {

But, I think the real problem is that val doesn't equal "3High".

Try this:

print("val = [");
print(val);
println("]");

If you see
val = [3High]
then the if test (or at least the revised one) should work.

If, instead (as I think more likely), you see
val = [3High
]
or
val = [
3High]
then the if statement won't be true.

val = val.trim();
would take care of the leading and/or trailing carriage return and/or line feed.