1

I'm trying to connect arduino and processing via serial. Whenever I run the processing sketch I get the following error in Processing:

RuntimeException: Error opening serial port COM26: Port busy
Could not run the sketch (Target VM failed to initialize).

Below is the arduino sketch and processing code, which I "borrowed" from here, to try to programmatically find the correct serial port to connect to.

Arduino:

int var;

void setup() {
  Serial.begin(9600);
}

void loop() {
  if (Serial.available()) {
    var = Serial.read();
  }
  Serial.println(var);
  delay(100);
}

Processing:

import processing.serial.*;

Serial ser_port;                // for serial port
PFont fnt;                      // for font
int num_ports;
boolean device_detected = false;
String[] port_list;
String detected_port = "";

void setup() {
  size(400, 200);                         // size of application window
  background(0);                          // black background
  fnt = createFont("Arial", 16, true);    // font displayed in window

  println(Serial.list());

  // get the number of detected serial ports
  num_ports = Serial.list().length;
  // save the current list of serial ports
  port_list = new String[num_ports];
  for (int i = 0; i < num_ports; i++) {
    port_list[i] = Serial.list()[i];
  }
}

void draw()
{
  background(0);
  // display instructions to user
  textFont(fnt, 14);
  text("1. Arduino or serial device must be unplugged.", 20, 30);
  text("   (unplug device and restart this application if not)", 20, 50);
  text("2. Plug the Arduino or serial device into a USB port.", 20, 80);

  // see if Arduino or serial device was plugged in
  if ((Serial.list().length > num_ports) && !device_detected) {
    device_detected = true;
    // determine which port the device was plugged into
    boolean str_match = false;
    if (num_ports == 0) {
      detected_port = Serial.list()[0];
    } else {
      // go through the current port list
      for (int i = 0; i < Serial.list().length; i++) {
        // go through the saved port list
        for (int j = 0; j < num_ports; j++) {
          if (Serial.list()[i].equals(port_list[j])) {
            break;
          }
          if (j == (num_ports - 1)) {
            str_match = true;
            detected_port = Serial.list()[i];
          }
        }
      }
    }
  }
  // calculate and display serial port name
  if (device_detected) {
    text("Device detected:", 20, 110);
    textFont(fnt, 18);
    text(detected_port, 20, 150);
    ser_port = new Serial(this, detected_port, 9600);
  }
}

I am a newbie at this, so not sure what I'm doing wrong. Would appreciate any help :)

7
  • Have you checked manually if COM26 is actually the COM port of your Arduino? Does the communication work with the Serial Monitor?
    – chrisl
    Dec 10, 2021 at 14:13
  • You should probably set detected port when it's found rather than doing it after the loop if nothing else, and I'd recommend getting the serial list only once before the loop instead of three times. This might not solve the problem, but it's certainly more deterministic. Dec 10, 2021 at 14:19
  • The port it's finding is the correct one. However, I haven't been able to make the communication work. It's saying the port is busy. I'm using an Arduino nano every. @DaveNewton You're saying I should set the serial port, directly after finding it, rather than wait to do it in the if device detected function? For the 2nd point, I'm not sure the code would work if I only check once, since I won't be able to programmatically find the com port the Arduino is on, if I only check once. Dec 10, 2021 at 14:24
  • And can you connect with the Serial Monitor to that port? Is there some other program open that uses that port?
    – chrisl
    Dec 10, 2021 at 14:29
  • I tried a simple app, where I manually set the port. Processing is not giving me any errors and supposed to be writing to the Arduino. And if I try to open the serial monitor, while the app is running it's saying the port is busy. However, the variable in the Arduino sketch is not updating. Dec 10, 2021 at 14:40

1 Answer 1

3

I tried your Processing sketch, and it does detect and try to connect to the serial port, but fails for some reason.

Processing "code" can include a try catch block to help you diagnose the issue. Using this modified sketch, you can print the errors to the console window.

import processing.serial.*;

Serial ser_port;                // for serial port
PFont fnt;                      // for font
int num_ports;
boolean device_detected = false;
String[] port_list;
String detected_port = "";

void setup() {
  size(400, 200);                         // size of application window
  background(0);                          // black background
  fnt = createFont("Arial", 16, true);    // font displayed in window

  println(Serial.list());

  // get the number of detected serial ports
  num_ports = Serial.list().length;
  // save the current list of serial ports
  port_list = new String[num_ports];
  for (int i = 0; i < num_ports; i++) {
    port_list[i] = Serial.list()[i];
  }
}

void draw()
{
  background(0);
  // display instructions to user
  textFont(fnt, 14);
  text("1. Arduino or serial device must be unplugged.", 20, 30);
  text("   (unplug device and restart this application if not)", 20, 50);
  text("2. Plug the Arduino or serial device into a USB port.", 20, 80);

  // see if Arduino or serial device was plugged in
  if ((Serial.list().length > num_ports) && !device_detected) {
    device_detected = true;
    // determine which port the device was plugged into
    boolean str_match = false;
    if (num_ports == 0) {
      detected_port = Serial.list()[0];
    } else {
      // go through the current port list
      for (int i = 0; i < Serial.list().length; i++) {
        // go through the saved port list
        for (int j = 0; j < num_ports; j++) {
          if (Serial.list()[i].equals(port_list[j])) {
            break;
          }
          if (j == (num_ports - 1)) {
            str_match = true;
            detected_port = Serial.list()[i];
          }
        }
      }
    }
  }
  else{
    text("else", 20, 110);
  }
  // calculate and display serial port name
  if (device_detected) {
    text("Device detected:", 20, 110);
    textFont(fnt, 18);
    text(detected_port, 20, 150);
    try{
      ser_port = new Serial(this, detected_port, 9600);
    }
    catch(Exception e){
      // Print detailed error information to the console.
      System.err.println(e);
      e.printStackTrace();
    }
  }
  else{
    text("Device NOT detected:", 20, 140);
  }
}

These are the errors I get on my computer using a Arduino Uno.

    at processing.serial.Serial.<init>(Unknown Source)
    at processing.serial.Serial.<init>(Unknown Source)
    at sketch_211210a.draw(sketch_211210a.java:85)
    at processing.core.PApplet.handleDraw(PApplet.java:2475)
    at processing.awt.PSurfaceAWT$12.callDraw(PSurfaceAWT.java:1547)
    at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:313)
java.lang.RuntimeException: Error opening serial port /dev/tty.wchusbserial620: Port busy
java.lang.RuntimeException: Error opening serial port /dev/tty.wchusbserial620: Port busy

Another issue is with this part of the code: if (device_detected). The draw() function is like the Arduino loop() function in that it keeps looping through the code. It is repeatedly trying to make a new serial connection to the same port, which MAY explain why the Port busy error message is repeated in the console error messages.

Using Processing IDE 3.5.3, there is a errors tab at the bottom of the console window. I am getting 2 errors there which don't seem to be involved with the port connection issue.

If you install the controlP5 library in the Processing IDE, you can use this port testing sketch to see the Port ID change every time you create a new connection with it. I suspect your sketch may connect to the Arduino the first time through the draw() function, then it keeps trying to connect to the same port which is busy.

// Serial port(s) connection tester. Processing version 3.5.3.
// For a list of all the ScrollableList Controller methods available,
// use: "ControlP5.printPublicMethodsFor(ScrollableList.class);"
// to print the entire list of the 165 functions to the console.
import controlP5.*;
import java.util.*;
import processing.serial.*;

ControlP5 cp5;
Serial myPort;
Textlabel outputWindowLine1, outputWindowLine2;
String portName;

void setup(){

  size(500, 431);

  // Use a font larger than the default "6px".
  ControlFont font = new ControlFont(createFont("Verdana", 14));

  // ALL CAPS is the default font for the control. Why?
  Label.setUpperCaseDefault(false);

  // Configure a controlP5 ScrollableList.
  cp5 = new ControlP5(this);
  cp5.addScrollableList("dropdown")
    .setPosition(0, 50)
    .setSize(500, 400)
    .setBarHeight(50)
    .setItemHeight(30)
    .setFont(font)
    .addItems(GetSerialPortList())
    .setType(ScrollableList.LIST)
    .setLabel("--- Click on a port name to try and connect to it ---")
    ;

  outputWindowLine1 = cp5.addTextlabel("outputWindowLine1Label")
    .setText("The list of port names is \"scrollable\".")
    .setPosition(0, 0)
    .setColorValue(0)
    .setFont(font)
    ;

  outputWindowLine2 = cp5.addTextlabel("outputWindowLine2Label")
    .setText("Press any character on the keyboard to reload the list.")
    .setPosition(0, 25)
    .setColorValue(0)
    .setFont(font)
    ;
}

void draw(){
  background(255);
}

// User selects a drop down item. Works like a JavaScript onChange()
// event, except you can click on the same item multiple times, this
// code will execute again on each mouse "click" of the same item.
void dropdown(int n){

  // Create a serial connection and send some
  // chars to the "USB to Serial Converter".
  try{

    // Get the port name.
    portName = Serial.list()[n];

    // If you don't do this, you can't re-connect to the same port again.
    // Re-connecting to the same port gives you a new "myPort ID" and may
    // take a few seconds.
    if(myPort != null){
      myPort.clear();
      myPort.stop();
    }

    // Create a Serial Port connection.
    myPort = new Serial(this, portName, 9600);

    // User message.
    outputWindowLine1.setText("Connected to portName: " + portName);
    outputWindowLine2.setText("myPort = " + myPort);

  }
  catch(Exception e){

    // User message.
    outputWindowLine1.setText("Error connecting to portName: " + portName);
    outputWindowLine2.setText("");

    // Print detailed error information to the console.
    System.err.println(e);
    e.printStackTrace();
  }
}

// Refresh the dropdown list of serial port names.
void keyPressed(){
  cp5.get(ScrollableList.class, "dropdown").setItems(GetSerialPortList());
  outputWindowLine1.setText("Serial port list refreshed!");
  outputWindowLine2.setText("");
}

// Get a List of the serial port names.
List GetSerialPortList(){
  List serialPortList = Arrays.asList(Serial.list());
  return serialPortList;
}

2
  • thank you very much for your detailed response. I'll take the time tomorrow to go through it, and digest. And I will post on here again. Have a good evening. Dec 10, 2021 at 19:33
  • I've decided to make a new post, since the error seems to be more basic/something else, and it feels like it would be more harm than good to try to edit this post. Dec 11, 2021 at 12:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.