Skip to content

Instantly share code, notes, and snippets.

@hiroeorz
Last active October 15, 2023 05:04
Show Gist options
  • Save hiroeorz/7868628 to your computer and use it in GitHub Desktop.
Save hiroeorz/7868628 to your computer and use it in GitHub Desktop.
firmataプロトコル覚え書き

Firmataプロトコル概要 (Ver 2.3)

FirmataはPC - マイコン間でやり取りするためのプロトコルです。汎用入出力の値の取得・書き込みその他の操作をPC側からArduinoのようなマイコンに対して行う為に使用されます。

firmata.org

Arduinoでの使用

ArduinoでFirmataプロトコルを使用してホストコンピュータとやり取りする場合は、ArduinoIDEを立ち上げて、ファイル -> スケッチの例 -> Firmata -> Standard Firmata を選択、開きそのままArduinoに書き込めば良いです。

##プロトコルフォーマット

  • 現在の最新バージョンは2.3です。
  • 扱えるアナログの最大点数は16点です。
  • 扱えるデジタルの最大点数は128点です。

Firmataプロトコル

データメッセージ

デジタルメッセージ(0x90 - 0x9F)

  • デジタルメッセージではデジタル状態の取得、書き込みを行います。
  • マイコンからホストコンピュータへ送信した場合は値の通知になります。
  • ホストコンピュータからマイコンへ送信した場合は値の書き込み要求になります。
  • Arduinoの場合、ホストコンピュータからデジタル入力pinに対してONビットを送信した場合はプルアップ回路の使用が有効になります。
内容 説明
種別コード + port番号 0x90 - 0x9F 種別コード。0から数えて3番目のportは"0x93"となる
0〜6bitデジタル状態 0b00000000 - 0b01111111 指定ポートの1〜7bitの状態をbitで表す。8bitめは使用不可
7bitデジタル状態 0b00000000 - 0b00000001 指定ポートの8bitの状態をbitで表す。2bitめ以降は不使用
説明

デジタルのON,OFF状態をbitの0,1として表現します。デジタル状態は8bitのまとまりを1portとして扱いますが、送信データの8bitめは使用できませんので8bitのうち 1-7bitを上位1byteに、8bitめだけを2byteめに埋め込んで、デジタルデータ部分全体で2byteとして送信します。

例として、全てのデジタルpinがONした(0から数えて)1portめの状態を送信する場合を考えます。

1portめの値を送信するので、種別コードは 0x91となります。

8bit全てONなので、11111111 ですが、8bitめは使えないので8bitめを2byteめに入れ、1byteめの8bitめには0を入れておきます。

00000001 01111111

種別コードを先頭に足した、最終的に送信する電文は

0x91 0x7F(0b01111111) 0x01(0b00000001)

となります。


アナログメッセージ(0xE0 - 0xEF)

  • アナログメッセージではアナログ状態の取得を行います。
  • マイコンからホストコンピュータへ送信した場合は値の通知になります。
内容 説明
種別コード + pin番号 0xE0 - 0xEF 種別コード。0から数えて3番目のpinは"0xE3"となる
アナログ値下位7bit 0〜127 指定アナログ値の下位7bitの値
アナログ値上位7bit 0〜127 指定アナログ値の上位7bitの値
説明

アナログ値の送信に使用します。アナログ値は一つの値を下位7bitと上位7bitとに分割して送信します。 デジタル値同様、値送信各1バイトの最上位ビット(8bitめ)は使用できません。

例として、アナログ値327を送信する場合を考えます。 327は00000001 01000111 です。しかし8bitめは使えませんので、下位の8bitめを上位の1ビットめに入れて、上位を全体に1bitずらします。

00000001 01000111 -> 00000010 01000111

下位の8bitめにあった 0 を上位の1bitめにずらして上位bit全体を左にシフトしています。 送信するときは下位 -> 上位の順番ですので、01000111 00000010として送信します。

この場合、pin番号が3だとすると、送信する電文全体を1バイト16進数で表すと

0xE3 0x47(0b01000111) 0x02(0b00000010)

となります。受け取った側はこれとは逆の操作をして元の値を取り出します。


バージョン通知(0xF9)

  • Firmataのプロトコルバージョンを通知します。
内容 説明
種別コード 0xF9 0xF9固定
メジャーバージョン番号 0〜127
マイナーバージョン番号 0〜127
説明

バージョン番号を通知します。 例として、バージョン番号 2.3 の場合はメジャーバージョン番号は 2 マイナーバージョン番号は 3 となります。

8bitめは使えませんのでそれぞれが取り得る値は 0〜127となります。

バージョン番号2.3を送る場合は

0xF9 0x02 0x03

となります。

制御メッセージ

pinモード設定(0xF4)

  • 指定pinの入出力モードを設定します。
内容 説明
種別コード 0xF4 0xF4固定
pin番号 0〜127 pin番号
モード 0〜4 0:入力 1:出力 2:アナログ 3:PWM(アナログ出力) 4:SERVO
説明

pin番号5をデジタル入力として設定する場合に送信する電文は

0xF4 0x05 0x01

となります。


アナログ値通知設定(0xC0 - 0xCF)

  • 指定アナログpinの、一定時間おき値通知の有効・無効を設定します。
内容 説明
種別コード + pin番号 0xC0〜0xCF pin番号が0から数えて3の場合は0xC3となる
有効/無効 0〜127 0:無効 0以外:有効
説明

有効/無効のフラグは0か、0以外の値かで判断します。例として4番pinのアナログ値通知を有効にするには

0xC4 0x01

となります。

この設定を有効にした場合、以後は有効にしたpinのアナログメッセージ アナログメッセージ(0xE0 - 0xEF) を一定時間おきに受け取る事になります。


デジタル変化通知設定(0xD0 - 0xDF)

  • 指定デジタルportの、状態変化時通知の有効・無効を設定します。
  • デジタル8点を1portとして、状態変化があったportの状態を通知するように設定します。
  • 例として4番pinが変化した場合、port0の通知を受け取ります。9番pinの場合はport1となります。
内容 説明
種別コード + port番号 0xD0〜0xDF port番号が0から数えて1の場合は0xD1となる
有効/無効 0〜127 0:無効 0以外:有効
説明

有効/無効のフラグは0か、0以外の値かで判断します。例として1番portのデジタル変化通知を有効に設定するには

0xD1 0x01

となります。

この設定を有効にした場合、以後はデジタル状態が変化した際に デジタルメッセージ(0x90 - 0x9F) を受け取る事になります。


Firmataバージョン通知リクエスト(0xF9)

  • マイコンに対して、Firmataプロトコルのバージョンを通知するように要求します。
  • 送信データは種別コードのみです。
内容 説明
種別コード 0xF9 0xF9固定
説明

送信するデータは種別のみですので

0xF9

となります。

このリクエスト送信後にマイコンより バージョン通知(0xF9) を受け取ります。

SysEx メッセージフォーマット

SysExメッセージフォーマットは可変長のデータを扱えるデータフォーマットです。SysExフォーマットでのデータでは

  • 1byteめは 0xF0 固定
  • 2バイトめはSysExコマンドの種別コード( 0x00 - 0x7F )
  • 3バイトめ以降は任意の長さのデータ
  • 最後に 0xF7 で終了

となります。

3バイトめ以降のデータ長は固定されていません。プログラム上では0xF7が出現した時点で一塊のデータを受信し終えたと判断します。

コマンド種類 コード 説明
RESERVED_COMMAND 0x00 2nd SysEx data byte is a chip-specific command (AVR, PIC, TI, etc).
ANALOG_MAPPING_QUERY 0x69 ask for mapping of analog to pin numbers
ANALOG_MAPPING_RESPONSE 0x6A reply with mapping info
CAPABILITY_QUERY 0x6B ask for supported modes and resolution of all pins
CAPABILITY_RESPONSE 0x6C reply with supported modes and resolution
PIN_STATE_QUERY 0x6D ask for a pin's current mode and value
PIN_STATE_RESPONSE 0x6E reply with a pin's current mode and value
EXTENDED_ANALOG 0x6F analog write (PWM, Servo, etc) to any pin
SERVO_CONFIG 0x70 set max angle, minPulse, maxPulse, freq
STRING_DATA 0x71 a string message with 14-bits per char
SHIFT_DATA 0x75 shiftOut config/data message (34 bits)
I2C_REQUEST 0x76 I2C request messages from a host to an I/O board
I2C_REPLY 0x77 I2C reply messages from an I/O board to a host
I2C_CONFIG 0x78 Configure special I2C settings such as power pins and delay times
REPORT_FIRMWARE 0x79 report name and version of the firmware
SAMPLING_INTERVAL 0x7A sampling interval
SYSEX_NON_REALTIME 0x7E MIDI Reserved for non-realtime messages
SYSEX_REALTIME 0x7F MIDI Reserved for realtime messages

ファームウエア名・バージョン番号要求(0xF0, 0x79)

  • Firmataプロトコルのバージョン番号とファームウエア名称を送信するようにマイコンに要求します。
内容 説明
種別コード 0xF0 0xF0固定
SysEx種別コード 0x79 0x79固定
SysEx終了コード 0xF7 0xF7固定
説明

送信データは以下のようになります。

0xF0 0x79 0xF7


ファームウエア名・バージョン番号受信(0xF0, 0x79)

  • Firmataプロトコルのバージョン番号、ファームウエア名称を受信します。
内容 説明
種別コード 0xF0 0xF0固定
SysEx種別コード 0x79 0x79固定
メジャーバージョン番号 0〜127
マイナーバージョン番号 0〜127
ファームウエア名(0-6bit) 0〜127
ファームウエア名(7-14bit) 0〜127
ファームウエア名(15-22bit) 0〜127
..... 0〜127
SysEx終了コード 0xF7 0xF7固定
説明

受信データは以下のようになります。

0xF0 0x79 ...(名称バイナリ)... 0xF7

ファームウエア名は、名称を表す文字列バッファを7bitずつに分け、おのおのの先頭に1bitの0を追加したものになります。

受信した場合はこの逆の操作をし、各バイトから下位7bitを取り出して連結するとファームウエア名称となります。


アナログ値サンプリング周期の設定(0xF0, 0x7A)

  • マイコンに対して、アナログ値のサンプリング周期を指定します。
  • この設定はデジタル状態の通知には影響しません。
内容 説明
種別コード 0xF0 0xF0固定
SysEx種別コード 0x7A 0x7A固定
サンプリング周期(ms)下位 0〜127 サンプリング周期の下位7bitを格納します
サンプリング周期(ms)上位 0〜127 サンプリング周期の上位7bitを格納します
SysEx終了コード 0xF7 0xF7固定
説明

例として、サンプリング周期を300ミリセカンドに設定したい場合、300 は2進数で 00000001 00101100 であり、8bitめは使用できない為、下位の8bit目を上位1bitめに入れ、上位は左に1bitシフトし 00000010 00101100 を得ます。

送信するデータは 下位 -> 上位 の順であり、これに種別コード、SysExコード、SysEx終了コードを加えると

0xF0 0x7A 0x2C(0b00101100) 0x02(0b00000010) 0xF7

となります。このデータを送信後は、マイコンからの アナログ値通知設定(0xC0 - 0xCF) 受信が300ミリセカンド毎となります。なお、Arduinoの Standard Firmata でのデフォルトのサンプリング周期は19ミリセカンドです。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment