22 марта 2013 г.

Исправление ошибки ArrayIndexOutOfBoundsException: 0 в Processing под Ubuntu

Все начинают дружить Processing 1.5.1 и Arduino, используя библиотеку Firmata, чтобы передавать данные туда-сюда через Serial. Неплохо начинать с примера arduino_output в библиотеке processing-arduino. При поиске платы Processing'ом может возникнуть ошибка
 ArrayIndexOutOfBoundsException: 0
с указанием на строку
  arduino = new Arduino(this, Arduino.list()[0], 57600);
Функция Arduino.list() [0] возвращает список устройств, обнаруженных на Serial и выбирает для работы самое первое устройство. Указанная выше ошибка возникает потому, что список имен устройств с Ubuntu не совпадает с ожидаемым Processing'ом.

Поможем ему в поиске. Посмотрим в Arduino IDE, где сидит наша плата:
Это /dev/ttyACM0. Добавим такую символьную ссылку на это устройство, чтобы Processing его опознал. Для этого в терминале выполним от имени суперпользователя команду 
  ln -s /dev/ttyACM0 /dev/ttySA0
Теперь плата Arduino будет распознаваться, и Processing сможет с ней общаться. Однако это решение одноразовое, поскольку после перезагрузки компьютера udev удаляет все лишние устройства из /dev. Необходимо написать правило для udev, которое бы создавало символьную ссылку каждый раз при включении системы.
Найдем информацию об устройстве, воторая позволит нам это сделать. Для этого в терминале выполним команду
  udevadm info -a -p $(udevadm info -q path -n ttyACM0)
В терминал вывалится много чего, из которого нас интересует следующий "абзац":
looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4':
    KERNELS=="2-1.4"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 2"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="c0"
    ATTRS{bMaxPower}=="100mA"
    ATTRS{urbnum}=="17"
    ATTRS{idVendor}=="2341"
    ATTRS{idProduct}=="0043"
    ATTRS{bcdDevice}=="0001"
    ATTRS{bDeviceClass}=="02"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="8"
    ATTRS{speed}=="12"
    ATTRS{busnum}=="2"
    ATTRS{devnum}=="11"
    ATTRS{devpath}=="1.4"
    ATTRS{version}==" 1.10"
    ATTRS{maxchild}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{authorized}=="1"
    ATTRS{manufacturer}=="Arduino (www.arduino.cc)"
    ATTRS{serial}=="7413736383735181D081"
В своем правиле мы будем использовать строки
    SUBSYSTEMS=="usb"
    ATTRS{serial}=="7413736383735181D081"
Для создания текстового файла с правилом выполним команду от имени суперпользователя
gedit /etc/udev/rules.d/42-arduino.rules
и запишем в него
SUBSYSTEMS=="usb",  ATTRS{serial}=="7413736383735181D081", SYMLINK+="ttySA0"
Теперь отсоединим Arduino, перезапустим udev (от рута):
restart udev
подключим снова плату, и убедимся, что ссылка появилась:
ls /dev/ | grep ttySA