J'ai un Arduino qui se lie parfois à /dev/ttyUSB0
et d'autres fois à /dev/ttyUSB1
, faisant échouer mon script.
Je ne veux pas énumérer toutes les possibilités de l'emplacement de mon appareil, mais je préfère qu'il soit lié à un endroit statique, par exemple /dev/arduino
.
Comment puis-je y parvenir?
Comme suggéré, vous pouvez ajouter quelques règles udev. J'ai édité le /etc/udev/rules.d/10-local.rules
contenir:
ACTION=="add", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", SYMLINK+="my_uart"
Vous pouvez vérifier les variables de votre appareil en exécutant
udevadm info -a -p $(udevadm info -q path -n /dev/ttyUSB0)
Il existe un guide plus approfondi sur lequel vous pouvez lire http://www.reactivated.net/writing_udev_rules.html
La syntaxe des règles ci-dessus peut fonctionner sur certaines distributions, mais n'a pas fonctionné sur la mienne (Raspbian). Comme je n'ai jamais trouvé un seul document qui explique tous les tenants et aboutissants, j'ai écrit le mien, à trouver ici . Voilà à quoi cela se résume.
1. découvrez ce qui est sur ttyUSB:
dmesg | grep ttyUSB
2. répertoriez tous les attributs de l'appareil:
udevadm info --name=/dev/ttyUSBx --attribute-walk
(avec votre numéro d'appareil au lieu de x, bien sûr). Choisissez un ensemble d'identifiants uniques, par exemple idVendor + idProduct. Vous pouvez également avoir besoin de SerialNumber si vous avez plusieurs appareils avec les mêmes idVendor et idProduct. Les numéros de série doivent être uniques pour chaque appareil.
3. Créez un fichier /etc/udev/rules.d/99-usb-serial.rules
avec quelque chose comme cette ligne:
SUBSYSTEM=="tty", ATTRS{idVendor}=="1234", ATTRS{idProduct}=="5678", SYMLINK+="your_device_name"
(en supposant que vous n'avez pas besoin d'un numéro de série là-bas, et bien sûr avec les numéros pour idVendor et idProduct que vous avez trouvés à l'étape 2.
4. Chargez la nouvelle règle:
Sudo udevadm trigger
5. Vérifiez ce qui s'est passé:
ls -l /dev/your_device_name
montrera à quel numéro ttyUSB le lien symbolique est allé. Si c'est /dev/ttyUSB1
, puis vérifiez qui en est propriétaire et à quel groupe il appartient:
ls -l /dev/ttyUSB1
Alors juste pour le plaisir:
udevadm test -a -p $(udevadm info -q path -n /dev/your_device_name)
J'ai un Rasperry Pi avec quatre caméras. Je prends pix avec fswebcam
qui identifie les caméras comme /dev/video0
.. video3
. Parfois, la caméra est video0
, vide02
, video4
et video6
mais on peut oublier ça pour l'instant.
J'ai besoin d'un ID persistant pour identifier un numéro de caméra afin que, par exemple video0
est toujours le même appareil photo car je sous-titre les photos. Malheureusement, cela ne se produit pas de manière fiable - au démarrage, les caméras sont énumérées comme video0
..video3
mais pas toujours de la même manière.
Les caméras ont toutes le même identifiant et numéro de série.
La solution à ce problème implique des règles udev, mais il y a aussi beaucoup d'hameçons.
Si vous exécutez la commande
udevadm info –attribute-walk –path=/dev/video0
vous obtenez une chape de sortie, mais les bits saillants sont
KERNEL=”video0”, SUBSYSTEM=”video4linux” and KERNELS=”1:1.2.4:1.0”.
Le bit KERNELS est un port de concentrateur USB. Avec quatre caméras, il y en a quatre - elles ne changent pas au redémarrage, mais le video{x}
associé à un port peut changer.
Nous avons donc besoin d'une règle udev pour lier un numéro vidéo à un port de concentrateur USB - quelque chose comme:
KERNEL==”video0”,SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0”,SYMLINK+=”camera0”
Semble simple - accédez à la caméra avec
fswebcam –d $realpath /dev/camera0
Sauf que cela ne fonctionne pas - si vous mettez cela dans une règle udev et que le système a alloué video0 (au démarrage) à un autre port, la règle udev est ignorée. Le lien symbolique vers /dev/camera0
dit essentiellement no such device
. Carré un.
Ce que nous voulons, c'est lier un lien symbolique à une adresse de concentrateur USB, pas un video{x}
nombre. Il a fallu un programme Python.
La première étape consistait à exécuter
fswebcam –d /dev/video${x} tst.jpg
pour x
entre 1 et 8. L'existence de tst.jpg
après chaque appel identifie s'il y a une caméra sur ce numéro de vidéo. À partir de cela, faites une liste des numéros de vidéo actifs. D'après mon expérience, c'est soit 0,1,2,3
ou 0,2,4,6
pour les caméras que j'ai utilisées.
D'autres peuvent bien sûr construire cette liste en utilisant un processus différent.
Ensuite, pour chaque numéro de vidéo dans la liste, exécutez
udevadm info –attribute-walk –path=/dev/videox > dd
et extraire le KERNELS= line
de dd
. À partir de ce processus, vous vous retrouvez avec une liste des adresses de port USB pour les caméras. Triez cette liste afin qu'à l'étape suivante, vous la traitiez toujours dans le même ordre. Appelez cela la "liste d'adresses".
Exécutez le udevadm … > dd
chose encore et faire une liste qui ressemble à
KERNEL==”video0”, SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0 ”,SYMLINK+=”camerax”. Call this the “video list”.
Parcourez maintenant la liste d'adresses - pour chaque entrée, trouvez l'entrée correspondante dans la liste des vidéos. Créez une nouvelle liste qui ressemble à une collection de lignes comme
KERNEL==”video0”, SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0 ”,SYMLINK+=”camera2”
Le x (numéro de lien symbolique) est remplacé par le numéro de séquence dans la liste d'adresses.
Vous avez maintenant une règle udev qui fonctionne. Un lien symbolique lié à une adresse de concentrateur USB, quel que soit le numéro vidéo attribué à ce port au démarrage.
Écrivez la liste finale dans un fichier /etc/udev/rules.d/cam.rules
. Courir udevadm trigger
pour l'activer et le travail est terminé. /dev/camera2
sera le même appareil photo (port USB) quel que soit son numéro de vidéo.
J'ai également pu trouver un appareil unique dans /dev/serial/by-id
. Je n'ai pas encore essayé de redémarrer, mais les fichiers de ce répertoire n'étaient que des liens vers le fichier de périphérique approprié (ttyACM[0-9]
). `
J'utilise Arch Linux sur Raspberry Pi, mais je suis tombé dessus juste en faisant un find
pour les noms de fichiers contenant "Arduino". Mes python fonctionnent bien en utilisant ces fichiers comme périphériques pour lire/écrire des données vers/depuis mes Arduinos (jusqu'à présent, deux sur un seul Pi).
Juste pour dire que ce qui précède a fonctionné pour moi et a également monté automatiquement l'appareil pour moi après avoir placé une entrée dans/etc/fstab (et il appelle également umount après le retrait du bâton)
c'est à dire.
/ etc/fstab
# See /etc/udev/rules.d/5-usb-disk.rules
/dev/backup /vol/backup ext4 defaults,errors=remount-ro 0 1
cat /etc/udev/rules.d/5-usb-stick.rules
#
# the next line creates a symlink to this disk drive called /dev/backup
# i.e.
# root:# ls -la /dev/backup
# lrwxrwxrwx 1 root root 3 Jul 22 19:33 /dev/backup -> sg0
# Backup usb stick - create /dev/backup
# ATTRS{model}=="Cruzer Blade "
ACTION=="add", ATTRS{model}=="Cruzer Blade ", SYMLINK+="backup"
# Clean up after removal
ACTION=="remove", ATTRS{model}=="Cruzer Blade ", RUN+="/bin/umount /vol/backup"
Donc, après avoir inséré ma clé USB, je reçois:
root:# mount | grep sd
/dev/sda1 on /vol/backup type ext4 (rw,relatime,errors=remount-ro,data=ordered)