В Linux, как идентифицировать несколько Arduino, подключенных через USB?

Если у меня есть несколько Arduino, подключенных через USB к компьютеру с Linux, и они отображаются как

  • /tty/ACM0
  • /tty/ACM1
  • /tty/ACM2

Как определить, какая Arduino какая без подключения к ним через последовательное соединение? Есть ли на Arduino серийный номер или уникальный идентификатор?

Спасибо за ваше время.

Ситуация: Uno R3, Mega, Leonardo с /ttyACM[1,2,3]

Вывод lsusb с устройствами в указанном выше порядке:

...
Шина 001 Устройство 011: ID 2341:0043
Шина 001 Устройство 013: ID 2341:8036
...
Шина 001 Устройство 014: ID 2341:0042

lsusb -d vendor:device -vvv показывает для каждого

Уно

Шина 001 Устройство 014: ID 2341:0042
Дескриптор устройства:
бДлина 18
bDescriptorType 1
bcdUSB 1.10
bСвязь класса устройств 2
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x2341
idProduct 0x0042
bcdDevice 0.01
iManufacturer 1 Arduino (www.arduino.cc)
iProduct 2
iSerial 220 55330313735351910141
bNumConfigurations 1
Дескриптор конфигурации:
bДлина 9
bDescriptorType 2
wTotalLength 62
bNumИнтерфейсы 2
bConfigurationValue 1
iКонфигурация 0
бматрибутес 0xc0
Автономный
Максимальная мощность 100 мА
Дескриптор интерфейса:
bДлина 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
b Интерфейс связи класса 2
bInterfaceSubClass 2 Аннотация (модем)
bInterfaceProtocol 1 AT-команды (v.25ter)
интерфейс 0
Заголовок CDC:
bcdCDC 10.01
ЦКД АКМ:
bmCapabilities 0x06
посылает перерыв
линейное кодирование и последовательное состояние
Союз CDC:
bМастерИнтерфейс 0
bSlaveInterface 1
Дескриптор конечной точки:
bДлина 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmАтрибуты 3
Прерывание по типу передачи
Тип синхронизации Нет
Данные о типе использования
wMaxPacketSize 0x0008 1x 8 байт
бИнтервал 255
Дескриптор интерфейса:
bДлина 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 10 Данные CDC
bInterfaceSubClass 0 Не используется
bInterfaceProtocol 0
интерфейс 0
Дескриптор конечной точки:
bДлина 7
bDescriptorType 5
bEndpointAddress 0x04 EP 4 OUT
бматрибутес 2
Тип передачи Массовая
Тип синхронизации Нет
Данные о типе использования
wMaxPacketSize 0x0040 1x 64 байта
бИнтервал 1
Дескриптор конечной точки:
bДлина 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
бматрибутес 2
Тип передачи Массовая
Тип синхронизации Нет
Данные о типе использования
wMaxPacketSize 0x0040 1x 64 байта
бИнтервал 1
Статус устройства: 0x0000
(на автобусе)

Леонардо:

Шина 001 Устройство 013: ID 2341:8036
Дескриптор устройства:
бДлина 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (определяется на уровне интерфейса)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x2341
idProduct 0x8036
bcdDevice 1.00
iManufacturer 1 ООО «Ардуино»
iProduct 2 Ардуино Леонардо
iSerial 0
bNumConfigurations 1
Дескриптор конфигурации:
bДлина 9
bDescriptorType 2
wTotalLength 100
bNumИнтерфейсы 3
bConfigurationValue 1
iКонфигурация 0
бматрибутес 0x80
(на автобусе)
Максимальная мощность 500 мА
Ассоциация интерфейса:
bДлина 8
bDescriptorType 11
bFirstInterface 0
bInterfaceCount 2
bСвязь функционального класса 2
bFunctionSubClass 2 Аннотация (модем)
bFunctionProtocol 1 AT-команды (v.25ter)
функция 0
Дескриптор интерфейса:
bДлина 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
b Интерфейс связи класса 2
bInterfaceSubClass 2 Аннотация (модем)
bInterfaceProtocol 0 Нет
интерфейс 0
Заголовок CDC:
bcdCDC 1.10
Управление вызовами CDC:
bmCapabilities 0x01
управление вызовами
bDataInterface 1
ЦКД АКМ:
bmCapabilities 0x06
посылает перерыв
линейное кодирование и последовательное состояние
Союз CDC:
bМастерИнтерфейс 0
bSlaveInterface 1
Дескриптор конечной точки:
bДлина 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmАтрибуты 3
Прерывание по типу передачи
Тип синхронизации Нет
Данные о типе использования
wMaxPacketSize 0x0040 1x 64 байта
бИнтервал 0
Дескриптор конечной точки:
bДлина 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
бматрибутес 2
Тип передачи Массовая
Тип синхронизации Нет
Данные о типе использования
wMaxPacketSize 0x0040 1x 64 байта
бИнтервал 0
Дескриптор интерфейса:
bДлина 9
bDescriptorType 4
bInterfaceNumber 2
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Устройство пользовательского интерфейса
bInterfaceSubClass 0 Нет подкласса
bInterfaceProtocol 0 Нет
интерфейс 0
Дескриптор HID-устройства:
bДлина 9
бдескриптортип 33
bcdHID 1.01
bCountryCode 0 Не поддерживается
bNumDescriptors 1
bDescriptorType 34 Отчет
wDescriptorLength 101
Дескриптор отчета: (длина 101)
Элемент (глобальный): страница использования, данные = [0x01] 1
Общие элементы управления рабочим столом
Элемент (локальный): использование, данные = [0x02] 2
мышь
Элемент (основной): коллекция, данные = [0x01] 1
Приложение
Элемент (локальный): использование, данные = [0x01] 1
Указатель
Элемент (основной): коллекция, данные = [0x00] 0
Физический
Элемент (глобальный): идентификатор отчета, данные = [0x01] 1
Элемент (глобальный): страница использования, данные = [ 0x09 ] 9
Кнопки
Элемент (локальный): минимум использования, данные = [0x01] 1
Кнопка 1 (основная)
Элемент (локальный): максимальное использование, данные = [0x03] 3
Кнопка 3 (третичный уровень)
Элемент (глобальный): логический минимум, данные = [0x00] 0
Элемент (глобальный): логический максимум, данные = [0x01] 1
Элемент (глобальный): количество отчетов, данные = [0x03] 3
Элемент (глобальный): размер отчета, данные = [0x01] 1
Элемент (основной): ввод, данные = [0x02] 2
Переменная данных Абсолютная No_Wrap Линейная
Preferred_State No_Null_Position Non_Volatile Битовое поле
Элемент (глобальный): количество отчетов, данные = [0x01] 1
Элемент (глобальный): размер отчета, данные = [0x05] 5
Элемент (основной): ввод, данные = [0x03] 3
Постоянная Переменная Абсолютная No_Wrap Линейная
Preferred_State No_Null_Position Non_Volatile Битовое поле
Элемент (глобальный): страница использования, данные = [0x01] 1
Общие элементы управления рабочим столом
Элемент (локальный): Использование, данные = [0x30] 48
Направление-X
Элемент (локальный): Использование, данные = [0x31] 49
Направление-Y
Элемент (локальный): использование, данные = [0x38] 56
Колесо
Элемент (глобальный): логический минимум, данные = [0x81] 129
Элемент (глобальный): логический максимум, данные = [0x7f] 127
Элемент (глобальный): размер отчета, данные = [0x08] 8
Элемент (глобальный): количество отчетов, данные = [0x03] 3
Элемент (основной): ввод, данные = [0x06] 6
Переменная данных Относительная No_Wrap Линейная
Preferred_State No_Null_Position Non_Volatile Битовое поле
Элемент (основной): конец коллекции, данные = нет
Элемент (основной): конец коллекции, данные = нет

......

Дескриптор конечной точки:
bДлина 7
bDescriptorType 5
bEndpointAddress 0x84 EP 4 IN
bmАтрибуты 3
Прерывание по типу передачи
Тип синхронизации Нет
Данные о типе использования
wMaxPacketSize 0x0040 1x 64 байта
бИнтервал 1
Статус устройства: 0x0000
(на автобусе)

И Mega256:

Шина 001 Устройство 014: ID 2341:0042
Дескриптор устройства:
бДлина 18
bDescriptorType 1
bcdUSB 1.10
bСвязь класса устройств 2
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x2341
idProduct 0x0042
bcdDevice 0.01
iManufacturer 1 Arduino (www.arduino.cc)
iProduct 2
iSerial 220 55330313735351910141
bNumConfigurations 1
Дескриптор конфигурации:
bДлина 9
bDescriptorType 2
wTotalLength 62
bNumИнтерфейсы 2
bConfigurationValue 1
iКонфигурация 0
бматрибутес 0xc0
Автономный
Максимальная мощность 100 мА
Дескриптор интерфейса:
bДлина 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
b Интерфейс связи класса 2
bInterfaceSubClass 2 Аннотация (модем)
bInterfaceProtocol 1 AT-команды (v.25ter)
интерфейс 0
Заголовок CDC:
bcdCDC 10.01
ЦКД АКМ:
bmCapabilities 0x06
посылает перерыв
линейное кодирование и последовательное состояние
Союз CDC:
bМастерИнтерфейс 0
bSlaveInterface 1
Дескриптор конечной точки:
bДлина 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmАтрибуты 3
Прерывание по типу передачи
Тип синхронизации Нет
Данные о типе использования
wMaxPacketSize 0x0008 1x 8 байт
бИнтервал 255
Дескриптор интерфейса:
bДлина 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 10 Данные CDC
bInterfaceSubClass 0 Не используется
bInterfaceProtocol 0
интерфейс 0
Дескриптор конечной точки:
bДлина 7
bDescriptorType 5
bEndpointAddress 0x04 EP 4 OUT
бматрибутес 2
Тип передачи Массовая
Тип синхронизации Нет
Данные о типе использования
wMaxPacketSize 0x0040 1x 64 байта
бИнтервал 1
Дескриптор конечной точки:
bДлина 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
бматрибутес 2
Тип передачи Массовая
Тип синхронизации Нет
Данные о типе использования
wMaxPacketSize 0x0040 1x 64 байта
бИнтервал 1
Статус устройства: 0x0000
(на автобусе)

, 👍21

Обсуждение

lsusb -vvv говорит?, @Ignacio Vazquez-Abrams

Можете ли вы отключить один и посмотреть, какой из них исчезнет?, @Anonymous Penguin

Не совсем, я хочу сделать это для удаленного массива датчиков на солнечной энергии, который будет очень далеко, чтобы кто-то мог это сделать, когда он перезагрузится., @vlad b.

Игнасио Васкес-Абрамс — как я могу сопоставить информацию из lsusb -vvv с /dev/ttyACM<x>? Есть ли что-то в выводе lsusb, которое я могу разобрать? Спасибо за идею!, @vlad b.

У вас есть другой Arduino, с которым вы можете сравнить выходные данные?, @Ignacio Vazquez-Abrams

Добавил еще два типа ардуино - все 3 подключены сразу., @vlad b.

Что еще меня озадачивает, так это то, что у леонардо iSerial=0, а у остальных серийный номер., @vlad b.

Помогает ли эта статья с моего личного сайта? http://wirespeed.xs4all.nl/mediawiki/index.php/Udev_rules_file_for_Arduino_boards Мне любопытно, есть ли у других Леонардо такой же серийный номер 0, мне это кажется странным., @jippie

Что произойдет, если вы используете sudo lsusb -s............?, @jippie


8 ответов


7

Предположим, что ваш дистрибутив использует udev:

udevadm info --query=all --name=/dev/ttyACM0

Для запуска этого (sudo / su) вам могут потребоваться привилегии root. Он выведет список такой информации:

P: /devices/pci0000:00/0000:00:1d.2/usb4/4-2/4-2:1.0/tty/ttyACM0
N: ttyACM0
S: serial/by-id/usb-Dean_Camera_LUFA_USB-RS232_Adapter_74133353537351403012-if00
S: serial/by-path/pci-0000:00:1d.2-usb-0:2:1.0
E: DEVLINKS=/dev/serial/by-id/usb-Dean_Camera_LUFA_USB-RS232_Adapter_74133353537351403012-if00 /dev/serial/by-path/pci-0000:00:1d.2-usb-0:2:1.0
E: DEVNAME=/dev/ttyACM0
E: DEVPATH=/devices/pci0000:00/0000:00:1d.2/usb4/4-2/4-2:1.0/tty/ttyACM0
E: ID_BUS=usb
E: ID_MM_CANDIDATE=1
E: ID_MODEL=LUFA_USB-RS232_Adapter
E: ID_MODEL_ENC=LUFA\x20USB-RS232\x20Adapter
E: ID_MODEL_FROM_DATABASE=Uno R3 (CDC ACM)
E: ID_MODEL_ID=0043
E: ID_PATH=pci-0000:00:1d.2-usb-0:2:1.0
E: ID_PATH_TAG=pci-0000_00_1d_2-usb-0_2_1_0
E: ID_REVISION=0001
E: ID_SERIAL=Dean_Camera_LUFA_USB-RS232_Adapter_74133353537351403012
E: ID_SERIAL_SHORT=74133353537351403012
E: ID_TYPE=generic
E: ID_USB_DRIVER=cdc_acm
E: ID_USB_INTERFACES=:020201:0a0000:
E: ID_USB_INTERFACE_NUM=00
E: ID_VENDOR=Dean_Camera
E: ID_VENDOR_ENC=Dean\x20Camera
E: ID_VENDOR_FROM_DATABASE=Arduino SA
E: ID_VENDOR_ID=2341
E: MAJOR=166
E: MINOR=0
E: SUBSYSTEM=tty
E: UDEV_LOG=3
E: USEC_INITIALIZED=751387324986

Это для Uno с модифицированной прошивкой на atmega16u2 (с USB на последовательный порт). Интересующие строки, вероятно, ID_MODEL_ID и ID_MODEL_FROM_DATABASE.

,

Спасибо. В этом случае я использую OpenWrt с hotplug2 по умолчанию, но я попытаюсь переключиться на udev и протестировать это., @vlad b.


1

У меня возникло бы сильное искушение идентифицировать каким-либо другим способом, например, чтобы сам скетч реагировал на специальную команду идентификации, просто чтобы избежать странных способов идентификации устройств USB.

,

5

Вы можете добавить псевдоним для каждого. Тогда вы знаете, что есть что. Вот хорошее руководство по настройке.

Вот фрагмент, который я написал на основе руководства. В приведенном ниже примере я использую адаптер FTDI RS232RL USB-Serial, который, как я полагаю, также использует Arduino.

  1. Чтобы назначить псевдоним устройству USB-Serial, нам нужно найти некоторую информацию об устройстве.
  2. Подключите USB. Это предполагает, что вы уже установили драйверы для этого устройства, и устройство видно при вводе:

lsusb

  1. Нам понадобится следующее а. Идентификатор поставщика б. Идентификатор продукта в. COM порт устройства.
  2. Для этого нужно немного поохотиться. Все ваши устройства регистрируют записи в «/var/log/messages».

Поэтому мы можем прочитать этот файл и найти правильный USB:

grep "ftdi" /var/log/messages

Вы также можете использовать "usb"

  1. Это поиск всех сообщений с тегом ftdi:

  2. Рядом с ftdi_sio стоит число вроде 1-1.2. Это USB-устройство

grep "usb 1-1.2" /var/log/messages

Или вы можете использовать:

dmesg | grep "usb 1-1.3"
  1. Это дает нам всю необходимую информацию:

Псевдоним USB

  1. Теперь, имея список серийных номеров, давайте создадим набор правил UDEV, который создаст символическую ссылку для каждого из этих устройств. Правила UDEV обычно разбросаны по множеству файлов в /etc/udev/rules.d. Создайте новый файл с именем 99-usb-serial.rules и поместите туда следующие строки:

В этом примере мой псевдоним называется lcdbox

SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A601ERJJ", SYMLINK+="lcdbox"
  1. SYMLINK – это имя вашего псевдонима. В данном случае мой псевдоним lcdbox.
  2. Сохраните файл и введите

    sudo udevadm control --reload-rules

  3. Тип

    ls –l /dev/lcdbox

lrwxrwxrwx 1 root root 7 1 января 1970 г. /dev/lcdbox -> ttyUSB0

  1. Это показывает, что мой псевдоним lcdbox сопоставлен с ttyUSB0
,

2

Вы всегда можете распечатать какой-либо идентификатор через COM порт в void setup(). После того, как определенная плата подключена, она отправит этот идентификатор на ваш USB-интерфейс (который вы слушаете с помощью какого-то приложения-демона на вашем Linux-боксе). Как только вы получите идентификатор, вы можете сопоставить его с его путем «Ардуино1»: «/dev/ttyACM0», «Ардуино2»: «/dev/ttyACM1», 'Arduino3' : '/dev/ttyACM2'... и т. д.

Имейте в виду, что когда устройство по какой-либо причине отключено, его физический путь может измениться, поэтому вам, возможно, придется переназначить их все. Для этого случая было бы неплохо написать отдельную функцию, например: get_id(), которую вы можете вызывать в любое время (не только при запуске).

,

3

Я бы использовал скрипт для создания псевдонима в разделе /dev/, а также установил для него группу и права с помощью udev, как и в других ответах.

Но если бы у меня не было udev, я бы передал lsusb в grep или awk, например lsusb|grep -e "idProduct".

В любом случае, с правилами udev или с lsusb и grep для идентификации USB-устройств используйте idVendor, idProduct и iSerial в части Device descriptor lsusb для правильной идентификации. idVendor сообщает производителю, что idProduct должен идентифицировать продукт от производителя, но иногда они используют один и тот же идентификатор продукта для более чем одного продукта. Наконец, при необходимости iSerial должен быть уникальным идентификатором для каждого экземпляра этого продукта.

,

4

Это очень просто! Вы должны настроить прошивку чипов ftdi и добавить правило udev:

Сначала получите ftdi_eeprom через apt-get или из исходников. Идентифицируйте свое устройство через lsusb и получите идентификатор:

lsusb

Шина 001 Устройство 005: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
....

Подготовьте конфигурацию и убедитесь, что vendor_id и product_id совпадают. Настройте строки в разделе Strings, чтобы получить уникальный идентификатор для вашего устройства.

vendor_id=0x0403 # Идентификатор поставщика
product_id=0x6001 # Идентификатор продукта

max_power=50 # Макс. потребляемая мощность: значение * 2 мА. Используйте 0, если self_powered = true.

###########
# Строки #
###########
изготовитель="FTDI" # Производитель
product="Arduino Nano" # Продукт
serial="arduino1" # Серийный номер

###########
# Параметры #
###########
self_powered=false # Отключить для питания от шины
remote_wakeup=false # Включите это для функции удаленного пробуждения
use_serial=true # Использовать строку серийного номера

# Обычно out не нужно менять ни один из этих флагов
# BM_type_chip=true # Все новые чипы относятся к типу BM
in_is_isochronous=false # В конечной точке изохронно
out_is_isochronous=false # Исходящая конечная точка является изохронной
suspend_pull_downs=false # Включить приостановку подтягиваний для снижения энергопотребления
change_usb_version=false # Изменить версию USB
usb_version=0x0200 # Используется только при включенном change_usb_version

########
# Разное #
########

filename="eeprom.old" # Имя файла, оставьте пустым, чтобы пропустить запись файла
cbus0=RXLED#
cbus1=TXLED#

Дамп текущей ftdi-прошивки:

ftdi_eeprom --read-eprom

Эта команда создает ${pwd}/eeprom.old, который содержит текущую прошивку на ftdi. Создайте резервную копию этого файла, прежде чем продолжить, потому что во время flash-eeprom файл перезаписывается. После резервного копирования прошейте ftdi:

ftdi_eeprom --flash-eeprom myconfig.conf

Теперь создайте правило udev, например

SUBSYSTEMS=="usb", ATTRS{idProduct}=="6001", ATTRS{idVendor}=="0403", SYMLINK+="$attr{serial}", OWNER="bananapi", GROUP="pi", MODE="0777"

в /etc/udev/rules.d/90-arduino-usb.rules и перезапустите udev.

service udev restart

Отключите и снова подключите устройство и попробуйте

ls -lah /dev/arduino1

Где arduino1 — это строка, определенная в разделе serial в приведенном выше .conf.

См. также: Риски ftdi_eeprom? - TX всегда высокий после прошивки

,

6

В Ubuntu 16.04 (и, возможно, в предыдущих версиях или других дистрибутивах) вы можете сделать следующее:

> ls /dev/serial/by-id

который отображает (на моей коробке, где подключен Arduino UNO):

usb-Arduino__www.arduino.cc__0043_A4139363931351318241-if00

Здесь можно легко найти идентификатор устройства 0043 (UNO).

Этот файл на самом деле является ссылкой на /dev/ttyACM0 в моем ящике.

,

Используйте ls -la /dev/serial/by-id, чтобы увидеть ссылку, @Qinjie


1

Обзор

  • Одним из способов, упомянутых ansi_lumen в его ответе, является прошивка ftdi чип EEPROM, чтобы иметь уникальный серийный номер, который затем может быть определяется правилами UDEV.

    Но оказалось, что он не будет работать на дешевых китайских ардуино, которые вместо этого FTDI имеет чип CH340G, который не имеет EEPROM для хранения уникальный идентификатор (CH340B должен работать).

  • Этот ответ предлагает написать правило UDEV со специальным скриптом который просит Arduino отправить свой уникальный идентификатор через последовательный порт. Проблема с то есть вам нужно изменить скетч Arduino и вообще это довольно сложно.

Идентификация по порту

Поэтому самый простой способ, который я нашел, заключался в использовании правил UDEV и идентификации ардуино по порту USB (devpath) поэтому подключение Arduino к тому же порту (даже во вложенных USB-концентраторах) создаст постоянное имя.

Настройка TLDR:

Измененная версия этого

  1. Найдите Arduino idVendor и idProduct:

lsusb

Вы получите что-то вроде этого:

...
Шина 004 Устройство 001: ID 1d6b:0003 Корневой концентратор Linux Foundation 3.0
Шина 003 Устройство 124: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial адаптер
Шина 003 Устройство 123: ID 214b:7000
Шина 003 Устройство 122: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial адаптер
Шина 003 Устройство 121: ID 1a86:7523 Адаптер USB-Serial QinHeng Electronics HL-340
Шина 003 Устройство 120: ID 1a40:0101 Концентратор Terminus Technology Inc.
...

Подключив/отключив Arduino, найдите, какой из них (у меня подключено 3). Ищем его ID. В моем случае "...ID 1a86:7523 QinHeng...". Итак, idVendor=1a86, idProduct=7523

  1. Создайте новый файл правил UDEV:

sudo nano /etc/udev/rules.d/99-usb-serial.rules

  1. Измените значения idVendor и idProduct на то, что вы нашли на предыдущем шаге, скопировав и вставив их в созданный нами файл правил:

SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="ttyUSB-arduino%s{/devpath}"

  1. Перезагрузить правила UDEV

sudo udevadm control --reload

  1. Переподключите Arduino, и теперь у него будет уникальное имя. Чтобы проверить это, введите:

ls /dev/ttyUSB*


Что будет выведено:

/dev/ttyUSB1 /dev/ttyUSB3 /dev/ttyUSB-arduino2.1 /dev/ttyUSB-arduino2.4 /dev/ttyUSB2 /dev/ttyUSB4 /dev/ttyUSB-arduino2.2 /dev/ttyUSB-arduino3

Как видите, мы по-прежнему получаем /dev/ttyUSBx, как и раньше, которые всегда меняются в зависимости от того, какой из них был подключен первым. Но теперь у нас также есть /dev/ttyUSB-arduino{port}, которые всегда одинаковы для одного и того же порта и только для Arduino. Чтобы проанализировать, что означает «..arduino2.4»: 2 относится ко второму порту ноутбука, а 4 — к четвертому порту usb-концентратора.

Чтобы лучше увидеть его, введите:

...
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 124: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter
Bus 003 Device 123: ID 214b:7000  
Bus 003 Device 122: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter
Bus 003 Device 121: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter
Bus 003 Device 120: ID 1a40:0101 Terminus Technology Inc. Hub
...

Вывод:

...
/: Шина 03.Порт 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 480M
|__ Порт 1: Dev 5, если 0, класс = устройство с интерфейсом пользователя, драйвер = usbhid, 12M
|__ Порт 1: Dev 5, если 1, класс = устройство с интерфейсом пользователя, драйвер = usbhid, 12M
|__ Порт 2: Dev 84, если 0, класс=концентратор, драйвер=концентратор/4p, 480M
|__ Порт 1: Dev 85, если 0, класс = определенный класс поставщика, драйвер = ch341, 12M
|__ Порт 2: Dev 86, если 0, класс = определенный класс поставщика, драйвер = ch341, 12M
|__ Порт 3: Dev 87, если 0, класс=концентратор, драйвер=концентратор/4p, 480M
|__ Порт 4: Dev 88, если 0, класс = определенный класс поставщика, драйвер = ch341, 12M
|__ Порт 3: Dev 89, если 0, класс = определенный класс поставщика, драйвер = ch341, 12M
/: Шина 02.Порт 1: Dev 1, Class=root_hub, Driver=ehci-pci/2p, 480M
|__ Порт 1: Dev 2, если 0, класс=концентратор, драйвер=концентратор/6p, 480M
...

Подключаясь/отключаясь, вы можете видеть, какие устройства к каким портам подключены

,