エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

PlatformIO で Arduino のプロジェクトを管理する

Arduino!

最近、Arduino にはまっています。

エントリモデルである Arduino UNO R3 や、それと同等の構成で小型化した Arduino NANOAtmelATmega328P というICを使っていますが、このワンチップは私がプログラミングに本格的に没入した頃に使っていた PC と遜色ない性能を持っています。Arduino に触っているとその深みにハマったときの感覚が蘇ってきます。

そして Arduino の深みにはまっていくと、Arduino IDE でちまちまとスケッチを描いていくのがおっくうになりコマンドラインで管理できる方法がないかと探すことになります。

見つけたのが PlatfomIO 。

Arduino に限らず複数のチップやプラットフォームに対応しているようですが、ここでは Arduino での使い方だけまとめておきます。

PlatformIO!

Arduino にならって「ぷらっとふぉみーお」と呼びたくなるのですが、つづりでは“IO”が大文字になっているので「ぷらっとふぉーむあいおー」と読むのだと思います。どう読むかは見つけられませんでした。

インストールする

Mac のばあい、Homebrew でインストールできます。

$ brew install platformio

Homebrew を使わないばあいは pip を使ってインストールできるようです。

利用できるボードを確認する

boards コマンドで利用できるボードを確認できます。

$ platform boards

けっこうな数が表示されます。Arduino だけでも 40 種類以上出てきます。 情報をしぼりたいばあいはコマンドのうしろにフィルタをつけます。

$ platformio boards "arduino uno" # Arduino UNO の情報だけを表示したい

Platform: atmelavr
------------------------------------------------------------------------------------------------------------------------------------------------------
ID                    MCU            Frequency  Flash   RAM    Name
------------------------------------------------------------------------------------------------------------------------------------------------------
uno                   ATMEGA328P     16Mhz     31kB    2kB    Arduino Uno

これで Arduino UNO の ID は uno とわかります。この ID はボードの指定をするときなどに利用します。

プロジェクトを準備する

プロジェクトを作成するディレクトリに移動して init コマンドを実行します。

$ mkdir sample
$ cd sample
$ platformio init

src/lib/ という二つのディレクトリと platformio.inireadme.txt という二つのファイルが作成されます。

sample
├── lib/
│   └── readme.txt
├── platformio.ini
└── src/

オプションを付けずに init コマンドを実行すると platformio.ini には実際の設定は追加されません。ターゲットにするボードの ID を指定することでその設定が追加されます。

$ platformio init -b uno # Arduino UNO を指定

次のように Arduino UNO の設定のセクションを持つ platformio.ini ファイルが作成されます。

[env:uno]
platform = atmelavr
board = uno
framework = arduino

(コメントは省略しています)

すでに初期化をしたディレクトリで別のボードを指定して init コマンドを実行すると、そのボードの設定が platformio.ini ファイルに追加されます。一つのプロジェクトで複数のボードに対応することができます。

Arduino NANO の ID を調べます。

$ platformio boards "arduino nano"

Platform: atmelavr
------------------------------------------------------------------------------------------------------------------------------------------------------
ID                    MCU            Frequency  Flash   RAM    Name
------------------------------------------------------------------------------------------------------------------------------------------------------
nanoatmega168         ATMEGA168      16Mhz     14kB    1kB    Arduino Nano ATmega168
nanoatmega328         ATMEGA328P     16Mhz     30kB    2kB    Arduino Nano ATmega328

現在一般的に手に入る Arduino NANO は ATmega382P が載っているので nanoatmega328 を指定します。

上と同じディレクトリで init コマンドを実行します。

$ platformio init -b nanoatmega328

Arduino UNO の設定のセクションはそのままに Arduino NANO の設定のセクションが追加されます。

[env:uno]
platform = atmelavr
board = uno
framework = arduino

[env:nanoatmega328]
platform = atmelavr
board = nanoatmega328
framework = arduino

ビルドする/アップロードする

ビルドとアップロードをします。アップロードのターゲットを指定しないとビルドのみを行います。

src/ ディレクトリの下に Arduino IDE で書くときと同じようにスケッチのファイルを作成します。拡張子も .ino にします。

void setup() {
  // ...
}

void loop() {
  // ...
}

ビルドします。

$ platformio run

上で書いたように複数の環境が設定されているばあい、それぞれでビルドが実行されます。

Environment uno              [SUCCESS]
Environment nanoatmega328   [SUCCESS]

特定の環境だけビルドしたい場合は -e オプションで指定します。

$ platformio run -e uno
...
Environment uno             [SUCCESS]
Environment nanoatmega328   [SKIP]

アップロードまで行う場合は -t オプションで upload を指定します。

$ platformio run -e uno -t upload

Mac のばあい、Arduino を USB で接続すると /dev/ ディレクトリに USB デバイスとしてマウントされます。PlatformIO は自動的にそれを見つけて Arduino にスケッチをアップロードします。

アップロード先を指定したいばあいは --upload-port オプションで指定することができます。

デフォルトの環境を指定する

環境を指定しないで run コマンドを実行した時のデフォルトの環境を platfromio.ini で指定できます。

platformio.ini ファイルに platfromio セクションを追加し、env_default でデフォルトの環境を指定します。

[platformio]
env_default=uno

[env:uno]
platform = atmelavr
board = uno
framework = arduino

[env:nanoatmega328]
platform = atmelavr
board = nanoatmega328
framework = arduino

環境を指定せずに run コマンドを実行します。uno 環境のみビルドされます。

$ platformio run
...
Environment uno             [SUCCESS]
Environment nanoatmega328   [SKIP]

依存するライブラリを指定する

各環境のセクションに lib_deps を追加します。

たとえば TimerOne を利用したいばあい次のように記述します。 run コマンドを実行すると必要であれば自動的にライブラリをダウンロードしてライブラリのビルドが実行されます。

[env:uno]
platform = atmelavr
board = uno
framework = arduino
lib_deps = TimerOne

複数のライブラリを指定したいばあいはライブラリごとに改行して記述します。

[env:uno]
platform = atmelavr
board = uno
framework = arduino
lib_deps =
  TimerOne
  DHT11

登録されているライブラリは Libraries · PlatformIO で検索できます。

GitHub などで公開されていれば URL で指定することもできます。自作のライブラリを使いたいけれども PlatformIO には登録していないというばあいなどに利用できます。GitHub のばあい http 形式でも ssh 形式でも指定できます。

[env:uno]
platform = atmelavr
board = uno
framework = arduino
lib_deps =
  https://github.com/PaulStoffregen/TimerOne.git
  git@github.com:adidax/dht11.git

ビルドオプションを指定する

たとえば ESP8266 というライブラリはソフトウェアシリアルを利用できますが、利用するにはマクロで ESP8266_USE_SOFTWARE_SERIAL という値が定義されていなければなりません。

#ifdef ESP8266_USE_SOFTWARE_SERIAL
ESP8266::ESP8266(SoftwareSerial &uart, uint32_t baud): m_puart(&uart)
{
    m_puart->begin(baud);
    rx_empty();
}
#else
ESP8266::ESP8266(HardwareSerial &uart, uint32_t baud): m_puart(&uart)
{
    m_puart->begin(baud);
    rx_empty();
}
#endif

ITEADLIB_Arduino_WeeESP8266/ESP8266.cpp at master · itead/ITEADLIB_Arduino_WeeESP8266 · GitHub

このようなばあいのために build_flags を使ってコンパイラにオプションを渡すことができます。

[env:uno]
platform = atmelavr
board = uno
framework = arduino
lib_deps =
  ESP8266
build_flags = -D ESP8266_USE_SOFTWARE_SERIAL

これで ESP8266SoftwareSerial を渡すことができるようになります。

#include <SoftwareSerial.h>
#include <ESP8266.h>

SoftwareSerial mySerial(11, 12);
ESP8266 wifi(mySerial);

void setup() {
  // ...
}

void loop() {
  // ...
}

設定を共有する

platformio.ini にはすべての環境に影響を及ぼす設定を書くセクションというのはないようです。

共通する設定を記述したセクションを用意して、それを各セクションが参照することで実現しています。

環境 uno と環境 nanoatmega328 で同じライブラリを利用するばあい、次のように記述します。 ここでは common としましたが、セクション名は任意のようです。

[common]
lib_deps =
  TimerOne
  DHT11
  ESP8266
build_flags = -D ESP8266_USE_SOFTWARE_SERIAL

[env:uno]
platform = atmelavr
board = uno
framework = arduino
build_flags = ${common.build_flags}
lib_deps = ${common.lib_deps}

[env:nanoatmega328]
platform = atmelavr
board = nanoatmega328
framework = arduino
build_flags = ${common.build_flags}
lib_deps = ${common.lib_deps}

いつか読むはずっと読まない:あれから数え30年

1988年に発売され一世を風靡した、カードゲームの金字塔『モンスターメーカー』。 オリジナルの楽しさをそのままに、短時間で濃密に遊べるようリメイクされた新版が登場!! モンスターを倒しながら財宝を集め、誰よりも早く迷宮から帰還して名声を得よう!

プログラミングに没入したころに発表されたゲーム。心なしか最近リバイバルが増えている気がします。ゲームブックKindleで復刻されたり。ハイパーリンクは以前からゲームブック向きだなとは思っていましたが。

MONSTER MAKER モンスターメーカー

MONSTER MAKER モンスターメーカー