W Linuksie, jak rozpoznać wiele Arduinos podłączonych przez USB?

17

Jeśli mam wiele Arduino podłączonych przez USB do komputera z systemem Linux, a pojawią się one jako

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

Jak mogę zidentyfikować, które Arduino jest, bez łączenia się z nimi przez połączenie szeregowe ? Czy na Arduino jest numer seryjny lub unikatowy identyfikator?

Dziękuję za Twój czas.

Sytuacja: Uno R3, Mega, Leonardo with / ttyACM [1,2,3]

Wyjście lsusb z urządzeniami w wyżej wymienionej kolejności:

...
Magistrala 001 Urządzenie 011: ID 2341: 0043
Magistrala 001 Urządzenie 013: ID 2341: 8036
...
Magistrala 001 Urządzenie 014: ID 2341: 0042

lsusb -d vendor: urządzenie -vvv pokazuje dla każdego

ONZ

Magistrala 001 Urządzenie 014: ID 2341: 0042
Deskryptor urządzenia:
  bDługość 18
  bDescriptorType 1
  bcdUSB 1.10
  bDeviceClass 2 Communications
  bDeviceSubClass 0
  bDeviceProtocol 0
  bMaxPacketSize0 8
  idVendor 0x2341
  idProduct 0x0042
  bcdDevice 0.01
  iManufacture 1 Arduino (www.arduino.cc)
  iProdukt 2
  iSerial 220 55330313735351910141
  bNumConfiguracje 1
  Deskryptor konfiguracji:
    b Długość 9
    bDescriptorType 2
    wTotalLength 62
    bNumInterfaces 2
    bConfigurationValue 1
    iConfiguracja 0
    bmAttributes 0xc0
      Własne zasilanie
    MaxPower 100mA
    Deskryptor interfejsu:
      b Długość 9
      bDescriptorType 4
      bInterfaceNumber 0
      bAlternateSetting 0
      bNumEndpoints 1
      bInterfaceClass 2 Communications
      bInterfaceSubClass 2 Streszczenie (modem)
      bInterfaceProtocol 1 Polecenia AT (v.25ter)
      Interfejs 0
      Nagłówek CDC:
        bcdCDC 10.01
      CDC ACM:
        bmCapabilities 0x06
          wysyła przerwę
          kodowanie linii i stan szeregowy
      CDC Union:
        bMasterInterface 0
        bSlaveInterface 1
      Deskryptor punktu końcowego:
        b Długość 7
        bDescriptorType 5
        b Punkt końcowy 0x82 EP 2 IN
        bmAttributes 3
          Przenieś typ transferu
          Typ synchronizacji Brak
          Dane typu użycia
        wMaxPacketSize 0x0008 1x 8 bajtów
        b Interwał 255
    Deskryptor interfejsu:
      b Długość 9
      bDescriptorType 4
      bInterfaceNumber 1
      bAlternateSetting 0
      bNumEndpoints 2
      bInterfaceClass 10 CDC Data
      bInterfaceSubClass 0 Nieużywany
      bInterfaceProtocol 0
      Interfejs 0
      Deskryptor punktu końcowego:
        b Długość 7
        bDescriptorType 5
        b Adres końcowy 0x04 EP 4 OUT
        bmAttributes 2
          Rodzaj transferu luzem
          Typ synchronizacji Brak
          Dane typu użycia
        wMaxPacketSize 0x0040 1x 64 bajty
        b Interwał 1
      Deskryptor punktu końcowego:
        b Długość 7
        bDescriptorType 5
        b Adres końcowy 0x83 EP 3 IN
        bmAttributes 2
          Rodzaj transferu luzem
          Typ synchronizacji Brak
          Dane typu użycia
        wMaxPacketSize 0x0040 1x 64 bajty
        b Interwał 1
Stan urządzenia: 0x0000
  (Zasilany z magistrali)

Leonardo:

Magistrala 001 Urządzenie 013: ID 2341: 8036
Deskryptor urządzenia:
  bDługość 18
  bDescriptorType 1
  bcdUSB 2.00
  bDeviceClass 0 (Zdefiniowane na poziomie interfejsu)
  bDeviceSubClass 0
  bDeviceProtocol 0
  bMaxPacketSize0 64
  idVendor 0x2341
  idProduct 0x8036
  bcdDevice 1.00
  iMan Producent 1 Arduino LLC
  iProduct 2 Arduino Leonardo
  iSerial 0
  bNumConfiguracje 1
  Deskryptor konfiguracji:
    b Długość 9
    bDescriptorType 2
    wTotalLength 100
    bNumInterfaces 3
    bConfigurationValue 1
    iConfiguracja 0
    bmAttributes 0x80
      (Zasilany z magistrali)
    MaxPower 500mA
    Powiązanie interfejsu:
      b Długość 8
      bDescriptorType 11
      bFirstInterface 0
      bInterfaceCount 2
      bFunkcja Klasa 2 Komunikacja
      bFunctionSubClass 2 Abstract (modem)
      bFunctionProtocol 1 Polecenia AT (v.25ter)
      iFunkcja 0
    Deskryptor interfejsu:
      b Długość 9
      bDescriptorType 4
      bInterfaceNumber 0
      bAlternateSetting 0
      bNumEndpoints 1
      bInterfaceClass 2 Communications
      bInterfaceSubClass 2 Streszczenie (modem)
      bInterfaceProtocol 0 Brak
      Interfejs 0
      Nagłówek CDC:
        bcdCDC 1.10
      Zarządzanie połączeniami CDC:
        bmCapabilities 0x01
          zarządzanie połączeniami
        bDataInterface 1
      CDC ACM:
        bmCapabilities 0x06
          wysyła przerwę
          kodowanie linii i stan szeregowy
      CDC Union:
        bMasterInterface 0
        bSlaveInterface 1
      Deskryptor punktu końcowego:
        b Długość 7
        bDescriptorType 5
        b Adres końcowy 0x81 EP 1 IN
        bmAttributes 3
          Przenieś typ transferu
          Typ synchronizacji Brak
          Dane typu użycia
        wMaxPacketSize 0x0040 1x 64 bajty
        b Interwał 0
      Deskryptor punktu końcowego:
        b Długość 7
        bDescriptorType 5
        b Adres końcowy 0x83 EP 3 IN
        bmAttributes 2
          Rodzaj transferu luzem
          Typ synchronizacji Brak
          Dane typu użycia
        wMaxPacketSize 0x0040 1x 64 bajty
        b Interwał 0
    Deskryptor interfejsu:
      b Długość 9
      bDescriptorType 4
      bInterfaceNumber 2
      bAlternateSetting 0
      bNumEndpoints 1
      bInterfaceClass 3 Human Interface Device
      bInterfaceSubClass 0 Brak podklasy
      bInterfaceProtocol 0 Brak
      Interfejs 0
        Deskryptor urządzenia HID:
          b Długość 9
          bDescriptorType 33
          bcdHID 1.01
          bCountryCode 0 Nieobsługiwany
          bNumDescriptors 1
          bDescriptorType 34 Raport
          wDescriptorLength 101
          Deskryptor raportu: (długość wynosi 101)
            Pozycja (globalna): Strona użytkowania, dane = [0x01] 1
                            Ogólne elementy sterujące pulpitu
            Pozycja (lokalna): użycie, dane = [0x02] 2
                            Mysz
            Pozycja (główna): kolekcja, dane = [0x01] 1
                            Podanie
            Pozycja (lokalna): użycie, dane = [0x01] 1
                            Wskaźnik
            Pozycja (główna): kolekcja, dane = [0x00] 0
                            Fizyczny
            Pozycja (globalna): identyfikator raportu, dane = [0x01] 1
            Pozycja (globalna): Strona użytkowania, dane = [0x09] 9
                            guziki
            Pozycja (lokalna): minimum użycia, dane = [0x01] 1
                            Przycisk 1 (podstawowy)
            Pozycja (lokalna): Maksymalne użycie, dane = [0x03] 3
                            Przycisk 3 (trzeciorzędowy)
            Pozycja (globalna): minimum logiczne, dane = [0x00] 0
            Pozycja (globalna): logiczne maksimum, dane = [0x01] 1
            Pozycja (globalna): liczba raportów, dane = [0x03] 3
            Pozycja (globalna): rozmiar raportu, dane = [0x01] 1
            Pozycja (główna): Dane wejściowe, dane = [0x02] 2
                            Zmienna danych Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Pozycja (globalna): liczba raportów, dane = [0x01] 1
            Pozycja (globalna): rozmiar raportu, dane = [0x05] 5
            Pozycja (główna): Dane wejściowe, dane = [0x03] 3
                            Stała Zmienna Absolutna No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Pozycja (globalna): Strona użytkowania, dane = [0x01] 1
                            Ogólne elementy sterujące pulpitu
            Pozycja (lokalna): użycie, dane = [0x30] 48
                            Kierunek-X
            Pozycja (lokalna): użycie, dane = [0x31] 49
                            Kierunek-Y
            Pozycja (lokalna): użycie, dane = [0x38] 56
                            Koło
            Pozycja (globalna): minimum logiczne, dane = [0x81] 129
            Pozycja (globalna): maksimum logiczne, dane = [0x7f] 127
            Pozycja (globalna): rozmiar raportu, dane = [0x08] 8
            Pozycja (globalna): liczba raportów, dane = [0x03] 3
            Pozycja (główna): Dane wejściowe, dane = [0x06] 6
                            Zmienna danych Relative No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Pozycja (główna): End Collection, data = none
            Pozycja (główna): End Collection, data = none

            ......

      Deskryptor punktu końcowego:
        b Długość 7
        bDescriptorType 5
        b Punkt końcowy 0x84 EP 4 IN
        bmAttributes 3
          Przenieś typ transferu
          Typ synchronizacji Brak
          Dane typu użycia
        wMaxPacketSize 0x0040 1x 64 bajty
        b Interwał 1
Stan urządzenia: 0x0000
  (Zasilany z magistrali)

I Mega256:

Magistrala 001 Urządzenie 014: ID 2341: 0042
Deskryptor urządzenia:
  bDługość 18
  bDescriptorType 1
  bcdUSB 1.10
  bDeviceClass 2 Communications
  bDeviceSubClass 0
  bDeviceProtocol 0
  bMaxPacketSize0 8
  idVendor 0x2341
  idProduct 0x0042
  bcdDevice 0.01
  iManufacture 1 Arduino (www.arduino.cc)
  iProdukt 2
  iSerial 220 55330313735351910141
  bNumConfiguracje 1
  Deskryptor konfiguracji:
    b Długość 9
    bDescriptorType 2
    wTotalLength 62
    bNumInterfaces 2
    bConfigurationValue 1
    iConfiguracja 0
    bmAttributes 0xc0
      Własne zasilanie
    MaxPower 100mA
    Deskryptor interfejsu:
      b Długość 9
      bDescriptorType 4
      bInterfaceNumber 0
      bAlternateSetting 0
      bNumEndpoints 1
      bInterfaceClass 2 Communications
      bInterfaceSubClass 2 Streszczenie (modem)
      bInterfaceProtocol 1 Polecenia AT (v.25ter)
      Interfejs 0
      Nagłówek CDC:
        bcdCDC 10.01
      CDC ACM:
        bmCapabilities 0x06
          wysyła przerwę
          kodowanie linii i stan szeregowy
      CDC Union:
        bMasterInterface 0
        bSlaveInterface 1
      Deskryptor punktu końcowego:
        b Długość 7
        bDescriptorType 5
        b Punkt końcowy 0x82 EP 2 IN
        bmAttributes 3
          Przenieś typ transferu
          Typ synchronizacji Brak
          Dane typu użycia
        wMaxPacketSize 0x0008 1x 8 bajtów
        b Interwał 255
    Deskryptor interfejsu:
      b Długość 9
      bDescriptorType 4
      bInterfaceNumber 1
      bAlternateSetting 0
      bNumEndpoints 2
      bInterfaceClass 10 CDC Data
      bInterfaceSubClass 0 Nieużywany
      bInterfaceProtocol 0
      Interfejs 0
      Deskryptor punktu końcowego:
        b Długość 7
        bDescriptorType 5
        b Adres końcowy 0x04 EP 4 OUT
        bmAttributes 2
          Rodzaj transferu luzem
          Typ synchronizacji Brak
          Dane typu użycia
        wMaxPacketSize 0x0040 1x 64 bajty
        b Interwał 1
      Deskryptor punktu końcowego:
        b Długość 7
        bDescriptorType 5
        b Adres końcowy 0x83 EP 3 IN
        bmAttributes 2
          Rodzaj transferu luzem
          Typ synchronizacji Brak
          Dane typu użycia
        wMaxPacketSize 0x0040 1x 64 bajty
        b Interwał 1
Stan urządzenia: 0x0000
  (Zasilany z magistrali)
vlad b.
źródło
lsusb -vvvmówi?
Ignacio Vazquez-Abrams,
Czy możesz odłączyć jeden i zobaczyć, który znika?
Anonimowy pingwin
1
Nie bardzo, chcę to zrobić dla zdalnego zestawu czujników zasilanych energią słoneczną, który będzie bardzo daleko dla kogoś, kto to zrobi po ponownym uruchomieniu.
vlad b.
Ignacio Vasquez-Abrams - jak mogę zmapować informacje z lsusb -vvv na / dev / ttyACM <x>? Czy w wyjściu lsusb jest coś, co mogę przeanalizować? Dziękuję za pomysł!
vlad b.
Czy masz inne Arduino, z którym możesz porównać dane wyjściowe?
Ignacio Vazquez-Abrams,

Odpowiedzi:

6

Zakładając, że twoja dystrybucja używa udev:

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

Do uruchomienia tego mogą być potrzebne uprawnienia roota (sudo / su). Wyświetli listę takich informacji:

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

Dotyczy to Uno ze zmodyfikowanym oprogramowaniem układowym na atmega16u2 (z USB na szeregowy). Linie zainteresowania to prawdopodobnie ID_MODEL_ID i ID_MODEL_FROM_DATABASE.

użytkownik2973
źródło
Dziękuję Ci. Używam OpenWrt w tym przypadku domyślnie z hotplug2, ale spróbuję przełączyć się na udev i przetestować to.
vlad b.
5

Możesz dodać alias dla każdego. Wtedy wiesz, który jest który. Oto fajny samouczek jak to skonfigurować.

Oto fragment, który napisałem na podstawie samouczka. W poniższym przykładzie używam adaptera USB-szeregowego FTDI RS232RL, co moim zdaniem jest tym, czego używa Arduino.

  1. Aby przypisać alias do urządzenia USB-Szeregowego, musimy znaleźć pewne informacje na urządzeniu
  2. Podłącz USB. Zakłada się, że masz już zainstalowane sterowniki do tego użytku przez urządzenie i urządzenie jest widoczne podczas pisania:

lsusb

  1. Będziemy potrzebować następujących: Identyfikator dostawcy b. Identyfikator produktu c. Numer seryjny urządzenia
  2. Aby to zrobić, trzeba trochę polować. Wszystkie twoje urządzenia rejestrują wpisy w „/ var / log / messages”.

Dlatego możemy odczytać ten plik i znaleźć odpowiedni USB:

grep "ftdi" /var/log/messages

Możesz także użyć „usb”

  1. Oto wszystkie wiadomości oznaczone tagiem ftdi:

  2. Obok ftdi_sio jest liczba taka jak 1-1.2. To jest urządzenie USB

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

Lub możesz użyć:

dmesg | grep "usb 1-1.3"
  1. To daje nam wszystkie potrzebne informacje:

Alias ​​USB

  1. Teraz, mając listę numerów seryjnych w dłoni, stwórzmy zestaw reguł UDEV, który utworzy ładne dowiązanie symboliczne dla każdego z tych urządzeń. Reguły UDEV są zwykle rozproszone na wiele plików w /etc/udev/rules.d. Utwórz nowy plik o nazwie 99-usb-serial.rules i umieść tam następujące linie:

W tym przykładzie mój alias nazywa się „lcdbox”

SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A601ERJJ", SYMLINK+="lcdbox"
  1. SYMLINK to nazwa Twojego aliasu. W tym przypadku moim aliasem jest lcdbox.
  2. Zapisz plik i wpisz

    sudo udevadm control --reload-rules

  3. Rodzaj

    ls –l / dev / lcdbox

lrwxrwxrwx 1 root root 7 sty 1 1970 / dev / lcdbox -> ttyUSB0

  1. To pokazuje, że mój alias lcdbox jest zmapowany na ttyUSB0
PhillyNJ
źródło
4

To całkiem proste! Musisz dostosować oprogramowanie układowe ftdi i dodać regułę udev:

Najpierw uzyskaj ftdi_eepromza pośrednictwem apt-getlub ze źródeł. Zidentyfikuj swoje urządzenie za pomocą lsusb i uzyskaj identyfikator:

lsusb

Magistrala 001 Urządzenie 005: ID 0403: 6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
…

Przygotuj config i upewnij się, że vendor_idi product_iddopasować. Dostosuj ciągi wStrings sekcji, aby uzyskać unikalny identyfikator urządzenia.

vendor_id = 0x0403 # Identyfikator dostawcy
product_id = 0x6001 # Identyfikator produktu

max_power = 50 # Max. pobór mocy: wartość * 2 mA. Użyj 0, jeśli self_powered = true.

###########
# Ciągi #
########### 
producent = „FTDI” # Producent
product = „Arduino Nano” # Produkt
serial = "arduino1" # Serial

###########
# Opcje #
###########
self_powered = false # Wyłącz to dla zasilania magistrali
remote_wakeup = false # Włącz to dla funkcji zdalnego budzenia
use_serial = true # Użyj ciągu numeru seryjnego

# Zwykle nie trzeba zmieniać żadnej z tych flag
# BM_type_chip = true # Wszystkie nowsze żetony są typu BM
in_is_isochronous = false # W punkcie końcowym jest izochroniczny
out_is_isochronous = false # Out Endpoint is Isochronous
suspend_pull_downs = false # Włącz zawieszenie rozwijania dla niższej mocy
change_usb_version = false # Zmień wersję USB
usb_version = 0x0200 # Używany tylko, gdy włączona jest zmiana_usb_version

########
# Misc #
########

filename = "eeprom.old" # Nazwa pliku, pozostaw puste, aby pominąć zapisywanie pliku
cbus0 = RXLED #
cbus1 = TXLED #

Zrzuć bieżące oprogramowanie sprzętowe ftdi:

ftdi_eeprom --read-eprom

To polecenie tworzy ${pwd}/eeprom.old, które zawiera bieżące oprogramowanie układowe na ftdi. Wykonaj kopię zapasową tego pliku przed kontynuowaniem , ponieważ w trakcie flash-eepromjego zapisywania plik jest przepisywany. Po utworzeniu kopii zapasowej sflashuj ftdi:

ftdi_eeprom --flash-eeprom myconfig.conf

Teraz utwórz regułę udev

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

w /etc/udev/rules.d/90-arduino-usb.rulesi ponownie uruchom udev.

service udev restart

Odłącz i ponownie podłącz urządzenie i spróbuj

ls -lah /dev/arduino1

Gdzie arduino1jest ciąg zdefiniowany serialw powyższym .conf.

Zobacz także: Ryzyko związane z ftdi_eeprom? - TX zawsze wysoki po flashowaniu

ansi_lumen
źródło
3

Użyłbym skryptu, aby utworzyć alias poniżej, /dev/a także ustawić grupę i prawa do niego, udevpodobnie jak inne odpowiedzi.

Ale gdybym nie miał udevbym rurę lsusbpod greplub awk, jak lsusb|grep -e "idProduct".

W każdym razie, z udevprzepisami lub z lsusbi grepdo identyfikacji urządzeń USB, użyj idVendor, idProducta iSerialw Device descriptorczęści lsusbdo właściwego idenification. idVendorInformuje o Manufaturer, idProductpowinny indentify produkt od producenta, ale czasami używać tego samego identyfikatora produktu dla więcej niż jednego produktu. Wreszcie, w razie potrzeby, iSerialpowinien być unikalnym identyfikatorem dla każdego przykładu tego produktu.

Anders
źródło
3

W systemie Ubuntu 16.04 (a może także w poprzednich wersjach lub innych dystrybucjach) możesz:

> ls /dev/serial/by-id

który wyświetla (na moim urządzeniu, do którego podłączony jest Arduino UNO):

usb-Arduino__www.arduino.cc__0043_A4139363931351318241-if00

Tutaj możesz łatwo znaleźć identyfikator urządzenia 0043 (UNO).

Ten plik jest w rzeczywistości linkiem do /dev/ttyACM0mojej skrzynki.

jfpoilpret
źródło
2

Zawsze możesz wykonać jakiś wydruk identyfikatora poprzez serial in void setup (). Po podłączeniu określonej płyty wyśle ​​ten identyfikator do interfejsu USB (którego słuchasz za pomocą jakiejś aplikacji demona na twoim Linux-ie). Po otrzymaniu identyfikatora możesz zamapować go na ścieżkę „Arduino1”: „/ dev / ttyACM0”, „Arduino2”: „/ dev / ttyACM1”, „Arduino3”: „/dev/ttyACM2” ... etc

Pamiętaj, że kiedy urządzenie zostanie odłączone z jakiegoś powodu, może zmienić swoją fizyczną ścieżkę, więc może być konieczne ponowne mapowanie wszystkich z nich. W tym przypadku dobrze byłoby napisać osobną funkcję np: get_id (), którą można wywołać w dowolnym momencie (nie tylko podczas uruchamiania).

cyberbrain
źródło
1

Mógłbym pokusić się o identyfikację w inny sposób, na przykład o to, że sam szkic zareaguje na specjalne polecenie identyfikacji, aby uniknąć dziwnych sposobów identyfikowania urządzeń przez USB.

EternityForest
źródło
0

Przegląd

  • Jednym ze sposobów, jak wspomniano w odpowiedzi na ansi_lumen, jest flashowanie pamięci EEPROM ftdi w celu uzyskania unikalnego numeru seryjnego, który mógłby następnie zostać zidentyfikowany przez reguły UDEV.

    Ale okazuje się, że nie będzie działać na tanich chińskich Arduinos, które zamiast FTDI mają układ CH340G, który nie ma pamięci EEPROM do przechowywania unikalnego identyfikatora ( CH340B powinien działać ).

  • Ta odpowiedź sugeruje napisanie reguły UDEV za pomocą specjalnego skryptu, który prosi Arduino o przesłanie unikalnego identyfikatora przez port szeregowy. Problem polega na tym, że musisz zmodyfikować szkic Arduino i ogólnie jest to dość skomplikowane.

Identyfikacja według portu

Tak więc najprostszym sposobem, jaki znalazłem, było użycie reguł UDEV i identyfikacja Arduinos według portu USB (devpath), więc połączenie Arduino z tym samym portem (nawet w zagnieżdżonych hubach USB) stworzy trwałą nazwę .

Konfiguracja TLDR:

Zmodyfikowana wersja tego

  1. Znajdź Arduino idVendor i idProduct:

lsusb

Otrzymasz coś takiego:

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

Podłączając / odłączając Arduino znajdź, który to jest (mam 3 podłączone). Szukamy jego identyfikatora. W moim przypadku „... ID 1a86: 7523 QinHeng ...”. Więc idVendor = 1a86, idProduct = 7523

  1. Utwórz nowy plik reguł UDEV:

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

  1. Zmodyfikuj wartości idVendor i idProduct według tego, co znalazłeś w poprzednim kroku podczas kopiowania, wklej go do utworzonego przez nas pliku reguł:

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

  1. Załaduj ponownie reguły UDEV

sudo udevadm control --reload

  1. Wymień Arduinos, a teraz będzie miało unikalną nazwę. Aby przetestować, wpisz:

ls /dev/ttyUSB*


Co da wynik:

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

Jak widać, nadal otrzymujemy / dev / ttyUSBx jak poprzednio, które zawsze się zmieniają w zależności od tego, który z nich został podłączony jako pierwszy. Ale teraz mamy także / dev / ttyUSB-arduino {port}, które są zawsze takie same dla tego samego portu i tylko dla Arduinos. Aby przeanalizować, co oznacza „..arduino2.4”: 2 oznacza drugi port laptopa, a 4 - czwarty port koncentratora USB.

Aby lepiej to zobaczyć, wpisz:

lsusb -t

Wynik:

...
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 480M
    |__ Port 1: Dev 5, If 0, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 1: Dev 5, If 1, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 2: Dev 84, If 0, Class=Hub, Driver=hub/4p, 480M
        |__ Port 1: Dev 85, If 0, Class=Vendor Specific Class, Driver=ch341, 12M
        |__ Port 2: Dev 86, If 0, Class=Vendor Specific Class, Driver=ch341, 12M
        |__ Port 3: Dev 87, If 0, Class=Hub, Driver=hub/4p, 480M
        |__ Port 4: Dev 88, If 0, Class=Vendor Specific Class, Driver=ch341, 12M
    |__ Port 3: Dev 89, If 0, Class=Vendor Specific Class, Driver=ch341, 12M
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/2p, 480M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/6p, 480M
...

Łącząc / rozłączając możesz zobaczyć, które urządzenia są na których portach

Gintaras Grėbliūnas
źródło