How can I avoid flipping between ttyUSB0 and ttyUSB1 when reconnecting to USB port under Python using pySerial?
Asked Answered
T

3

6

I have a serial Python program, Linux environment (Raspbian / Raspberry Pi), that uses a serial port via a USB-to-serial adapter. I need to handle a situation when the user unplugs the USB adapter and then reinsert 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 reinsert 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.

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)
Toucan answered 20/1, 2018 at 12:37 Comment(0)
F
12

You could try creating a udev rule that would create a symbolic link 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 Raspberry Pi or unplug the USB and reinsert it. There should now be a /dev/myUSB entry that you can use the same way you would the ttyUSB# entry.

Felicific answered 20/1, 2018 at 12:51 Comment(1)
You can find the manual, for example, here or hereTuddor
G
0

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's are blocked because not closed.

Gingras answered 29/5, 2019 at 13:58 Comment(0)
M
0

If the opened port file is closed when unplugged (or on error handler), then the port name will not change on subsequent connection of the USB device. If left open then it will create a different name each time.

Match answered 25/2, 2021 at 12:26 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.