简体   繁体   中英

Python: Testing Serial Ports for Answer

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!!

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

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. .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM