Последовательное соединение между arduino и процессором не работает: Порт занят

Я пытаюсь подключить arduino и обработку через serial. Всякий раз, когда я запускаю скетч обработки, я получаю следующую ошибку при обработке:

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

Ниже приведен скетч arduino и код обработки, который я "позаимствовал" отсюда, чтобы попытаться программно найти правильный последовательный порт для подключения.

Arduino:

int var;

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

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

Обработка:

import processing.serial.*;

Serial ser_port;                // для последовательного порта
PFont fnt;                      // для шрифта
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);    // шрифт, отображаемый в окне

  println(Serial.list());

  // получить количество обнаруженных последовательных портов
  num_ports = Serial.list().length;
  // сохранить текущий список последовательных портов
  port_list = new String[num_ports];
  for (int i = 0; i < num_ports; i++) {
    port_list[i] = Serial.list()[i];
  }
}

void draw()
{
  background(0);
  // показать инструкции пользователю
  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);

  // посмотрите, было ли подключено Arduino или последовательное устройство
  if ((Serial.list().length > num_ports) && !device_detected) {
    device_detected = true;
    // определить, к какому порту было подключено устройство
    boolean str_match = false;
    if (num_ports == 0) {
      detected_port = Serial.list()[0];
    } else {
      // пройдите по текущему списку портов
      for (int i = 0; i < Serial.list().length; i++) {
        // пройдите по сохраненному списку портов
        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];
          }
        }
      }
    }
  }
  // вычислить и отобразить имя последовательного порта
  if (device_detected) {
    text("Device detected:", 20, 110);
    textFont(fnt, 18);
    text(detected_port, 20, 150);
    ser_port = new Serial(this, detected_port, 9600);
  }
}

Я новичок в этом деле, поэтому не уверен, что делаю не так. Буду признателен за любую помощь :)

, 👍1

Обсуждение

Вы проверяли вручную, действительно ли COM26 является COM-портом вашего Arduino? Работает ли связь с последовательным монитором?, @chrisl

Вероятно, вам следует установить обнаруженный порт, когда он будет найден, а не делать это после цикла, если ничего другого, и я бы рекомендовал получать последовательный список только один раз перед циклом, а не три раза. Это может и не решить проблему, но она, безусловно, более детерминирована., @Dave Newton

Порт, который он находит, является правильным. Однако мне так и не удалось наладить связь. Он говорит, что порт занят. Я использую Arduino nano каждый раз. @DaveNewton Вы говорите, что я должен установить последовательный порт сразу после его обнаружения, а не ждать, чтобы сделать это в функции if device detected? Что касается 2-го пункта, я не уверен, что код будет работать, если я проверю только один раз, так как я не смогу программно найти com-порт, на котором находится Arduino, если я проверю только один раз., @Zhelyazko Grudov

И можете ли вы подключиться к этому порту с помощью последовательного монитора? Есть ли какая-то другая открытая программа, которая использует этот порт?, @chrisl

Я попробовал простое приложение, где вручную установил порт. Обработка не дает мне никаких ошибок и должна писать на Arduino. И если я попытаюсь открыть последовательный монитор, пока приложение работает, оно скажет, что порт занят. Однако переменная в скетче Arduino не обновляется., @Zhelyazko Grudov

Вопрос означал, можете ли вы подключиться к Arduino с помощью чего-либо еще *not* во время работы программы, например, работает ли она на *all*. Моя точка зрения на обнаружение заключается в том, что как только в цикле появляется не совпадающий последовательный порт,вы можете прекратить проверку—вы знаете индекс недавно подключенного последовательного порта устройства., @Dave Newton

IDE подключается к нему как обычно. Обработка работает не так, как ожидалось. Не знаете, с чем еще попробовать? Re: обнаружение - понятно, попробую упростить код., @Zhelyazko Grudov


1 ответ


Лучший ответ:

3

Я попробовал ваш скетч обработки, и он действительно обнаруживает и пытается подключиться к последовательному порту, но по какой-то причине терпит неудачу.

Обработка "кода" может включать блок try catch, который поможет вам диагностировать проблему. Используя этот модифицированный скетч, вы можете распечатать ошибки в окне консоли.

import processing.serial.*;

Serial ser_port;                // для последовательного порта
PFont fnt;                      // для шрифта
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);    // шрифт, отображаемый в окне

  println(Serial.list());

  // получить количество обнаруженных последовательных портов
  num_ports = Serial.list().length;
  // сохранить текущий список последовательных портов
  port_list = new String[num_ports];
  for (int i = 0; i < num_ports; i++) {
    port_list[i] = Serial.list()[i];
  }
}

void draw()
{
  background(0);
  // показать инструкции пользователю
  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);

  // посмотрите, было ли подключено Arduino или последовательное устройство
  if ((Serial.list().length > num_ports) && !device_detected) {
    device_detected = true;
    // определить, к какому порту было подключено устройство
    boolean str_match = false;
    if (num_ports == 0) {
      detected_port = Serial.list()[0];
    } else {
      // пройдите по текущему списку портов
      for (int i = 0; i < Serial.list().length; i++) {
        // пройдите по сохраненному списку портов
        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);
  }
  // вычислить и отобразить имя последовательного порта
  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){
      // Выведите подробную информацию об ошибке на консоль.
      System.err.println(e);
      e.printStackTrace();
    }
  }
  else{
    text("Device NOT detected:", 20, 140);
  }
}

Это ошибки, которые я получаю на своем компьютере, используя 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

Другая проблема связана с этой частью кода: if (device_detected). Функция draw() похожа на функцию Arduino loop() в том смысле, что она продолжает зацикливаться на коде. Он неоднократно пытается установить новое последовательное соединение с тем же портом, что МОЖЕТ объяснить, почему сообщение об ошибке Port busy повторяется в сообщениях об ошибках консоли.

При использовании Processing IDE 3.5.3 в нижней части окна консоли есть вкладка errors. Я получаю там 2 ошибки, которые, похоже, не связаны с проблемой подключения порта.

Если вы установите библиотеку controlP5 в среду IDE обработки, вы можете использовать этот скетч тестирования портов, чтобы увидеть изменение идентификатора порта каждый раз, когда вы создаете с ним новое соединение. Я подозреваю, что ваш скетч может подключиться к Arduino в первый раз через функцию draw (), а затем он продолжает пытаться подключиться к тому же порту, который занят.

// Тестер подключения последовательных портов. Обработка версии 3.5.3.
// Для получения списка всех доступных методов контроллера
// use: "ControlP5.printPublicMethodsFor(ScrollableList.class);"
// вывести на консоль весь список из 165 функций.
import controlP5.*;
import java.util.*;
import processing.serial.*;

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

void setup(){

  size(500, 431);

  // Используйте шрифт больше, чем по умолчанию "6px".
  ControlFont font = new ControlFont(createFont("Verdana", 14));

  // ALL CAPS - это шрифт по умолчанию для элемента управления. Почему?
  Label.setUpperCaseDefault(false);

  // Настройка списка прокрутки controlP5.
  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);
}

// Пользователь выбирает выпадающий элемент. Работает как JavaScript onChange()
// событие, за исключением того, что вы можете нажать на один и тот же элемент несколько раз, это
// код будет выполняться снова при каждом "щелчке" мыши по одному и тому же элементу.
void dropdown(int n){

  // Создайте последовательное соединение и отправьте несколько
  // chars к "USB to Serial Converter".
  try{

    // Получить имя порта.
    portName = Serial.list()[n];

    // Если вы этого не сделаете, вы не сможете снова подключиться к тому же порту.
    // Повторное подключение к тому же порту дает вам новый "myPort ID" и может
    // потратьте несколько секунд.
    if(myPort != null){
      myPort.clear();
      myPort.stop();
    }

    // Создайте соединение с последовательным портом.
    myPort = new Serial(this, portName, 9600);

    // Сообщение пользователя.
    outputWindowLine1.setText("Connected to portName: " + portName);
    outputWindowLine2.setText("myPort = " + myPort);

  }
  catch(Exception e){

    // Сообщение пользователя.
    outputWindowLine1.setText("Error connecting to portName: " + portName);
    outputWindowLine2.setText("");

    // Выведите подробную информацию об ошибке на консоль.
    System.err.println(e);
    e.printStackTrace();
  }
}

// Обновите выпадающий список имен последовательных портов.
void keyPressed(){
  cp5.get(ScrollableList.class, "dropdown").setItems(GetSerialPortList());
  outputWindowLine1.setText("Serial port list refreshed!");
  outputWindowLine2.setText("");
}

// Получить список имен последовательных портов.
List GetSerialPortList(){
  List serialPortList = Arrays.asList(Serial.list());
  return serialPortList;
}

,

большое вам спасибо за ваш подробный ответ. Завтра я найду время, чтобы просмотреть его и переварить. И я буду публиковать здесь еще раз. Хорошего вечера., @Zhelyazko Grudov

Я решил сделать новый пост, так как ошибка кажется более простой/чем-то еще, и мне кажется, что было бы больше вреда, чем пользы, чтобы попытаться отредактировать этот пост., @Zhelyazko Grudov