How to auto-detect Arduino COM port?

Viewed 49987

I'm using an Arduino with the Firmata library for communication to a C# application, and I want to eliminate a COM port configuration component since it can change from machine to machine...

Is it possible to:

  1. Enumerate list of COM ports in the system? (In my googling I've seen some fairly ugly Win32 API code, hoping there's maybe a cleaner version now)
  2. Auto-detect which COM port(s) are connected to an Arduino?
8 Answers

I just had a similar challenge with a Teensyduino communicating with a PC based processing language program. It may be useful for someone working with something Java or processing language rather than C#.

The basic idea of this solution was to send a handshake request ("!sh\n") to each Serial port and then listen for a response ("$h\n") from each device until the correct handshake response was received. Thereby showing which of the ports was the device I was seeking.

Also, I'm quite new to StackOverflow so please forgive and educate me if I'm breaking any StackOverflow etiquette in this answer.

Processing Language Code:

import processing.serial.*;

int ellipticalWalkerTeensyIndex; /* Represents Elliptical Walker Serial Port index in the Serial.list() String array. */
boolean latch;

String[] serialPortList = Serial.list();
int serialPortCount = serialPortList.length;
Serial[] ports = new Serial[serialPortCount];
int[] serialConnected = new int[serialPortCount];

void setup(){
    for (int z = 0; z < serialPortCount; ++z) { /* Initialise serialConnected array to 0; Anything not marked to 1 later will be ignored. */
        serialConnected[z] = 0;
    } 

    ellipticalWalkerTeensyIndex = -1; /* Initialise ellipticalWalkerTeensyIndex to -1, as the correct serial port is not yet known. */
    latch = false;

    for (int z = 0; z < serialPortCount; ++z) {
        try {
            ports[z] = new Serial(this, serialPortList[z], 9600);
            serialConnected[z] = 1; /* Mark this index as connected. */
            ports[z].write("!sh");  /* Send handshake request;  Expected response is "$h\n" */
        }catch (Exception e){
            println("Could not connect to "+Integer.toString(z)+" exception details: "+e);
        }
    }
}

void draw(){
    if (ellipticalWalkerTeensyIndex < 0) {
        for (int z = 0; z < serialPortCount; ++z) {
            if(serialConnected[z]>0){ /* Only attempt communication if we have marked this serial port as connected during the setup routine. */
                if (ports[z].available()>0) { /* Read from serial port 'z' if data is available. */
                    String lineOfData = ports[z].readStringUntil('\n');
                    if(lineOfData.charAt(0)=='$' && lineOfData.charAt(1)=='h'){ /* Check if received response matches expected handshake response */
                        ellipticalWalkerTeensyIndex = z; /* Note the correct serial port for the teensy. */
                    }
                } 
            }
        }    
    }else{
        if (!latch) {
            println("The teensyduino is on serial port: "+serialPortList[ellipticalWalkerTeensyIndex]);
            latch = true;
            exit();
        }
    }
}

Runtime results:

PS C:\repos\elliptical_walker> processing-java --sketch=c:\repos\elliptical_walker\EW0 --run
The teensyduino is on serial port: COM3
Finished.

With this php script you can transmit and receive data from arduino

<?php
 /**
 * Remember to go to Device Manager> Ports (COM & LPT)>Arduino XXX (COMXX)>right
 * click>Properties>
 * Port Settings>Advanced>uncheck "use FIFO buffers ........."
 * In other hand, remeber that the Tx speed has to be the same in PhpConnect.php, in
 * Arduino sketch and in the COM
 * properties in Device manager, I selected 115200 b/s.
 *
 */
  // RX form PC**************
 $t = $_POST['text1'];
 include 'PruebaBatchCOM.php';
 $puerto = escapeshellarg($usbCOM);
 $dato = escapeshellarg($t);
 exec("node C:\\xampp\\htdocs\\DisenoWEBTerminados\\BatteryTester\\Scripts\\writeandread.js {$puerto} {$dato} 2>&1", $output1);
 $str = implode($output1);
 $str1 = explode(",",$str);
 $myJSON = json_encode($str1);// this is the response to AJAX
 echo $myJSON;
 ?>

PruebaBatchCOM.php is

<?php
$puerto = array(); 
$file111 = "PruebaCOMRetrieve.bat";
exec($file111, $puerto);
$usbCOM = implode(",",$puerto); 
?>

PruebaCOMRetrieve.bat

@echo off
setlocal

for /f "tokens=1* delims==" %%I in ('wmic path win32_pnpentity get caption  
/format:list ^| find "Arduino Uno"') do (
call :setCOM "%%~J"
)

:: end main batch
goto :EOF

:setCOM <WMIC_output_line>
:: sets _COM#=line
setlocal
set "str=%~1"
set "num=%str:*(COM=%"
set "num=%num:)=%"
set port=COM%num%
echo %port%
Related