How to let the user select COM (serial) port within a sketch?

edited January 2018 in Arduino

Hi,

I have a relatively simple Processing sketch which connects to an external hardware sensor via Bluetooth (serial port) and visualizes the data. The sketch works acceptably on my computer, but since the COM (serial) port is hard-coded within the sketch, I need to recompile the sketch for every different computer on which I use the program.

To improve the portability of my Processing sketch across different computers/configurations, I would like to be able to let the user select the COM (serial) port within the sketch or "void setup()" routine.

Conceptually: void setup() { // List all the available serial ports: println(Serial.list()); println("Enter serial port number: ");

// Wait for the user to input a serial port number // (not sure how to get user input within the setup() routine, though) // user_serial_port = ???

// Open the port that the user selected using the default rate: myPort = new Serial(this, Serial.list()[user_serial_port], 57600); }

I have looked in the forum for some examples of user-selectable COM ports, but it seems like almost everyone is hard-coding the COM port number in their sketch. Thank you in advance for some help/guidance with this request.

Regards,

Geoffrey

Answers

  • Answer ✓

    Here's an example that I have just recently written, which addresses this problem. If there is only one serial port available (no matter what its COM number may be), then there is no user interaction. If none are available, or there is one, but it is in use by another application (e.g. Hyperterm, etc.) then a diagnostic is displayed. If there are two or more ports available, then the user is asked to choose which one they want.

        /** Example of selecting a particular Serial Port
         *  from the list of all possibilities returned
         *  in Serial.list().
         *
         *  Uses showInputDialog box kindly suggested to
         *  me by GoToLoop.  Thank you, GoToLoop! 
        */
    
        import processing.serial.*;
        import static javax.swing.JOptionPane.*;
    
        Serial myPort;        // The serial port
    
        final boolean debug = true;
    
        void setup() {
          String COMx, COMlist = "";
        /*
          Other setup code goes here - I put this at
          the end because of the try/catch structure.
        */
          try {
            if(debug) printArray(Serial.list());
            int i = Serial.list().length;
            if (i != 0) {
              if (i >= 2) {
                // need to check which port the inst uses -
                // for now we'll just let the user decide
                for (int j = 0; j < i;) {
                  COMlist += char(j+'a') + " = " + Serial.list()[j];
                  if (++j < i) COMlist += ",  ";
                }
                COMx = showInputDialog("Which COM port is correct? (a,b,..):\n"+COMlist);
                if (COMx == null) exit();
                if (COMx.isEmpty()) exit();
                i = int(COMx.toLowerCase().charAt(0) - 'a') + 1;
              }
              String portName = Serial.list()[i-1];
              if(debug) println(portName);
              myPort = new Serial(this, portName, 19200); // change baud rate to your liking
              myPort.bufferUntil('\n'); // buffer until CR/LF appears, but not required..
            }
            else {
              showMessageDialog(frame,"Device is not connected to the PC");
              exit();
            }
          }
          catch (Exception e)
          { //Print the type of error
            showMessageDialog(frame,"COM port is not available (may\nbe in use by another program)");
            println("Error:", e);
            exit();
          }
        }
    
  • Javz,

    Thank you for this example. I will try it out tonight!

    -Geoffrey

  • this is really great! thanks

  • wait actually, this doesnt end up connecting correctly to the port. i'm using mac osx. i'm going to start to debug, but i'm not actually getting serial data transferred even though it seems to bring up the port and open it. any ideas? thanks

  • sorry disregard that. (baud rate :) )

    thanks again this is great

  • edited November 2014

    All,

    Thanx again with this code. I have been using a substantially-similar derivative quite successfully on my MacOS Processing installation. However, when I port the same code to a Windows 64-bit machine (using Processing 2.2.1), it seems like the setup() routine loops back, spawning the "Which port..." query again.

    Has anyone seen this behavior before and have any suggestions about how to stop it?

    Regards,

    Geoffrey

  • edited May 2016

    After playing with this code, I was able to make it work quite nicely with one addition/update to make the JOptionPane showInputDialog window appear ON TOP of the other windows.

    Reference javz's code example, but...

    1. Replace the "import static javax.swing.JOptionPane.*" with import javax.swing.JOptionPane; import javax.swing.JDialog;

    2. Replace the single line "COMx = showInputDialog..." with JDialog dialog = new JDialog(); dialog.setAlwaysOnTop(true); COMx = showInputDialog(dialog, "Which COM port...\n"+COMlist);

    I was pretty psyched about this because I had user complaints about not being able to find the background COM port query window.

    Hope this helps clarify...please reply if you have any more detailed questions.

  • Correction to my earlier post - you need to replace the "showInputDialog" and other references to JOptionPane functions with an explicit call such as JOptionPane.showInputDialog.

  • Dear Sir, you're a lifesaver! Thank you very much for this highly efficient code!

  • edited January 2018

    This was perfect except that my Linux box has 32 ports, so mapping to a letter isn't going to happen so easily. I decided to try my hand at Java, and came up with a dropdown list instead.

    Sorry about the code highlighting. I tried highlight-ctrl-o, and the pre-/pre thing, but to no avail. ctrl-t just opened another tab. Apparently wysiwyg isn't what it used to be. The formatting worked after all.

      
    
    // Up near the top
    import javax.swing.JOptionPane; // Had to change this which meant showMessageDialog() changes
    final boolean debugPort = true; 
    
    
    ... 
    
    // in setup()
    
              // Allow user to choose serial port
              String COMx = "";
              try {
                if(debugPort) printArray(Serial.list());
                int numPorts = Serial.list().length;
                 if (numPorts != 0) {
                  if (numPorts >= 2) {
                    COMx = (String) JOptionPane.showInputDialog(null, 
                    "Select COM port", 
                    "Select port", 
                    JOptionPane.QUESTION_MESSAGE, 
                    null, 
                    Serial.list(), 
                    Serial.list()[0]);
            
                    if (COMx == null) exit();
                    if (COMx.isEmpty()) exit();
                  }
                  myPort = new Serial(this, COMx, 9600); // change baud rate to your liking
                  myPort.bufferUntil('\n'); // buffer until CR/LF appears, but not required..
                }
                else {
                  JOptionPane.showMessageDialog(frame,"Device is not connected to the PC");
                  exit();
                }
            
    // Then the rest of setup() because exit() does not exit in Processing until setup() is done.
            
              catch (Exception e)
              { //Print the type of error
                JOptionPane.showMessageDialog(frame,"COM port " + COMx + " is not available (maybe in use by another program)");
                println("Error:", e);
                exit();
              }
    }
    
    
Sign In or Register to comment.