Setting serial number on CH340 USB-Serial device

There is no storage on the CH340 and family of UARTs where you could put a unique ID. This is also a problem for the PL2303 type. I have been trying to find solutions for this problem. First and easiest is the position of the device on the USB bus. It will be unique for each device. If you're using linux you can find each device under /dev/serial/by-path . There is also a /dev/serial/by-id but there will only be one entry there for this device because it shows the last one connected. FTDI chips will each have unique entries here. Cheap chips won't, but they each have an entry under /dev/serial/by-path. This position, and the device names, should persist across reboots. If you have a lot of changes to your USB devices, plug all the CH340 devices into the same hub, then plug that in. The devices will enumerate in the order that they are plugged in to the hub. This one-hub trick should work for MacOS and windows too, they should come up in the same order.

Harder method- udev rules. For devices with a unique ID such as FTDI you can set a udev rule that sees it's serial number and then creates a symlink to that device, it's straightforward.

For devices with the same or no Serial number, it's a lot more complex. I created a udev rule that looks like this:

SUBSYSTEM=="tty", ATTRS{product}=="USB2.0-Serial", RUN+="/usr/local/bin/cheapduino.py %k", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", ENV{ID_MM_DEVICE_IGNORE}="1"

when the device matches the product and vendor of the cheap arduino, it runs the script 'cheapduino.py' with the device as argument, for instance

cheapduino.py ttyUSB0

Then the cheapduino script connects by serial to the device and sends the string 'ID' and the software on the device responds DEVID=THX1138 or whatever. The script then creates a symlink /dev/THX1138 that points to /dev/ttyUSB0

There are a lot of drawbacks to this method. The script must time out if the software on the cheapduino doesn't answer. Also this is not using the SYMLINK function of udev so it won't clean up dead links on disconnect, but it will overwrite them on reconnect. All of your cheapduinos must have this functionality in their software, with different device IDs set. They all must use the same baud rate as the script unless you want to write a very complex script that takes a long time. Finally, this method works much better at low baud rate than at high baud rate, which for timing reasons may not succeed every time. (cheapduinos are cheap!) 9600 works much better than 115200 which works after several tries. But since all your CH340 arduinos must be the same speed with this method, you can only go as slow as your fastest device.

This method DOES work though, and it's what I'm using because I bought way too many of these cheap things.

In the end, buy genuine Arduinos or at least ones with FTDI chips or something else that sends a unique device ID.

=Rich


If what you want is to tell apart 2 devices that are basically identical, you have 2 ways:

  • always plug them in the same ports and use the USB tree to differentiate them
  • create an handshake protocol, where each Arduino uses a code that you have previously stored in their respective EEPROMs. It might even be possible to write a helper function for UDEV, so that the helper function does the handshake and tells UDEV the serial that is stored in each EEPROM. That would allow to write a UDEV rule for your devices.

CH340B (not the G) has an EEPROM where you can store the serialnumber.

https://www.mpja.com/download/35227cpdata.pdf

There is a windows tool as well to read/write it:

http://www.downxia.com/downinfo/196126.html

Will try to install and see how the G version behaves...