How to avoid flipping between ttyUSB0 and ttyUSB1 when reconnect to USB port under Python using pySerial?

蹲街弑〆低调 提交于 2021-02-07 09:16:21

问题


I have a serial Python program, Linux environment (Raspbian / Raspberry Pi), that uses a serial port via USB & serial adapter. I need to handle a situation when the user unplug the USB adapter and then re-insert it.

The problem is that, on reconnect, the ttyUSB0 becomes ttyUSB1 and so the port is no longer found. However, if I stop the Python program (keyboard interrupt) and again unplug and re-insert the USB adapter, then the port goes back to ttyUSB0 (and so I can start over again). This can happen only when the Python program is stopped.

I tested the program in a flip-flop mode (and it seems to be working) in order to use ttyUSB1 when ttyUSB0 is no longer found and then vice versa, use ttyUSB0 back in case ttyUSB1 is no longer found etc., but this looks like a weird solution to me.

Question: is there a better way to force pySerial to "forget" it has ever been connected to ttyUSB0 in case of error and release the current port to the system while the program is still running ?

Here is a working flip-flop test program:

import serial
import time

p = "/dev/ttyUSB0"

while True:
    error_flag = False
    try:
        s = serial.Serial(port=p, baudrate=9600, bytesize=8, parity="N", stopbits=1, timeout=None, xonxoff=False, rtscts=False, write_timeout=None, dsrdtr=False, inter_byte_timeout=None)
    except Exception as e:
        error_flag = True
        if "ttyUSB0" in str(e):
            p = "/dev/ttyUSB1"
            print ("port is now", p)
        elif "ttyUSB1" in str(e):
            p = "/dev/ttyUSB0"
            print ("port is now", p)
        else:
            print (e)   # none of the above

    # if not error_flag do whatever etc.

    time.sleep(1)

回答1:


You could try creating a udev rule that would create a symlink to that USB device and then you would be able to use something like /dev/myUSB that would always stay the same for that specific USB device.

First you will need to find some identifying information for the USB drive. Typing in lsusb should display some information that looks like:

Bus 001 Device 004: ID 0403:6001 Future Technology Devices International

In this example 0403 is the Vendor Id and 6001 is the Product Id.

Create a file named 99_usbdevice.rules(i don't think the name matters, just the directory):

sudo nano /etc/udev/rules.d/99_usbdevices.rules

Note that the directory above may be specific to Raspbian.

Copy/paste the line below into the file and save it:

SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", SYMLINK+="myUSB"

Restart your Pi or unplug the USB and re-insert it. There should now be a /dev/myUSB entry that you can use the same way you would the ttyUSB# entry.




回答2:


Do not forget to close the file descriptor of /dev/ttyUSB0 as soon as you detect that the user unplugged the USB adapter (read or write with error), and before the reinsertion. If you properly close the device, the ttyUSB1 device will never appear. On the other hand, you can see in some cases also ttyUSB2, ttyUSB3, and so on, if all the previous ttyUSBx are blocked because not closed.



来源:https://stackoverflow.com/questions/48356223/how-to-avoid-flipping-between-ttyusb0-and-ttyusb1-when-reconnect-to-usb-port-und

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!