owned this note
owned this note
Published
Linked with GitHub
# PlatformIOでオープンソースのうまみを感じよう
この記事は [SFC-RG Advent Calendar 2016](http://www.adventar.org/calendars/1413) の3日目の記事です。
---
Webも結構好きです。shunkinです。最近のWeb, mobile app開発環境では、ライブラリマネージャ, IDEの機能を活用したり、継続的インテーグレーションを利用したデプロイの自動化, ユニットテストを行ないバグを減らしながら開発するのが当たり前になっていると思います。
今回は、これらの開発に便利な機能を組み込み開発に持ち込むことができる[PlatformIO](http://platformio.org/)を紹介します。基本的には、[公式クイックスタート](http://docs.platformio.org/en/stable/quickstart.html)をなぞります。
## 背景とPlatformIOについて
![PlatformIO](http://cdn.platformio.org/images/platformio-logo.17fdc3bc.png)
### 背景
冒頭で述べたような機能は、どのような領域に対するプログラミングでも有用です。しかし、これらの手法は、プログラムが実行される環境に極端なばらつきがない、もしくは、その差を吸収する言語などの条件が合わさってはじめて行えます。どの環境でどのライブラリが実行できるのかや、呼べる関数を開発環境側が正確に知らなくてはライブラリマネージャやコードコンプリート機能を提供する事が出来ないからです。
その為、フレームワークも少なく、構成の異なるボードが無数に存在する組み込み開発では、従来これらの機能を導入することが困難でした。
組み込み開発では、それぞれのボードごとに固有のライブラリ, 書き込みツール, クロスコンパイル環境(Toolchain)を用意して開発環境を用意する必要があります。当然それらのツール自体にも依存関係とバージョンが存在し、それらを最新に保ちながら開発することも難しいことですし、もしも複数のボードに対して開発を行なうのであれば、それぞれのボードごとに環境を更新し続けなくてはなりません。加えて、書いたC/C++のコードはボードに依存し再利用性が低くなってしまいます。
これらの問題を解決するオープンソースプラットフォームが、[PlatformIO](http://platformio.org/)です。
### 凄さ
1. 同一のコードを複数の環境で実行できる。2016-12-3時点で、20のプラットフォーム, 9つの有名フレームワーク, 344個のボードに対応している。
1. IDEからコードコンプリート機能を利用できる。
3. コーディングからテスト、ビルド、アップロード、シリアル経由の動作確認までを1つのツールで全て行える。
4. OSSなので、これからも対応ボード, ライブラリの増加が期待できる。
## 本記事の目標
さて、本記事では、PlatformIOの便利さを知ってもらうため、PlatformIOを利用して以下のことをするコードを書いてみようと思います。
1. LEDをチカチカさせる
2. 加速度センサーであるADXL345を利用して加速度を取得
## 実行環境
本記事の内容は、以下の環境で確かめています。
ESP-12eに対してネイティブのtoolchainを導入してプログラムを書き込むのは、[昨年の自分の記事](https://gist.github.com/shunkino/2056083843d6a5a1fb63)をご参照下さい。
> マシン : MacBook Pro (Retina, 13-inch, Late 2013)
> OS : macOS Sierra 10.12.1(16B2555)
> 対象ボード : [ESP-12e](http://www.aitendo.com/product/12168)
> 加速度センサ : [ADXL345](http://akizukidenshi.com/catalog/g/gM-06724/)
## PlatformIO
PlatformIOの特徴を紹介しながら目標を達成していきます。
### 導入
入手方法はいくつか有ります。基本的には、AtomエディタにPlatformIOプラグインを付けるか、CLIツールをインストールします。Atom用PlatformIOプラグインには、CLIツールも含まれるため両方を必ずインストールしなくてはならないというわけではありません。
1. PlatformIO IDEをインストールする
プラグイン導入済みのパッケージが有ります。[こちら](http://platformio.org/platformio-ide)からダウンロードできます。
2. PlatfomIOのプラグインをAtomに導入する
Atomのパッケージマネージャからプラグインを導入します。方法は[こちら](http://docs.platformio.org/en/stable/ide/atom.html#installation)に書いてあります。
3. PlatformIO CLIのみをインストールする
CLIツールのみをインストールします。手順は[こちら](http://docs.platformio.org/en/stable/installation.html)。
### プロジェクトの初期化
まず、プロジェクトを初期化し、プロジェクト管理に必要なファイルを生成します。その際、どのボードに向けてプロジェクトを作成するのかを決めます。複数でも構いませんし、後から追加することも出来ます。PlatformIO側で用意されたコマンドを利用して一覧を得ることが出来ます。
```
platformio boards
```
![こんな感じ](http://web.sfc.wide.ad.jp/~shunkin/images/boards.png)
対象ボードが見つかったら、プロジェクトディレクトリを作成し、そのなかでinitします。
```
platformio init --board esp12e --board teensy20pp
```
こんな感じで初期化をすると、以下のファイルが作成されます。
* .gitignore -> PlatformIO用のメタファイルをcommitしないように
* .travis.yml -> travis CI用
* lib/ -> private libraryを自分で入れるディレクトリ
* platformio.ini -> 先程決めたボード情報などの情報を格納
* src/ -> ソースコードを書くディレクトリ
### ソースコードの記述
適当なエディタ or PlatformIO IDEでsrc/main.cppを編集します。内容は公式ガイドに沿ったLチカで。
```c
/**
* Blink
*
* Turns on an LED on for one second,
* then off for one second, repeatedly.
*/
#include "Arduino.h"
#include <Wire.h>
#define ledPin 13
void setup()
{
// initialize LED digital pin as an output.
pinMode(ledPin, OUTPUT);
}
void loop()
{
// turn the LED on (HIGH is the voltage level)
digitalWrite(ledPin, HIGH);
// wait for a second
delay(1000);
// turn the LED off by making the voltage LOW
digitalWrite(ledPin, LOW);
// wait for a second
delay(1000);
}
```
### ライブラリマネージャ
さて、上記のものをそのままBuild & Runさせても良いのですが、せっかくなので、優秀なライブラリマネージャも紹介したいと思います。
ライブラリマネージャも、検索ツールが付属しており、コマンドから簡単に使用したいライブラリを探してきてインストールする事が出来ます。
```
platformio lib search adxl345
```
![library tool](http://web.sfc.wide.ad.jp/~shunkin/images/library.png)
こんな感じで検索できるはずだと思います。この中から、compatibilityを見ながら使いたいライブラリを探します。自分の使用したいプラットフォームに対応したいい感じのライブラリが見つかったら、次のコマンドを利用してインストールします。
```
platformio lib install 559
```
こうすることで、.piolibdeps以下にライブラリがインストールされ、使用可能になります。(同時に、IDEからコードコンプリート機能を利用できるようになります。)
### ライブラリの使用
ライブラリを無事導入できたら、先程編集したsrc/main.cppを編集して加速度を測定するコードを書きましょう。サンプルコードを参考に、3つの軸にかかる加速度をそれぞれ読み取ります。
```c
/**
* Blink
*
* Turns on an LED on for one second,
* then off for one second, repeatedly.
*/
#include "Arduino.h"
#include <Wire.h>
#include <ADXL345.h>
#define ledPin 13
ADXL345 accel(ADXL345_STD);
void setup()
{
// initialize LED digital pin as an output.
pinMode(ledPin, OUTPUT);
Serial.begin(115200);
accel.begin();
byte deviceID = accel.readDeviceID();
if (deviceID != 0) {
delay(500);
Serial.println("read device succeed");
Serial.print("0x");
Serial.print(deviceID, HEX);
Serial.println("");
} else {
Serial.println("read device id: failed");
while(1) {
delay(100);
}
}
// Data Rate
// - ADXL345_RATE_3200HZ: 3200 Hz
// - ADXL345_RATE_1600HZ: 1600 Hz
// - ADXL345_RATE_800HZ: 800 Hz
// - ADXL345_RATE_400HZ: 400 Hz
// - ADXL345_RATE_200HZ: 200 Hz
// - ADXL345_RATE_100HZ: 100 Hz
// - ADXL345_RATE_50HZ: 50 Hz
// - ADXL345_RATE_25HZ: 25 Hz
// - ...
if (!accel.writeRate(ADXL345_RATE_50HZ)) {
Serial.println("write rate: failed");
while(1) {
delay(100);
}
}
// Data Range
// - ADXL345_RANGE_2G: +-2 g
// - ADXL345_RANGE_4G: +-4 g
// - ADXL345_RANGE_8G: +-8 g
// - ADXL345_RANGE_16G: +-16 g
if (!accel.writeRange(ADXL345_RANGE_2G)) {
Serial.println("write range: failed");
while(1) {
delay(100);
}
}
if (!accel.start()) {
Serial.println("start: failed");
while(1) {
delay(100);
}
}
}
void loop()
{
if (accel.update()) {
Serial.print(accel.getX());
Serial.print(",");
Serial.print(accel.getY());
Serial.print(",");
Serial.print(accel.getZ());
Serial.println("");
} else {
Serial.println("update failed");
while(1) {
delay(100);
}
}
// turn the LED on (HIGH is the voltage level)
digitalWrite(ledPin, HIGH);
// wait for a second
delay(1000);
// turn the LED off by making the voltage LOW
digitalWrite(ledPin, LOW);
// wait for a second
delay(1000);
}
```
こういうふうに書いてやることで、ADXL345とI2C通信を行ない、加速度を取得することができると思います。
### ビルド & アップロード機能
さて、コードが出来てライブラリの依存環境も解消できたら、実行をしてみましょう。
すみませんが、ここではIDEを利用していることを想定します。CLIのみの方は[ここ](http://docs.platformio.org/en/stable/quickstart.html)を読んで下さい。
まず、IDE内のサブメニューを開きます。
![サブメニュー](http://web.sfc.wide.ad.jp/~shunkin/images/menu.png)
この中から、BuildもしくはUploadを選びます。Uploadを選んだときは、もしBuildが最新でなければ自動的にBuildもしてくれます。
もし複数のプラットフォームがターゲットのプロジェクトであればそれら全てに対してBuildないしUploadをします。
現在ビルドしたいターゲットが1つだけであるならば、```Run other target...```を指定することでビルド先を指定してビルドやアップロードが出来ます。
このタイミングで、(もしまだ無ければ)各プラットフォーム向けのクロスコンパイル環境, 書き込みツールがインストールされます。
## 結論
このコードを実行することで、以下のようにSerialから加速度が吐き出され、LEDはチカチカするはずです。
![accel](http://web.sfc.wide.ad.jp/~shunkin/images/accel.png)
今回PlatformIOを利用してLEDチカチカに加えてADXL345を動作させました。書いたコードは、Arduino Frameworkに対応したボードであれば、下位層によらずに実行可能です。用意がめんどくさいクロスコンパイル環境や転送ツールが自動的にインストールされて便利ですね。幸せだ。
## P.S.
ライブラリのディレクトリを見ると、keywords.txtを始めとしてlibraryをPlatformIOから上手く扱うためのメタファイルが有ります。これらをライブラリ作者やコミッターが追加していくことで、PlatformIOのエコシステムが成長し、より便利になります。OSSって最高だねって気分になって下さい。ここまでありがとうございました。
製作者に感謝...!!
## 関連
* [ESP8266に対してネイティブのtoolchainを導入しプログラムを書き込む](https://gist.github.com/shunkino/2056083843d6a5a1fb63)
読んでおくと、今回の内容がどれだけ嬉しいかが分かるかもしれない。