Python: Testing Serial Ports for Answer
Question: I'm trying to build a short code that will test all Serial COM ports (I'm on
windows) for reply. For example, I have a Arduino connected on COM3, and when
it connects, it sends a serial message.

I want that when I run the python script it automatically detects which is the
right COM port to use.

I have the function that lists all the ports, but I can't make it work to test
all of them and detect in which the arduino is connected.

**Python:**

    
    
    import serial
    import time
    import _winreg as winreg
    import itertools
    import datetime
    
    def enumerate_serial_ports():
        """ Uses the Win32 registry to return an
            iterator of serial (COM) ports
            existing on this computer.
        """
        path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
        try:
            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path)
        except WindowsError:
            raise IterationError
    
        for i in itertools.count():
            try:
                val = winreg.EnumValue(key, i)
                yield str(val[1])
            except EnvironmentError:
                break
    
    connected = False
    
    for porta in enumerate_serial_ports():
        print "TRYING PORT: " + porta
        start = datetime.datetime.now()
        delta=0
        ser = serial.Serial(porta,9600,timeout=0)
        if ser.isOpen():
            while ser.isOpen() and delta < 1:
                delta = (datetime.datetime.now()-start).seconds
                r = ser.read()
                if r == None:
                    print "connected!"
    

**Arduino Code**

    
    
    void setup(){
      // Open serial connection.
      Serial.begin(9600);
      pinMode(13, OUTPUT);
      Serial.write(6); 
    }
    
    void loop(){ 
    
    } 
    

Thank you!!


Answer: This is a common problem in that there is no "connection" for serial ports. As
you see, when you open() a serial port, that has no relation to whether
something is plugged in on the other end of the wires. All the open() calls
are doing is establishing the handles to the serial port hardware inside that
machine. The open() guarantees nothing about the other side of the cable.

The concept of "connection" is something you must create. Connections are
normally created by some protocol handshake between the two devices that
establishes to both that they are talking to who they expect.

Two general approaches are:

  * probe and check for a response
  * listen for a beacon

I warn in this related question that the first approach of pushing bytes at an
unknown device is not the safest approach:

[Related question](http://stackoverflow.com/questions/21615591/how-can-i-keep-
the-serial-address-consistent-on-my-arduino-uno-mac-osx)

You have chosen the second approach where the Python side passively listens
for a beacon. You need something similar to this, where you receive some
predefined message and respond when you receive:

    
    
    // loop for a short time listening for a *
    if r != None:
        if r.endswith("*"):
            ser.write("I_hear_you")
            print "connected"
    

The Arduino side powers up and broadcasts the beacon. It continues to
broadcast until someone answers

    
    
    beaconmode = True;
    
    void loop() {
       if (beaconmode) {
         delay(1000);
         Serial.write("*");
         // Serial.read() and check for "I_hear_you"
         if (someone heard my beacon) {
           beaconmode = false;
           // now the two devices are "connected"
           connectedmode = true;
       }
       if (connectedmode) {
         // do normal stuff
       }
    }
    

If you are seeking to be even more robust, this handshake could be expanded
one step. As it is, it only confirms that the Python side heard the Arduino
side. The added step would be for the Arduino to acknowledge by transmitting
"I heard that you heard me". Then you would have something similar to how the
3 way handshake used to establish TCP connections. .

