Как определить СОМ порт

Egor_Ovechkin
Offline
Зарегистрирован: 06.08.2014

Всем привет!

Подцепил несколько диодов к mega2560, пытась управлять ими с помощью Processing.

Изначально указывал СОМ порт явно

println(Serial.list()); 
  // I know that the first port in the serial list on my mac 
  // is always my  Keyspan adaptor, so I open Serial.list()[1]. 
  // Open whatever port is the one you're using. 
  myPort = new Serial(this, Serial.list()[1], 9600); 
  myPort.clear();
  s = myPort.readStringUntil(lf);
  s = null;

но хотелось бы чтобы программа сама находила к какому порту подключена ардуина.

пытался сделать это так(в proccesing):

void draw()
{
  
  int  nOfPort = -1;
  if (thisPort == false)
  {
    nOfPort++;
    myPort = new Serial(this, Serial.list()[nOfPort], 9600); 
    myPort.clear();
    s = myPort.readStringUntil(lf);
    s = null;
    myPort.write('9');
    delay(500);
  }
  
  else
  {//код основной программы}
}
void serialEvent(Serial p) 
{
  s = myPort.readStringUntil(lf);
  // println (s);
  if (s != null)
  {
    colorZad(s);
  }
}

boolean thisPort = false;
void colorZad (String s)
{
  char firstSymbol = s.charAt(0);
  char secondSymbol = s.charAt(1);
  switch(firstSymbol)
  {
  case 'y':
    thisPort = true;
//для нужд основной программы
  case '-':
    atWork = false;
    a = '0';
    break;
  case 'n':
  case 'N':
    koorZadv[5][2] = secondSymbol - '0';
    break;
  case 'm':
  case 'M':
    koorZadv[6][2] = secondSymbol - '0';
    break;
  case 'd':
  case 'D':
    koorZadv[7][2] = secondSymbol - '0';
    break;
  case 'l':
    koorZadv[8][2] = secondSymbol;
    break;
  case'0':
  case'1':
  case'2':
  case'3':
  case'4':
    koorZadv[firstSymbol - '0'][2] = secondSymbol - '0';
    break;
/////////
  }
}

+ прошил в ардуино:

void loop()
{
  while (Serial.available() == 0 );
  if (val == 9)
  {
    Serial.println("yes");
  }
  Main(val);//основная программа
}

в итоге получаю ошибку при запуске скетча processing

Eror inside Serial.<init>()

Может кто сталкивался?как решить эту задачу?

(строго не судите пытался всё изложить досупно)

Заранее спасибо:)

 

Egor_Ovechkin
Offline
Зарегистрирован: 06.08.2014

да, 4 строку

04 int  nOfPort = -1;

вынес за пределы блока draw

и убрав открытие порта из блока setup() - сразу забыл это сделать - получаю ошибку

ArrayIndexOutOfBoundsException: 2- то есть вылетаю за пределы массива как я понял

ourlive
Offline
Зарегистрирован: 26.05.2012

структура автоматического поиска ардуины такая

1.ардуина ожидает данныс с кома

2. процессинг строит список имеющихся портов

3. поочерёдно пытается открыть все порты и отправить на них уникальную команду-строку типа "ping"

4. ардуина получив "ping" отсылает обратно ответ "pong" и свой ID

5. в процессинге цикл открытия порта и отсылки/чтения данных необходимо обернуть функцией исключения, потому как все занятые порты, недоступные и т.п. будут выдавать ошибку и остановку скетча

Таким методом можно идентифицировать хоть десяток одновременно подключенных дуин имеющих уникальные иды.

Поищите в "общем" "сканирующий тепловизор", там был пример работающий на эту тему. У меня оно есть, но на домашнем компе.

ourlive
Offline
Зарегистрирован: 26.05.2012

анализируя количество портов и возникшие ошибки процессинг должен уметь выдавать сообщения типа "нет доступных портов" или "обнаружено портов №№, ардуин не обнаружено". Идеально кконечно чтобы сканер ещё на доступных портах перебирал все варианты скорости порта. Но это долгая история. Проще принять какую то скорость за стандарт и ни в одном проекте в последующем без крайней надобности от него не отступать.

sav liana
Offline
Зарегистрирован: 28.11.2016

ourlive пишет:
структура автоматического поиска ардуины такая... 

ourlive пишет:
анализируя количество портов и возникшие ошибки процессинг должен уметь... 

Все это замечательно, но пока нигде не нашел примера:

по определению доступных и недоступных COM-портов ? Кто подскажет...

Nosferatu
Offline
Зарегистрирован: 04.11.2012

Список доступных портов можно вывести так:

import processing.serial.*;  
void setup()
{
}
void draw()
{  
  for (int i = 0; i < Serial.list().length; i++)
    println(Serial.list()[i]);
}

Посылать на эти порты "приветствие", на которое ардуино ответит.

sav liana
Offline
Зарегистрирован: 28.11.2016

Передает Arduino:

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

void loop() {
Serial.println("Arduino UNO");
delay(100);
}

Принимает Processing:

import processing.serial.*;
Serial port, portX;
String StrInput="-------------------------------";
String COMX = "COMX ???";

void setup()
{  
  println("N of ports = "+Serial.list().length);
  for ( int i = 0; i < Serial.list().length; i++)
  {
    println("port = "+Serial.list()[i]);
    println("i=" + i);
    portX = new Serial(this, Serial.list()[i], 9600);
    portX.bufferUntil('\n');
    for(int j=0; j<10; j++) 
    {
      println("    j=" + j);
      if ( portX.available() >0 ) 
      {
      StrInput = (portX.readStringUntil('\n'));
      StrInput = StrInput.substring(0, StrInput.length()-2);
      if (StrInput.substring(0,3).equals("Ard")) COMX = Serial.list()[i];
      println("    xCOMX = " + COMX);
      }
      delay(300);
    }
    portX.stop();
  }
}

void draw()    {     }
 
 
Nosferatu
Offline
Зарегистрирован: 04.11.2012

sav liana

Вот только подключить ардуину после запуска программы не получится. И при отключении ардуины программа может зависнуть. По уму надо в draw() эти ситуации отрабатывать, для возможности горячей замены.

sav liana
Offline
Зарегистрирован: 28.11.2016

... и видимо с прерыванием.

Еще дело осложняется тем, что моя ардуина выдает внушительный поток...  Зпутанное дело получается... И как работает Serial.Flush(); не понятно... Как то надо чистить буфер...

Пример со сканирующим тепловизором, видимо, этот... там вручную выбирается порт?

ourlive
Offline
Зарегистрирован: 26.05.2012

Я такой когда то делал тепловизор, тут даже скетч где то был.

Выдранная из контекста функция:

void com_select() {               //поиск нужного компорта
  if (comport=="") {              //если ком порт не выбран
  String port[] = Serial.list(); 
  int i = 0;
  while (i < port.length) {
    print("number of COM-port ");
    println(i+1);
  text(port[i],10,50+i*20);
  try { myPort = new Serial(this, Serial.list()[i], 115200);
        pause(3000);  //без паузы глючит и ком зависает (аналог delay(), самописный)
        com_read(); com_bufer=""; //опустошить буфер перед пингом
        myPort.write("#png"); myPort.write(char(13)); //пингануть
        pause(3000);
        com_read();       //прочитать данные
        if (com_bufer.substring(0,6).equals("#pN001")==true) {comport=port[i]; println("port "+port[i]+" OK"); i=port.length+1;  status="COM порт определён";} //если ответ правильный
        else {println("port "+port[i]+" NO OK");i++;  myPort.stop(); pause(1000); print("com_err ");println(com_bufer);status="COM порт не определён";} //если ответ не правильный или его нет
  } catch (Exception e) {println(port[i]+" -");myPort.stop(); i++; status="COM порт не определён";} //данный порт не доступен, не отвечает или высылает неверный ответ
  }//***while
  if (port.length==0) {status="Нет доступных COM портов";}
  }
} //************************************com_select()

Если захотите в этом ужасном куске кода разобраться, то всё будет ясно. Весь смысл сводится к тому, что на команду #png в порт ардуина возвращает своё имя, в данном случае #pN001. Тот порт с которого пришел правильный ответ и есть наш. Процесс открытия порта обёрнут отлавнивателем исключений, потому как если попытаться открыть занятый порт, будет ошибка и остановка работы скетча. Если ни с одного из имеющихся портов ожидаемого отклика не пришло портов вообще не обнаружено, значит нужная ардуина не подключена.

Если выкинуть всё лишнее, то всё сводится к 10 строкам кода.

А началось всё с того, что на разных машинах у меня порты тогда оказались разные, лень было переназначать каждый раз.

До состояния "потеря ардуины" во время работы допиливается легко, но если только если структура команд строится по принципу "процессинг спросил, ардуина ответила".