CraftDuino v2.0
  • - это CraftDuino - наш вариант полностью Arduino-совместимой платы.
  • CraftDuino - настоящий конструктор, для очень быстрого прототипирования и реализации идей.
  • Любая возможность автоматизировать что-то с лёгкостью реализуется с CraftDuino!
Просто добавьте CraftDuino!

Программирование Arduino - библиотека Firmata

Firmata library – библиотека, реализующая протокол Firmata
Firmata
Библиотека Firmata реализует протокол Firmata, что позволяет простым образом общаться с программами на компьютере.
Данная библиотека входит в состав Arduino IDE.
Удобна тем, что при необходимости не нужно изобретать велосипед и придумывать свой протокол, как, например, в этой программе управления, а уже использовать этот готовый протокол. К тому же он реализован и для Processing-а.

Рассмотрим функции библиотеки:

void begin();
void begin(long);

Описание:
Запуск/инициализация библиотеки

Параметры:
long – отличная от установленной по-умолчанию(57600) скорость обмена

void printVersion(void);
Описание:
Отправить компьютеру версию протокола

void blinkVersion(void);
Описание:
Промигать версию протокола на 13 пине.

void printFirmwareVersion(void);
Описание:
отправить название прошивки и ее версию на компьютер.

void setFirmwareNameAndVersion(const char *name, byte major, byte minor);
Описание:
установить название и версию прошивки, используя название скетча без расширения (.pde)

Отправка сообщений

void sendAnalog(byte pin, int value);
Описание:
отправить аналоговое сообщение

void sendDigitalPort(byte portNumber, int portData);
Описание:
Отправить значение порта одним 8-битным сообщением

void sendSysex(byte command, byte bytec, byte* bytev);
Описание:
послать сообщение в виде массива байт

void sendString(const char* string);
Описание:
Отправить сообщение в виде стоки

void sendString(byte command, const char* string);
Описание:
Отправить сообщение в виде стоки командного типа

Получение сообщений

int available(void);
Описание:
Проверяет наличие сообщений в буфере

void processInput(void);
Описание:
Прочесть сообщение из буфера, отправить данные зарегистрированным функциям-обработчикам

void attach(byte command, callbackFunction newFunction);
void attach(byte command, systemResetCallbackFunction newFunction);
void attach(byte command, stringCallbackFunction newFunction);
void attach(byte command, sysexCallbackFunction newFunction);


Описание:
Задать функцию-обработчик для определённого типа сообщений

void detach(byte command);
Описание:
Отменить функцию-обработчик для определённого типа сообщений

Функции-обработчики
Фунцкия-обработчик должна быть вида:

generic:
void (*callbackFunction)(byte, int);

system_reset:
void (*systemResetCallbackFunction)(void);

string:
void (*stringCallbackFunction)(char*);

sysex:
void (*sysexCallbackFunction)(byte command, byte argc, byte*argv);


Типы сообщений
Ниже представлены типы сообщений, к которым можно подключить вашу функцию-обработчик:
#define DIGITAL_MESSAGE         0x90 // данные цифрового порта (8-бит)
#define ANALOG_MESSAGE          0xE0 // аналоговое значение пина (PWM)
#define REPORT_ANALOG           0xC0 // включить/отключить отчет об аналоговом пине
#define REPORT_DIGITAL          0xD0 // включить/отключить отчет о цифровом пине
//
#define SET_PIN_MODE            0xF4 // установить режим пина: INPUT/OUTPUT/PWM/etc

#define FIRMATA_STRING          0x71 // строка: stringCallbackFunction

#define SYSTEM_RESET            0xFF // сообщение для перезагрузки прошивки: systemResetCallbackFunction


Пример:
Получение и отправка аналогового сообщения
#include <Firmata.h>

byte analogPin;

void analogWriteCallback(byte pin, int value)
{
    pinMode(pin,OUTPUT);
    analogWrite(pin, value);
}

void setup()
{
    Firmata.setFirmwareVersion(0, 1);
    Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
    Firmata.begin();
}

void loop()
{
    while(Firmata.available()) {
        Firmata.processInput();
    }
    for(analogPin = 0; analogPin < TOTAL_ANALOG_PINS; analogPin++) {
        Firmata.sendAnalog(analogPin, analogRead(analogPin)); 
    }
}


Другой пример – управление двумя сервами:
#include <Firmata.h>
#include <Servo.h>

Servo servo9;
Servo servo10;

void analogWriteCallback(byte pin, int value)
{
    if(pin == 9)
      servo9.write(value);
    if(pin == 10)
      servo10.write(value);
}

void setup() 
{
    Firmata.setFirmwareVersion(0, 2);
    Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);

    servo9.attach(9);
    servo10.attach(10);
   
    Firmata.begin(9600);
}

void loop() 
{
    while(Firmata.available())
        Firmata.processInput();
}


Теперь нужно разобраться – какой формат сообщений нужно предавать с управляющей программы компьютера (хоста).
В этом поможет описание протокола на официальном сайте
firmata.org/wiki/Protocol
а так же пример программы, управляющей состоянием портов Arduino:
firmata.org/wiki/Proposals

Исходный код которой можно скачать здесь:
www.pjrc.com/teensy/firmata_test/firmata_test.tar.gz
и разобраться, как посылать/принимать данные по данному протоколу.

Код для установки значения на выходе цифрового порта:
uint8_t buf[3];
buf[0] = 0x90 | pin;
buf[1] = val & 0x7F;
buf[2] = (val >> 7) & 0x7F;
port.Write(buf, 3);


Код для установки аналогового значения:
uint8_t buf[3];
buf[0] = 0xE0 | pin;
buf[1] = val & 0x7F;
buf[2] = (val >> 7) & 0x7F;
port.Write(buf, 3);


Код для установки состояния порта:
uint8_t buf[4];
buf[0] = 0xF4;
buf[1] = pin;
buf[2] = mode;
port.Write(buf, 3);


, где
port – экземпляр класса Serial для работы с COM-портом
pin – номер пина ардуины
val – значение для установки
mode – состояние порта – одно из:
#define MODE_INPUT    0x00
#define MODE_OUTPUT   0x01
#define MODE_ANALOG   0x02
#define MODE_PWM      0x03
#define MODE_SERVO    0x04
#define MODE_SHIFT    0x05
#define MODE_I2C      0x06


Cсылки:
arduino.cc/en/Reference/Firmata
firmata.sourceforge.net/wiki/Protocol
www.acraigie.com/programming/firmatavb/default.html

По теме:
Практическое программирование Arduino- программирование работы с COM-портом
Arduino и Matlab
Arduino и LabVIEW
  • +1
  • 1 августа 2010, 13:54
  • noonv

Комментарии (11)

RSS свернуть / развернуть
+
0
Интересное, конечно, решение, но только зачем-то подразумевает написание обработчиков. Можно было бы отдавать полный контроль управляющему приложению.

И самого главного нет — передачи данных. Есть «строка», но эту строку надо ещё парсить, а это тоже целый процесс. Нет обратной связи — дошло ли, в целости ли…
В общем сомнительная библиотека. Надо изобретать что-то своё!
avatar

savarez

  • 8 сентября 2010, 18:11
+
0
Что нет проверки целостности данных — это минус.
Разве нет передачи данных?
Cвоё, разумеется, изобрести можно, но рекомендую внимательнее присмотреться к этому протоколу.
Например, этот же протокол для работы с Arduino использует Processing, да и для взаимодействия с URBI я планирую использовать именно его.
avatar

noonv

  • 8 сентября 2010, 18:40
+
0
А разве есть передача данных? Я присмотрелся как мог, и пришёл к выводу, что даже для процессинга реализация посредственная.
Собственно для связи с процессингом я и начал писать свою библиотеку.
На мой взгляд гораздо интереснее взаимодействие на следующем уровне:
В программе для Ардуино подключаются функции в качестве событий, которым передаются данные, тут схоже как сделано в Firmata, но во-первых очень редко надо передавать String, тем более, что его не просто парсить, во-вторых длинны byte явно недостаточно для передачи большинства значений. Поэтому интереснее если будет передаваться массив int, при чём к нему ещё будет прилагаться параметр команды — для определения обработчика:

function(int * values, int length)
{
   param = values[1];
   param2 = values[2];
   ...
}

void setup()
{
  lib.attach(0, function);
  lib.attach(1, anotherFunction);
}


А из Процессинга:

  lib.send(0, new int[] {10,20,30});


0 — как команда, для определения разных функций на разные команды (чтобы не развлекаться switch-case)).

Библиотека должна сама проверять целостность, и отправлять-принимать авто-отчёт об успешности передачи и т.п.

Ну и ещё интересный и важный момент — автоматический поиск и определение порта на котором висит устройство.

В общем много есть ценных нововведений, которые в Firmata вряд ли реализуют в ближайшее время.
avatar

savarez

  • 8 сентября 2010, 19:08
+
0
это немного не то, но взглянуть стоит — RPC(Remote Procedure Call) для Arduino
avatar

noonv

  • 8 сентября 2010, 19:26
+
+1
Да, схожая тема, но пока мы тут говорили — я написал львиную долю того, чего хотел получить от Firmata.
Через некоторое время, думаю, смогу представить здесь. Вдруг кому-то будет интересно.
avatar

savarez

  • 8 сентября 2010, 19:40
+
0
Отлично! С нетерпением буду ждать :)
avatar

noonv

  • 8 сентября 2010, 19:41
+
0
А я не пойму… Serial.print уже не катит?
и на компе аналогично. Хоть процессинг, хоть на сях, хоть на (О трепещите ацкие кодеры) VB.NET
avatar

MAFia

  • 26 сентября 2011, 14:46
+
0
покопался в коде этой фирматы, нашел опрос шины i2c/ А есть ли там 1wire?
avatar

nes

  • 22 марта 2013, 23:23
+
0
а как сервами крутить, что нужно в COM слать? разъясните пожалуйста…
avatar

Borocco

  • 16 августа 2013, 15:46
+
0
аналоговое значение.
см. пример в Управляемая веб-камера или же web-cam-бот
avatar

admin

  • 16 августа 2013, 18:48
+
0
объясните подробней, что нужно на ком отправлять, допустим из arduino ide.
P.S. очень нужно, перерыл все, но так и не понял(
avatar

Borocco

  • 20 августа 2013, 15:17

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.