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