08.06.2010

Processing vs Arduino

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

Самый простой способ - использовать библиотеку Serial, которая доступна по умолчанию. При помощи операторов Serial.print() можно передать произвольные данные через USART МК ATmega в реальный или виртуальный COM-порт (текущие модели Arduino/Freeduino используют  USB-to-TTL мост на чипе FT232RL). Естественно, можно не только получать, но и  отправлять, организовав таким образом полноценный интерактив.

Написание собственного протокола обмена, пусть даже не очень сложного - весьма скучное занятие. В поисках того, как реализовать его просто и непринужденно, вы обязательно наткнетесь на Processing: он примечателен тем, что именно от его IDE была унаследована ArduinoIDE.

Что же такое Processing?

Если кратко - еще один язык программирования, порожденный от Java и позволяющий быстро создавать программы построения изображений и анимации, а также делать все это интерактивным. При этом Arduino как раз и может стать тем самым элементом, который эту интерактивность обеспечивает.

Скачав, распаковав и запустив последнюю версию PDE (Processing Development Evironment), вы найдете сходство с ArduinoIDE настоль очевидным, что руки сами начнут автоматически набирать "setup":


Здесь программы тоже называются скетчами. Однократно выполняемая часть оформляется в setup, повторяемая циклически - в draw (аналог loop). Меню Sketch | Run вызывает компиляцию скетча в полноценное Java-приложение и его запуск в отдельном окне, куда оно старательно отображает свою картинку. После окончательной отладки можно нажать Export (соответствует пиктограмме Upload для ArduinoIDE) - и тогда создается html-код страницы с java-апплетом, готовый к размещению в www.


Для быстрого ознакомления с различиями Processing и Wiring создана вот эта страничка. По большому счету, все сводится к отличиям C++ от Java, которые обычно подробно описываются в любом учебнике по Java.

Вернемся к Arduino, точнее к его библиотеке Firmata. Она берет на себя "черную работу" по поддержке механизма обмена между скетчем и программой на "большом брате". Разработчику остается только продумать логику работы этого небольшого АПК, определить поведение нужных callback-функций и вставить вызовы библиотеки в setup и loop. Если вы уже пробовали реализовывать интерактив средствами Serial - попробуйте как-нибудь с Firmata - должно получиться проще, лучше и быстрее.

Именно с помощью Firmata можно "прикрутить" Arduino к Processing-у, для этого:
  • скачайте библиотеку для Processing-а и распакуйте ее в папку libraries/arduino в каталоге для скетчей Processing (создайте каталоги при необходимости) - но имейте ввиду, что в версии 1.1 она уже включена в состав дистрибутива, так что скорее всего можно обойтись без этого шага;
  • запустите ArduinoIDE, откройте скетч из Examples | Firmata | StandardFirmata, откомпилируйте и загрузите его в свою Arduino-совместимую плату (и не отключайте её после этого);
  • запустите Processing, откройте пример из папки libraries/arduino/examples/arduio_output через File | Open;
  • запустите скетч на выполнение.
Если в ответ на попытку компиляции Processing ругается на невозможность найти cc.arduino.*, сходите в меню Sketch | Add file..., добавьте файл libraries/arduino/library/Arduino.jar и повторите попытку компиляции.

Результатом работы скетча является вот такое нехитрое окно состояния цифровых выходов: 



Каждый кубик обозначает один цифровой выход от 13 до 0. Щелкая по нему, мы переключаем состояние межу HIGH и LOW. Как минимум, к выходу 13 подключен светодиод L, так что изменение его состояния можно наблюдать вполне визуально.

Вот как это выглядит внутри скетча Processing:

import processing.serial.*;

import cc.arduino.*;

Arduino arduino;

color off = color(4, 79, 111);
color on = color(84, 145, 158);

int[] values = { Arduino.LOW, Arduino.LOW, Arduino.LOW, Arduino.LOW,
 Arduino.LOW, Arduino.LOW, Arduino.LOW, Arduino.LOW, Arduino.LOW,
 Arduino.LOW, Arduino.LOW, Arduino.LOW, Arduino.LOW, Arduino.LOW };

void setup() {
  size(470, 200);
  
  println(Arduino.list());
  arduino = new Arduino(this, Arduino.list()[0], 57600);
  
  for (int i = 0; i <= 13; i++)
    arduino.pinMode(i, Arduino.OUTPUT);
}

void draw() {
  background(off);
  stroke(on);
  
  for (int i = 0; i <= 13; i++) {
    if (values[i] == Arduino.HIGH)
      fill(on);
    else
      fill(off);
      
    rect(420 - i * 30, 30, 20, 20);
  }
}

void mousePressed()
{
  int pin = (450 - mouseX) / 30;
  
  if (values[pin] == Arduino.LOW) {
    arduino.digitalWrite(pin, Arduino.HIGH);
    values[pin] = Arduino.HIGH;
  } else {
    arduino.digitalWrite(pin, Arduino.LOW);
    values[pin] = Arduino.LOW;
  }
}


Сначала в функции setup() происходит создание объекта Arduino, через вызов его конструктора:

  arduino = new Arduino(this, Arduino.list()[0], 57600);

Первым аргументом в списке идет this - так уж принято. Далее указывается порт, к которому подключен Arduino, например /dev/ttyUSB0 для Linux. Для его получения существует функция Arduino.list() - статическая (можно использовать без привязки к экземпляру объекта), возвращающая список плат. Подключение будет выполнено к первой из этого списка (элемент с номером 0).  Последним идет скорость порта, для этой версии Firmata она фиксирована и составляет 57600.

После создания объекта можно вызывать привычные операторы Wiring, не забывая предварять их именем объекта arduino (например - перевод всех цифровых пинов в режим вывода):

  for (int i = 0; i <= 13; i++)
    arduino.pinMode(i, Arduino.OUTPUT);

Циклически вызываемый метод draw() занимается перерисовкой кубиков по текущим значениям выходов, хранимых в промежуточном массиве values (инициализирован в начале значениями константы Arduino.LOW).

И, наконец, обработчик событий от мыши mousePressed() - вычисляет по координатам клика нужный кубик, инвертирует соответствующую ему ячейку массива values и вызывает digitalWrite, чтобы актуализировать состояние выхода нашего Arduino.

Попробуем наваять скетч самостоятельно, например - пусть при помощи потенциометра будет регулироваться насыщенность красным. Схема подключения переменного сопротивления до безобразия тривиальна:





А вот скетч Processing:

import processing.serial.*;

import cc.arduino.*;

Arduino arduino;

void setup() {
  size(200, 200);  
  arduino = new Arduino(this, Arduino.list()[0], 57600);
}

void draw() {
  background(255 * arduino.analogRead(0) / 1024,0,0);
}

Всю отрисовку выполняет функция background(value1, value2, value3) - где valueN соответствуют составляющим красного, зеленого и синего. Зная, что analogRead вернет число от 0 до 1023, нехитрой операцией масштабируем этот диапазон в 0..255.

Как видите - запредельно просто, почти как с ArduinoIDE. Наиболее выдающиеся скетчи Processing можно посмотреть на openprocessing.org. Все они, конечно же, доступны под лицензией CC-SA.

 В статье использованы материалы из Playground:
 
http://www.arduino.cc/playground/Interfacing/Processing

12 комментариев:

  1. спасибо!хорошая,полезная статья,прочитал с удоволбствием :)

    ОтветитьУдалить
  2. процессинг интересен только в плане визуализации. Я так и не нашел библиотек сделать нормальный пользовательский интерфейс (меню, кнопки, виджеты). Может пропустил?

    ОтветитьУдалить
  3. >>процессинг интересен только в плане визуализации. Я так и не нашел библиотек сделать нормальный пользовательский интерфейс (меню, кнопки, виджеты). Может пропустил?

    скетч процессинга это java аплет. В принципе можно руками или другими способами, но можно.

    ОтветитьУдалить
  4. GUI-библиотеки имеются: http://www.processing.org/reference/libraries/#interface

    ОтветитьУдалить
  5. Можете помочь с самодельной аруиной? Сделал себе
    Arduino Serial Single Sided ver.3 (c Atmega168-20PU)
    http://robocraft.ru/blog/arduino/19.html
    и не могу ей управлять из Processing.

    Скачал arduino-1.0.1 http://arduino.googlecode.com/files/arduino-1.0.1-windows.zip
    и processing-1.5.1http://processing.googlecode.com/files/processing-1.5.1-windows.zip
    Запускаю arduino-1.0.1
    Настройки:
    СОМ порт - СОМ1
    Плата Arduino NG or older w/ATmega168
    JP0 в положении 2-3
    JP4 замкнут
    Запускаю скетч Blink, LED13 мигает с интервалом 1 сек.
    Плата рабочая.

    Отсюда: http://arduino.cc/playground/Interfacing/Processing
    загружаю библиотеку:
    http://arduino.cc/playground/uploads/Interfacing/processing-arduino.zip
    и распаковываю ее в
    \processing-1.5.1\modes\java\libraries\
    С http://rxtx.qbang.org/wiki/index.php/Download
    качаю http://rxtx.qbang.org/pub/rxtx/rxtx-2.1-7-bins-r2.zip
    Заменяю файлы:
    \arduino-1.0.1\rxtxSerial.dll
    \arduino-1.0.1\lib\RXTXcomm.jar
    \processing-1.5.1\modes\java\libraries\serial\library\RXTXcomm.jar
    \processing-1.5.1\modes\java\libraries\serial\library\windows32\rxtxSerial.dll
    \processing-1.5.1\modes\java\libraries\serial\library\windows64\rxtxSerial.dll
    файлами из rxtx-2.1-7-bins-r2.zip

    Заливаю в ардуину StandardFirmdata.

    Код: Выделить всё
    Загрузка выполнена,
    Размер скетча в двоичном коде: 11 850 байт (из 14 336 байт максимум).


    Закрываю arduino-1.0.1.

    Запускаю из Processing libraries\arduino\arduino_output:

    Код: Выделить всё
    Stable Library
    =========================================
    Native lib Version = RXTX-2.1-7
    Java lib Version = RXTX-2.1-7
    [0] "COM1"



    Все вроде бы работает, но LED13 не мигает, когда я нажимаю на квадратики.
    Хотя RX помигивает в момент нажатия.

    Пробовал стандартный тест

    Код: Выделить всё
    import processing.serial.*;
    import cc.arduino.*;

    Arduino arduino;
    int ledPin = 13;

    void setup()
    {
    //println(Arduino.list());
    arduino = new Arduino(this, Arduino.list()[0], 57600);
    arduino.pinMode(ledPin, Arduino.OUTPUT);
    }

    void draw()
    {
    arduino.digitalWrite(ledPin, Arduino.HIGH);
    delay(1000);
    arduino.digitalWrite(ledPin, Arduino.LOW);
    delay(1000);
    }

    тоже не работает.
    При этом на этом же софте Arduino nano прекрасно мигает 13м светодиодом.
    Что я делаю не так?

    ОтветитьУдалить
    Ответы
    1. Меня смущает шаг с заменой файлов. Вы уверены, что это необходимо делать?

      Удалить
    2. Без замены файлов при запуске скетча выдает что то вроде такого:

      WARNING: RXTX Version mismatch
      Jar version = RXTX-2.2pre1
      native lib Version = RXTX-2.2pre2

      а после замены файлов:

      Stable Library
      =========================================
      Native lib Version = RXTX-2.1-7
      Java lib Version = RXTX-2.1-7

      Удалить
    3. Проблема решена. Нужно скорость СОМ порта везде поменять на 4800.
      Больше чем 4800 Atmega168-20PU не тянет.

      Удалить
  6. Проблема решена. Нужно скорость СОМ порта везде поменять на 4800.
    Больше чем 4800 Atmega168-20PU не тянет.

    ОтветитьУдалить
  7. Скетч не работает.
    соощение: illegalAccessError:tried to access class processing.core. PApplet$RegisteredMethod
    Ошибка в строке
    arduino = new Arduino(this, Arduino.list()[1], 9600);
    Имеются порты СОМ1 и СОМ3.
    Порт для Ардуино - СОМ3.
    Как разрешить проблему?

    ОтветитьУдалить
    Ответы
    1. Статья написана более 4 лет назад. Уверены, что берете самые последние версии всех компонентов?

      Удалить
  8. Что бы не мучиться, устанавливаем свежие библиотеки
    http://playground.arduino.cc/Interfacing/Processing

    ОтветитьУдалить