Программирование 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();
}

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

Исходный код которой можно скачать здесь:
http://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сылки:
http://arduino.cc/en/Reference/Firmata
http://firmata.sourceforge.net/wiki/Protocol
http://www.acraigie.com/programming/firmatavb/default.html

По теме
Практическое программирование Arduino- программирование работы с COM-портом
Arduino и Matlab
Arduino и LabVIEW


11 комментариев на «“Программирование Arduino — библиотека Firmata”»

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

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

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

    • А разве есть передача данных? Я присмотрелся как мог, и пришёл к выводу, что даже для процессинга реализация посредственная.
      Собственно для связи с процессингом я и начал писать свою библиотеку.
      На мой взгляд гораздо интереснее взаимодействие на следующем уровне:
      В программе для Ардуино подключаются функции в качестве событий, которым передаются данные, тут схоже как сделано в 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 вряд ли реализуют в ближайшее время.

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

    • Отлично! С нетерпением буду ждать 🙂

Добавить комментарий

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Arduino Bluetooth CraftDuino DIY Google IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд юмор

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение