Why my Serial Port stays busy?

I am using a Win 10 Surface tablet to display settings of my robot arm.

My data stream comes through a HC 06 Arduino BT dongle at 57600 baud, paired with the tablet.

It worked fine when the sketches were small but now , after re-opening the sketch , I get:

Error opening Serial port COM 3: port busy.

This happens even if the data stream is off.
After I restart the sketch about 10 times, it works, connecting to the COM3.

So I tried an Exit button on the sketch that would “liberate” the COM for the next time:

 BTPort.stop();
    BTPort.clear();
   delay(10);
   exit();

Did not help.
What to do? Is there a way to try re-connecting to the com from Setup several times, without crashing the sketch?

I am desperate, it was all going so well.

Here is my COM code in Setup:

 BTPort = new Serial(this, "COM3", 57600);
      BTPort.clear();
  // Throw out the first reading, in case we started reading 
  // in the middle of a string from the sender.
  myString = BTPort.readStringUntil(lf);
  myString = null;

Please help, thank you,
Mitch

1 Like

In that case you‘re probably trying to access the Arduino‘s Serial Port from both Processing and the Arduino IDE at the same time. Try closing the Arduino IDE and retry. That should probably solve it. :wink:

Now I see your reply. Thanks

The BUSY problem happens even if the Arduino is powered off

When the Arduino is ON , it is connected to USB to my MAC, a totally different computer that runs the Processing sketch.

It seem that WIN 10 wont give access to the Sketch to the Com3 port.
Whether the pipe is on or off.

What to do ?
Thanks

Also, at if I reprogram the Arduino and it reboots on the Processing I get

Error, disabling serialEvent() for COM3
null
No glyph found for the ? (\uFFFD) character

Than the whole sketch hangs up and does not recover, unless I restart it ,
(Several times because of the COM Busy")

Is there a way to recover from the “unrecongnized character”?
And just read the next transmission?
Thanks

The disabling serialEvent() error is probably due to sending a null object to your arduino.
Which the reason for is probably the noGlyph error. It basically means that the char doesn‘t have a Glyph.

As for solving you problem… well, i don‘t know your Code, so there are only Limited things i can do…

Again, please make sure that the SerialMonitor in the Arduino IDE is not open! Your answer does seem like you‘re talking about something else, so i‘m not sure if you did that…

Also, in Processing, did you try adding a Delay of 500 or more before reading the Serial Port?

Lex,
THanks for the reply,

To clarify, the arduino is sending data to the Processing via Serial4. So I can look in the serial monitor in the same time. No? It is a Teensy 3.5 by the way.

What is the problem with the gliph and the Serial event being disabled?

Here is the main code.

//import apsync.*;
import processing.serial.*;
import g4p_controls.*;
import java.awt.Font;

boolean running = false;

//Serial myPort;

PFont f;
PFont font;
PFont BauHousefont;
//f = createFont("Arial",16,true);
//AP_Sync streamer;

char c1; // first character in the incoming string.
char CharFromKbd; //charater from keyboard

String BeforeSending = "";
//public String streamer;


/////////////////////Arm Depiction section
float segLength = 250;
////////////////////////////////

String inBuffer;

float BaseEncGlobal;
float ShoEncGlobal;
float ElbowEncGlobal;
float VertRotEnc;
float HorRotEnc;
 float GripEncGlobal;
float X_axis;
float Y_axis;
float  Z_axis;
 int GripOrientationRead;
float ArmOpeningMM;
 float HorAngRad;
 float VerAngRad;
 float Mode;
 float GripCommand;
 float TheStepNo;
 float CommandSent;
 float CommandCompleted;
 float X_Err;
 float Y_Err;
 float Z_Err;
 float T_Err;
 float BaseAngRad;
 float ShoAngRad;
 float ElbowAngRad;

 
/// outgoing
 String customKey;

 String Message;


///// color definitions White Yellow green Blue magenta Orange indigo
//int w, y, g, b, m, o;
int w= #FFFFFF; // white
int y= #FCF442; //yellow
int g= #A0FFA3; //green
int b= #64E1FF; // blue
int m= #CC15D3; // Magenta
int o= #FF6C67;  // orange
int i= #B767FF; // indigo
int r= #FC0B03; // red
int bk = (#212121);


GButton btn;

PImage RedButtonCalib;
Serial BTPort;
int lf = 10;    // Linefeed in ASCII
String myString = null;

public void setup(){ ////////////////////////////////////////////////////////////////////////////////////////////////////////

  size(1790,1100, JAVA2D);
  createGUI();
  customGUI();
 



RedButtonCalib = loadImage("RedButtonCalib.png");

      //surface.setResizable(true);
     printArray(Serial.list()); 
  // streamer = new AP_Sync(this,"/dev/cu.usbserial-A50285BI", 57600);  // FTDI ON SERIAL1
  // streamer = new AP_Sync(this,"/dev/cu.usbserial-A50285BI", 115200);  // FTDI ON SERIAL1
   // streamer = new AP_Sync(this,"COM3", 57600); // HC06 bluetooth
    BTPort = new Serial(this, "COM3", 57600);
      BTPort.clear();
  // Throw out the first reading, in case we started reading 
  // in the middle of a string from the sender.
   myString = BTPort.readStringUntil(lf);
   myString = null;
   //  BTPort.bufferUntil('\n');
  //streamer = new AP_Sync(this,"/dev/cu.usbmodem2574541", 38400);  // Teensy 3.5 built in usb port
  //  myPort = new Serial(this,"/dev/cu.usbmodem2574541", 115200);  // Teensy 3.5 built in usb port

  font = loadFont("AgencyFB-Bold-200.vlw");
  BauHousefont = loadFont("Bauhaus93-100.vlw");
  //font = createFont("AgencyFB-Bold-200",16,true);
 //f = createFont("Arial",16,true);
  BeforeSending = "s"; // s for stream . Checking that the Processing to Arduino works.
  //streamer.send(BeforeSending.toString());
       BeforeSending = "";
  //////////////////////Button creation
  
 
  BTPort.write('s');
   // frameRate(5);
  
}

public void draw(){
  
    background(bk);
  textAlign(LEFT);

    int FontBig= 90;
    int FontMed= 50;
    int FontSml= 40;
    int spaceDown = 75;
    
 
 // /*
  
  
///*
  
  //GripEncGlobal = nums[5] ;
  /*
float ArmOpeningMM;
 float HorAngRad;
 float VerAngRad;
 float Mode;
 float GripCommand;
 float TheStepNo;
 float CommandSent;
 float CommandCompleted;
 // ElbowEncGlobal = list [2];
 */
  
 
  

// image(RedButtonCalib, 220, 0);
   textFont(font, FontSml);
      fill(255, 255, 205); //White
     text("Encoders Pulses:", 20, spaceDown );  
 textFont(font, FontMed);
   fill(o); // Green
  text("G:", 20, spaceDown *2); 
  text( (nf(GripEncGlobal, 1,0)), 80, spaceDown*2);
  
  fill( i); 
  text("H:", 20, spaceDown *3);  
text((nf(HorRotEnc,1,0)), 80, spaceDown*3);

 fill(b); //Blue dark
text("V:", 20, spaceDown *4);
 text((nf(VertRotEnc,1,0)),80, spaceDown*4);
 
  fill(y); // Yellow
  text("E:", 20, spaceDown *5);
 text((nf(ElbowEncGlobal,1,0)), 80, spaceDown*5);
// /////////progress bar 
 noStroke();
   fill (#817703);
  rect(20, 384, 200, 20, 5);
  fill(y);
  rect(20, 384, ((200*(ElbowEncGlobal-ShoEncGlobal))/105500), 20, 5);
 ///////////end rectangles   
 
  
  
   fill(m); // magenta
   text("S:", 20, spaceDown *6);
  text((nf(ShoEncGlobal,1,0)), 80, spaceDown*6);
////////////bar  
  fill (#43013F);
  rect(20, 460, 200, 20, 5);
  fill(m);
  rect(20, 461, ((200*ShoEncGlobal)/91700), 20, 5);
/////////end bar
    fill(g); // Green
   text("B:", 20, spaceDown *7);
  text((nf(BaseEncGlobal,1,0)), 80, spaceDown *7);

/////////////////////////////////////////////////////////   
  int LS = 300; // left spacing
  fill(w); //White
  textFont(font, FontSml);
    text("XYZ mm:", LS, spaceDown ); 
    
    textFont(font, FontMed); 
      fill(g);
  text("X:", LS, spaceDown*2 ); 
  text( (nf(X_axis,1,1)), LS+40, spaceDown*2);


  
       fill(m); // magenta
  text("Y:", LS, spaceDown*3 ); 
  text( (nf(Y_axis,1,1)), LS+FontMed, spaceDown*3);
  
   fill(238,242, 0); // Yellow
    text("Z:", LS, spaceDown*4 ); 
  text( (nf(Z_axis,1,1)), LS+40, spaceDown*4);

  
textFont(font, FontSml);
  fill(o); 
    text("HGrAng:", LS, spaceDown*4.8 ); 
  text(nf(HorAngRad, 0, 1)+"°" , LS+120, spaceDown*4.8);

  fill(b); 
  
    text("VGrAng:", LS, spaceDown*5.6 ); 
  text (nf(VerAngRad , 0, 1)+"°", LS+120, spaceDown*5.6);
 
   
     int LS3 = 560; // left spacing
  fill(255, 255, 255); //White
  textFont(font, FontSml);
    text("MODE:", LS3, spaceDown ); 
    if (Mode ==0)
    {text("WAYPOINTS", LS3+100, spaceDown ); 
    }
    else if (Mode ==1)
    {fill (o);
      text("PAUSE", LS3+100, spaceDown ); 
    }
    else if (Mode ==2)
    { fill (r);
      text("RUN MOTION", LS3+100, spaceDown ); 
    }
 ////////active step   
    fill(g);
      textFont(font, FontMed); 
  text("ACTIVE ST:", LS3, 150 ); 
  text( (nf(TheStepNo, 1,0)), LS3+200, 150);
/// Message
   fill(g);
      textFont(font, 40); 
  //text("ACTIVE ST:", LS3, 150 ); 
   text( Message, LS3, 220);
  // GripCommand

   fill(r);
      textFont(font, FontMed); 
  text("GripCo:", LS3, 280 ); 
  text( (nf( GripCommand,1,0)), LS3+140, 280);
  
  
  
  fill(b);
      textFont(font, FontMed); 
  text("CSent:", LS3, 340 ); 
  text( (nf(CommandSent,1,0)), LS3+140, 340);
  
   text("CCmpte:", LS3, 400 ); 
  text( (nf(CommandCompleted,1,0)), LS3+150, 400);
  
  text("Err XYZ T:", LS, 490 ); 
  text( (nf(X_Err,1,0))+" "+(nf(Y_Err,1,0))+" "+(nf(Z_Err,1,0))+" "+(nf(T_Err,1,0))+"°", LS+199, 490);
 
  ////////////SHOW BEFORE SENDING
fill(o);   
textFont(font, 150); 
   text("STEP: ", 970, 150);
  text( BeforeSending, 1280, 150);


////// MENU LIST
 fill(g);
      textFont(font, 30); 
  text("111-DICE,  200-BLOCKS, 300-DRAW, 400-LASER", 970, 1070 );
  
/////////BOTTOM SWITCH

   //   fill(g);
  //    textFont(font, FontMed); 
 // text("SHOW COORDINATES", 1030, 1065 ); 
  
  
  ///////////////HOME 
 

  
///////end of home      

  
  // println( TheStepNo);
 GripDepiction();
  ArmDepiction();
   
   /*
   print ("mouseX:") ;
   println (mouseX) ;
   print ("mouseY:") ;
   println (mouseY) ;
   
   */


}// end of draw

void serialEvent(Serial BTPort) {
inBuffer = BTPort.readStringUntil(lf);  
      if (inBuffer !=  null)
      {println(inBuffer);
      c1 = inBuffer.charAt(0);
      DataSplit();
      inBuffer = null;
      }  
}




void keyPressed() { // I made this just to be displayed on the processing screen
 // if ((key >= 'A' && key <= 'z') || key == ' ') 
 
// println("pressed " + int(key) + " " + keyCode);
  if(keyCode != ENTER &&
      keyCode != DELETE &&
      keyCode != ESC &&
      keyCode != UP &&
      keyCode != DOWN &&
      keyCode != BACKSPACE &&
      keyCode != TAB &&
      keyCode != ALT &&
      keyCode != CONTROL &&
      keyCode != RETURN )
  {
    CharFromKbd = key;
    BeforeSending = BeforeSending + key;
    
  }
 
   if (keyCode == ENTER)
   {
      println(BeforeSending + " sent");
   //  streamer.send(BeforeSending.toString());
       BeforeSending = "";
   }
   
  if (keyCode == DELETE || keyCode == BACKSPACE)
  {
    if(BeforeSending.length() > 0)
       BeforeSending=BeforeSending.substring(0, BeforeSending.length() - 1); 
    }

}


// Use this method to add additional statements
// to customise the GUI controls
public void customGUI(){
HOME.setFont(new Font("AgencyFB-Bold-200", Font.BOLD, 70));
Send.setFont(new Font("", Font.BOLD, 70));
int KeypadFontSize=160;
button1.setFont(new Font("", Font.BOLD,  KeypadFontSize));
button2.setFont(new Font("", Font.BOLD,  KeypadFontSize));
button3.setFont(new Font("", Font.BOLD,  KeypadFontSize));
button4.setFont(new Font("", Font.BOLD,  KeypadFontSize));
button5.setFont(new Font("", Font.BOLD,  KeypadFontSize));
button6.setFont(new Font("", Font.BOLD,  KeypadFontSize));
button7.setFont(new Font("", Font.BOLD,  KeypadFontSize));
button8.setFont(new Font("", Font.BOLD,  KeypadFontSize));
button9.setFont(new Font("", Font.BOLD,  KeypadFontSize));
button0.setFont(new Font("", Font.BOLD,  KeypadFontSize));

NEXT.setFont(new Font("", Font.BOLD,  80));
PREV.setFont(new Font("", Font.BOLD,  80));
DEL.setFont(new Font("", Font.BOLD,  50));

CALIBLOW.setFont(new Font("", Font.BOLD,  30));
CALIBARROWS.setFont(new Font("", Font.BOLD,  30));

SHOW.setFont(new Font("", Font.BOLD,  18));
buttonM.setFont(new Font("", Font.BOLD,  30));
buttonP.setFont(new Font("", Font.BOLD,  30));
buttonR.setFont(new Font("", Font.BOLD,  30));

}

/*  depository

HOME.setFont(new Font("Arial", Font.BOLD, 70));
HOME.setFont(new Font("Bauhaus93-100.vlw", Font.BOLD, 70));
*/

There is more code, as I have the Data Split function and the GUI, but I dont think they are related to serial dropping out.

Any ideas?
Thanks

In the serialEvent() method, try adding as the first line :

if (BTPort != null) println("All Good");

I have a feeling that the communication just doesn‘t work (which is probably caused by the same reason that causes those PortBusy errors…).

As for the noGlyph error, that means your font doesn‘t support that character (for example it has no glyph/fontimage for the letter ‘e’ or something like that).

You can check which char that is, by doing :

font.getGlyph('e'); // e is just a random char. You should Test all of them

OK
Regarding the “Port busy”:
I replaced the BT Dongle from an HC 06 (slave) to a HC05 - Master dongle and boosted the baud to 115200.
The problem went away, YEY. I think windows makes this port available for being a Master??

Regarding the Gliph.

I added your code and did this in the Serial Event

void serialEvent(Serial BTPort) {
  if (BTPort != null) 
  {//println("All Good");
  
  inBuffer = BTPort.readStringUntil(lf);  
      if (inBuffer !=  null)
      {
       println(inBuffer);
     c1 = inBuffer.charAt(0);
     println(c1);
     DataSplit();
      inBuffer = null;
      } 
  }
    //  */
}

It all works like a charm as long as i dont activate the DataSplit();

Only then I get the glyph issue.

I tried to find what it is but I only get a “?”
char ch = ‘\u171A’; // this is the missing one.
println(ch);

Here is the Split data, do you see an issue?

void DataSplit()
{if  (c1 == 'e')
  {
  float[] errs = float(split(inBuffer, ' '));
  // pos 0 is the "e
  X_Err = errs[1] ;
  Y_Err = errs[2] ;
  Z_Err = errs[3] ;
  T_Err = errs[4] ;
  BaseAngRad = errs[5] ;
  ShoAngRad = errs[6] ;
  ElbowAngRad = errs[7] ;
 
  }

else if (c1 == 'M')
{ 
  
Message= inBuffer;

}


else // 
{
 float[] nums = float(split(inBuffer, ' '));

  BaseEncGlobal = nums[0] ; 
  ShoEncGlobal = nums[1] ;
  ElbowEncGlobal = nums[2] ;
  VertRotEnc = nums[3] ;
  HorRotEnc = nums[4] ;
  GripEncGlobal = nums[5] ;
  X_axis = nums[6] ;
  Y_axis = nums[7] ;
  Z_axis = nums[8] ;
  HorAngRad = nums[9] ;
  VerAngRad = nums[10] ;
  Mode = nums[11] ;
  TheStepNo = nums[12] ;
  GripCommand = nums[13] ;
  CommandSent = nums[14] ;
  CommandCompleted = nums[14] ;
  
}


}

yes, but answered 2 times already.

KLL

If you scroll up, this is the first time you write me.
Any ideas on this Error?

Error, disabling serialEvent() for COM3
null
No glyph found for the ? (\uFFFD) character

It shows randomly , but especially in this instance

else if (c1 == ‘M’)
{

Message= inBuffer;

}

If I try to display as text the “Message”, the it hangs the sketch all the time.

My problem is that I get one inString from the serial.
Sometimes is a bunch of numbers, sometimes is a bunch of text.

I am trying to provide an if else to treat them differently. One is split for values, one is just a string to be shown on the screen.

Sorry, now I looked a the other thread.

Yes, sorting numbers works OK for right now.

The trouble is when I get a string of text.

-a- use trim
-b- use length

no, the trouble is you split a string and
assign values [i] without checking first if they exist.
if you expect 16 parameter, and get less like ?15?
you better ignore the whole line and report

//void serialEvent(Serial BTPort) {
//  inBuffer = BTPort.readStringUntil(lf); 


String inBuffer = "158018 70222 149288 44793 12944 94 -96.0 -305.8 129.4 221.9 45.2 1 -1 0 0 0";
//String inBuffer = "e 96.0 305.8 129.4 221.9";
char c1;

void test() {
  inBuffer = trim(inBuffer); //_______   https://processing.org/reference/trim_.html
  if (inBuffer !=  null) { //_________   ignore other
    println(inBuffer);
    c1 = inBuffer.charAt(0); //_______   your logic on first char
    if  (c1 == 'e') {
      float[] errs = float(split(inBuffer, ' '));
      //println(errs);
      if ( errs.length >=5 ) { //_____   https://processing.org/reference/Array.html  ( expected number of values )
         for ( int i = 0; i < errs.length; i++ ) 
           println( i, errs[i] ); //__   only use if check that exists
      } else {
        println("wrong number of parameters ERRS");
        println(errs);
      }
    } else {
      float[] nums = float(split(inBuffer, ' '));
      //println(nums);
      if ( nums.length >=16 ) { //_____   https://processing.org/reference/Array.html  ( expected number of values )
         for ( int i = 0; i < nums.length; i++ ) 
           println( i, nums[i] ); //__   only use if check that exists
      } else {
        println("wrong number of parameters NUMS");
        println(nums);
      }
    }
  }
}

void setup() { test(); }

2 Likes

Thanks a lot,

I wrote the entire sketch based on the length of the inBuffer.
Works like a charm. Much better then detecting the first char.
I feel silly,

Thanks again,
Mitch

3 Likes