SPRESENSE で Firmata を動かす

# SPRESENSE で Firmata を動かす

## はじめに

[SPRESENSE](https://twitter.com/SonyDevJapan) のメインボードと拡張ボードを購入したので、
SPRESENSE に Firmata ライブラリを移植してみます。

SPRESENSE ボードは、Arduino 互換なのであっさり移植できるはず。
なんといっても拡張ボードは Arduino UNO と同じ形状です、動かないはずがない。

## Firmata とは？

ホストPCと通信するためのプロトコルを定義したライブラリです。
Firmata の詳しい説明は、正式な呼び名さえ知らないので...、他に譲りますが、ホストPC側のツールは、Processing をはじめとして、Python, Perl, Ruby, Java, Go, Rust, ... と一通り揃っています。（ファーマタなのか...ファルマータなのか...）

SPRESENSE 上で Firmata スケッチを一回焼いておくだけで、あとはホストPC側から SPRESENSE のポート制御を行うことができるようになります。SPRESENSE のピン仕様を調べるのと、これを使ってゆくゆくはスクラッチ「Scratch」等のビジュアルプログラミング言語からSpresenseを制御できるようにする予定（野望）です。

## SPRESENSEボード開発環境構築

開発環境のセットアップ手順は [Spresense Arduino スタートガイド](https://developer.sony.com/develop/spresense/docs/arduino_set_up_ja.html) に詳しく載ってます。(~~手抜き~~詳細は割愛)
Arduinoを使ったことがある人なら、

1. ボードマネージャのURLに[package_spresense_index.json](https://github.com/sonydevworld/spresense-arduino-compatible/releases/download/generic/package_spresense_index.json) を追加して
2. ボードマネージャからインストールするだけ、です

## Firmata 移植

移植した Firmata ライブラリを GitHub にアップしました。
https://github.com/baggio63446333/Firmata

移植といっても Board.h に SPRESENSE 用の定義を追加しただけです。
あまりにもアッサリしすぎたので勢いあまって本家にプルリク出してみました。
**(2019/10/21追記) 本家(https://github.com/firmata/arduino) にもマージされました。
いずれ Arduino IDE をインストールするだけで Firmata on SPRESENSE が使えるようになります。**

```cpp:Board.h
// SPRESENSE
#elif defined(ARDUINO_ARCH_SPRESENSE)
#define TOTAL_ANALOG_PINS       NUM_ANALOG_INPUTS
#define TOTAL_PINS              NUM_DIGITAL_PINS + 4 + NUM_ANALOG_INPUTS // + 4 built-in led
#define VERSION_BLINK_PIN       LED_BUILTIN
#define IS_PIN_DIGITAL(p)       ((p) >= 0 && (p) < (NUM_DIGITAL_PINS + 4))
#define IS_PIN_ANALOG(p)        ((p) >= (TOTAL_PINS - NUM_ANALOG_INPUTS) && (p) < TOTAL_PINS)
#define IS_PIN_PWM(p)           ((p) == 6 || (p) == 5 || (p) == 9 || (p) == 3)
#define IS_PIN_SERVO(p)         ((p) < NUM_DIGITAL_PINS)
#define IS_PIN_I2C(p)           ((p) == SDA || (p) == SCL)
#define IS_PIN_SPI(p)           ((p) == 10 || (p) == 11 || (p) == 12 || (p) == 13)
#define PIN_TO_DIGITAL(p)       (((p) < NUM_DIGITAL_PINS) ? (p) : (_LED_PIN((p) - NUM_DIGITAL_PINS)))
#define PIN_TO_ANALOG(p)        ((p) - (TOTAL_PINS - NUM_ANALOG_INPUTS))
#define PIN_TO_PWM(p)           (p)
#define PIN_TO_SERVO(p)         (p)
#define analogRead(p)           analogRead(_ANALOG_PIN(p)) // wrap function for analogRead()
````

これから SPRESENSE を使うにあたって何度も参照することになると思うので、
ここに SPRESENSE ボードのピン定義をまとめておきます（適宜、加筆予定）。

* ピン番号を調べるときのコネクタ図はこちら

  * [拡張ボード](https://developer.sony.com/develop/spresense/docs/images/overview_hardware_extboard_signal.jpg)
  * [メインボード](https://developer.sony.com/develop/spresense/docs/images/overview_hardware_mainboard_signal.jpg)

* 拡張ボード
  * デジタル：PIN_D00 ~ PIN_D15
  * デジタルI/O電圧： 3.3V or 5V (ジャンパ切り替え)
  * レベルシフタを通してデフォルトでプルアップされている
  * アナログ：A0 ~ A5
  * アナログ入力範囲：0 ~ 5V

* メインボード
  * デジタル：PIN_D14 ~ PIN_D28
  * デジタルI/O電圧：1.8V
  * アナログ：A2 ~ A3
  * アナログ入力範囲：0 ~ 0.7V

* ソースコード上のピン定義はこちら

  * [pin_arduino.h](https://github.com/sonydevworld/spresense-arduino-compatible/blob/master/Arduino15/packages/SPRESENSE/hardware/spresense/1.0.0/variants/spresense/pins_arduino.h)

* デジタルピン

  * コネクタに出ているのは 29 本ですが、NUM_DIGITAL_PINS はトータル 45 本も定義されています
  * 拡張ボードを自作する人向けですかね

* アナログ入力ピン
  * NUM_ANALOG_INPUTS はアナログ専用ピンで計 6 本あります
  * analogRead() 関数の引数は単純な数字ではなく A0, A1, A2, A3, A4, A5 という名前を使います
  * A0, A1, A2, A3 の 4 本は低速ADC、A4, A5 の 2 本は高速ADC、と二種類に分かれている

* LED
  * メインボードに LED が 4つもついてます
  * これは助かる～。さすが分かってらっしゃる＞SONYさん
  * せっかくなので Firmata 経由でも LED を触れるようにしておきました

## Firmata 動作

### Target (SPRESENSEボード) 側

1. Arduino IDE の Library Manager を使って [Firmata](https://github.com/firmata/arduino) をダウンロード

2. `StandardFirmata`サンプルスケッチを実行してボードに焼く
  Arduino 初心者でここの手順が分からないというコメントがあればもっとちゃんと書きます ^^;

### ホストPC 側

前述したようにホストPC側のツールはいろいろありますが、ここでは [Firmata Test ツール](https://github.com/firmata/firmata_test) を使います。

▼ここから各プラットフォーム用のツールがダウンロードできます。
~~https://github.com/firmata/firmata_test/downloads~~
http://firmata.org/wiki/Main_Page

1. Windows 版バイナリをダウンロードして firmata_test.exe を実行します
2. Port -> SPRESENSE が接続されている COM ポートを選択します
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432852/3bc4118b-3a89-0955-a4ad-d541453db9ff.png)

3. Pin 番号が次のように並んでいます。
00 ~ 44 : Digital
45 ~ 48 : LED
49 ~ 54 : Analog
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432852/bb5a1261-7d29-b982-d8c9-a310fbaa2125.png)
例えば、Pin45 ~ 48 に `Output` を選択したまま、`High` / `Low` を切り替えると L チカします。
どこかの Pin を `Input` に切り替えて、電源 / GND につなぐとステータスが `High` / `Low` に切り替わります。 
Anglog ピンは周期的に読み出しを行った値がリアルタイムに表示されます。

## さいごに

Firmata を使ってホストPCから SPRESENSE ボードを制御する環境が整いました。
SPRESENSE の Arduino 互換は本当でした。