arduino-cliによるArduinoアプリケーションの開発

144Labの入江田です。 Arduinoの開発にはArduinoIDEを使う方法が主流ですが、 今回はまだマイナーな「arduino-cli」を使った開発方法を紹介します。

2020/09/14にarduino-cliのv0.13.0がリリースされました。

初期にあった不具合もほとんど解消され安定してきたのでそろそろ実用フェーズに組み込んでもいいんじゃないかという状況になってきました。

ArduinoIDEのツラミ

GUI操作でボードサポートや依存ライブラリのインストールや更新ができCUIを一切使わずに済むことに関してはよく考えられた環境ではありますが、

  • 内包されたエディタがnotepadにほんの少し機能追加したレベル
  • 複数ファイルの取り扱いがわかりにくい
  • 世の中にはC/C++に関する便利なツールがあるがそのほとんどは使えない
  • 今時のIDEのように複数のプロジェクトを横断する機能はない
  • 他人の起こした環境と同じ環境を構築するのが手間がかかる(見比べて合わせる必要がある)
  • 成果物を保存する機能や保存した成果物を書き込むだけなどが簡単にはできず、開発ではない関係者であっても同じように開発環境を整えてもらう必要がある

手慣れた開発者は新規プロジェクトをArduinoIDEで起こして、慣れたエディタを使ってコードを編集し、IDEにもどってコンパイルやターゲットへの書き込みを行うという操作を行っています。

これはつまり「開発環境の構築」、「コンパイル」、「フラッシュ」さえできればIDEである必要はないということなのです。

そこで「arduino-cli

Arduino陣営が開発した「arduino-cli」というツールがあります。これはArduinoコア機能を提供するコマンドラインツールです。

ArduinoIDEとarduino-cliは互いにボードサポートやライブラリの保存場所を共有していますので、ArduinoIDEで環境構築しておいてその他の機能はarduino-cliを利用することもできますし、逆もまた可能です。

arduino-cliはArduinoIDEにあるエディタとシリアルモニタ以外の機能は全てあります。

arduino-cliインストール

macOSユーザー

> brew install arduino-cli

Linuxユーザー

> mkdir ~/bin
> curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR=~/bin sh

PATH=$HOME/bin:$PATHをお使いのシェルのprofileファイルに追記してください。(例:~/.bash_profileなど)

Windows10ユーザー

  1. ダウンロード https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_Windows_64bit.zip
  2. 展開してarduino-cli.exeをパスの通ったフォルダに移動

arduino-cliインストールの確認

> arduino-cli version
arduino-cli Version: 0.13.0 Commit: 693a045eea420c29ca7027e668eee31bce37365d

ターゲットサポートの追加

設定ファイルの初期化(すでにある場合は以下を実行しても何もしません)

> arduino-cli config init
Config file written to: /Users/USERNAME/Library/Arduino15/arduino-cli.yaml

上記のarduino-cli.yamlに以下のURLを追記(開発に使うボードのガイドに書かれたURLなど)

board_manager:
  additional_urls:
  - https://www.adafruit.com/package_adafruit_index.json

インデックスの更新とターゲットサポートの検索

> arduino-cli core update-index
Downloading missing tool builtin:ctags@5.8-arduino11...
builtin:ctags@5.8-arduino11 downloaded
Installing builtin:ctags@5.8-arduino11...
builtin:ctags@5.8-arduino11 installed
Downloading missing tool builtin:serial-discovery@1.0.0...
builtin:serial-discovery@1.0.0 downloaded
Installing builtin:serial-discovery@1.0.0...
builtin:serial-discovery@1.0.0 installed
Updating index: library_index.json downloaded
Updating index: package_index.json downloaded
Updating index: package_index.json.sig downloaded
Updating index: package_adafruit_index.json downloaded
Updating index: package_index.json downloaded
Updating index: package_index.json.sig downloaded
Updating index: package_adafruit_index.json downloaded
> arduino-cli core search nrf52
ID             Version Name                            
adafruit:nrf52 0.21.0  Adafruit nRF52                  
arduino:mbed   1.1.6   Arduino nRF528x Boards (Mbed OS)
arduino:nrf52  1.0.2   Arduino nRF52 Boards  

ターゲットサポートのインストール

> arduino-cli core install adafruit:nrf52

このインストール状況はArduinoIDEにも反映されるし、 ArduinoIDEの方が探したり入れたりしやすいと思う場合は ArduinoIDEでインストールしてもらっても構いません。

ライブラリのインストール

サーチ

> arduino-cli lib search --names ArduinoJson
Name: "ArduinoJson"
Name: "CTBot"
Name: "Constellation"
Name: "DarkSkySevenDay"
Name: "Effortless-SPIFFS"
Name: "IFTTTMaker"
Name: "Kaa IoT Platform"
Name: "OpenWeatherOneCall"
Name: "cloud4rpi-esp-arduino"
Name: "jsonlib"
Name: "weatherLocation"

インストール

> arduino-cli lib install ArduinoJson
ArduinoJson depends on ArduinoJson@6.16.1
Downloading ArduinoJson@6.16.1...
ArduinoJson@6.16.1 downloaded
Installing ArduinoJson@6.16.1...
Installed ArduinoJson@6.16.1

このインストール状況はArduinoIDEにも反映されるし、 ArduinoIDEの方が探したり入れたりしやすいと思う場合は ArduinoIDEでインストールしてもらっても構いません。

アプリケーション開発

以下のようなフォルダツリーを起こしましょう。

  • プロジェクトルート
    • APP_NAME/
      • APP_NAME.ino

APP_NAMEはドットを含まない任意のアプリケーション名です。 守るべき注意事項として親フォルダ名とメインのAPP_NAME.inoの名前は一致している必要があります。

APP_NAME.ino

void setup() {
    ...
}

void loop() {
    ...
}

ターゲットボード名、ポート名の調べ方

ターゲットをUSB接続した状態で以下のコマンドを実行すると 適合するボード名のリストが表示されます。

> arduino-cli board list
Port                Type            Board Name          FQBN                    Core
/dev/tty.usbmodem1422401    Serial Port (USB)   Nordic nRF52840DK (PCA10056)    adafruit:nrf52:pca10056 adafruit:nrf52

または対応可能ボードの全てを表示または検索することもできます。

> $ arduino-cli board listall nrf52
Board Name                                  FQBN                         
Adafruit Bluefruit Metro nRF52840 Express   adafruit:nrf52:metro52840    
Adafruit Feather nRF52832                   adafruit:nrf52:feather52832  
Adafruit Feather nRF52840 Express           adafruit:nrf52:feather52840  
Adafruit ItsyBitsy nRF52840 Express         adafruit:nrf52:itsybitsy52840
Nordic nRF52840DK (PCA10056)                adafruit:nrf52:pca10056      

ピン番号について

ピン番号はターゲットボードサポートライブラリ側とターゲットボードの組み合わせで決まります。異なる組み合わせで利用する場合やCPU互換な別のボードを利用する場合は自前でピン番号割当をする必要があります。

あと、CPUモジュールのスペックシートみると、ピンに名称をつけている場合があったりするので番号との対応は確認する必要があったりします。

一例としてはnRF51/nRF52シリーズでは「P0##」「P1##」というような名称が付与されています。名称と番号の関係は以下の通り。 Pm_nn に対し 32*m+nnという計算で番号が決められています。

  • P0_00: 0
  • P0_01: 1
  • P0_31: 31
  • P1_00: 32
  • P1_01: 33

nRFシリーズは概ねこの形になっていますが、ボードによってはボードのシルクに従う必要があったりしますので、ボードごとのサンプルを参考にしてください。

アプリケーション例

いわゆるLチカです。APP_NAMEを仮に「sample1」とします。 この場合、親フォルダも「sample1」という名前である必要があります。

sample1/sample1.ino

#define LED1 6 // ターゲットによってピン番号は異なります。

void setup() {
    pinMode(LED1, OUTPUT);
}
void loop() {
    Serial.println("loop");
    digitalWrite(LED1, 0);
    delay(500);
    digitalWrite(LED1, 1);
    delay(500);
}

ビルド

sample1.inoのあるフォルダにて以下のコマンドでビルドできます。

> arduino-cli compile -b adafruit:nrf52:pca10056 .

Sketch uses 38404 bytes (4%) of program storage space. Maximum is 815104 bytes.
Global variables use 6756 bytes (2%) of dynamic memory, leaving 230812 bytes for local variables. Maximum is 237568 bytes.

この場合、「build/」フォルダが作られ、成果物一式はその配下に出力されます。

  • sample1/build/adafruit.nrf52.pca10056/
    • sample1.ino.elf
    • sample1.ino.map
    • sample1.ino.hex
    • sample1.ino.zip

elfがバイナリ、mapはマップファイルというデバッグ情報ファイルです。 hexやzipがファーム書きこみ用のファイルです。

書き込み

開発の際はターゲットボードをPCと接続しておき、 以下のコマンドで書き込みを実行します。

> arduino-cli upload -b adafruit:nrf52:pca10056 -p /dev/tty.usbmodem142101 .
Upgrading target on /dev/cu.usbmodem142101 with DFU package /Users/nobo/Dropbox/Work/Articles/arduino-cli/sample1/build/adafruit.nrf52.pca10056/sample1.ino.zip. Flow control is disabled, Single bank, Touch disabled
########################################
####################################
Activating new firmware
Device programmed.

もし成果物だけを配布してファームウェアを書き換えたい場合は以下のコマンドのように「-i 成果物.ino.zip」で書き換えができます。

> arduino-cli upload -b adafruit:nrf52:pca10056 -p /dev/tty.usbmodem142101 -i build/adafruit.nrf52.pca10056/sample1.ino.zip 

デバッグ

Arduino開発のデバッグは主にシリアルモニターによるプリントデバッグを行います。

APP_NAME.inoのsetup関数の冒頭にSerial.begin(115200);を入れておきましょう。

void setup() {
    Serial.begin(115200);
}

以下のようにしてデバッグプリントをする場合、シリアルモニターには「param: <paramの値>」というようなログが出力されます。

Serial.print("param: ");
Serial.println(param);

シリアルモニタを入手しましょう。以下のどちらかがお勧めです。 (もちろん使い慣れたシリアルターミナルソフトを使っても構いません)

  • miniterm.py(All platform)
  • Go言語を使った自作コマンド

python3およびpipコマンドが環境に利用可能であれば、「pip3 install pyserial」にて「miniterm.py」というコマンドが利用可能になります。

使い方: ポート名とボーレート指定を引数に指定します。

miniterm.py /dev/tty.usbmodem142101 115200

モニターの止め方は「Ctrl+[」を押します。

Go言語を利用可能な環境であれば「go get github.com/144lab/miniterm」にて「miniterm」というコマンドが利用可能になります。 使い方:ポート名を指定します(ボーレートは115200固定です)

miniterm /dev/tty.usbmodem142101

モニターの止め方は「Ctrl+C」を押します。

まとめ

単一のinoファイルだけでアプリケーションを構築する形を紹介しました。 この形が基本なので、なにか試したいことなどはこの形で試すと間違いにくいのでお勧めです。

GUIスタイルのIDEは模索する動作には向きますが、反復や再現する必要が出た時に効率が落ちます。こう言ったCUIなツールは最初のとっつきは悪いですが、慣れれば慣れるほどに効率が上がっていきますので是非挑戦してみてください。また、エディタはお気に入りのものを使えば良いので開発効率自体も上がるはずです。

arduino-cliはesp8266やesp32の開発も問題なくできるようになりました。 M5Stackシリーズの開発にもどうぞ!