Arduinoでスケッチを作成する際にはライブラリを使う事が多い。
数多くのライブラリが公開・提供されており、Arduino IDEのライブラリマネージャから簡単にインストールしたり、GitHub等から zip形式でダウンロード、インストールしたりする事も出来る。
複雑な処理やセンサー等のデバイス制御をライブラリを使う事で簡単にスケッチから利用する事が出来るが、 面倒なトラブルも引き起こしやすい。
発生し易いトラブルとして
- あるPCではビルドが通るのに他のPCではビルドが通らない。
- ビルドは通るのに思い通り動かない。
- ライブラリを更新したら動かなくなった、ビルドが通らなくなった。
等々。
今まで問題なかったスケッチが、ある日ビルドして動かしてみたら動かなくなる事があるのが非常に厄介である。 Arduinoに限った事ではないが、ライブラリの仕様が変わったり使えていた関数が使えなくなったりと言った事が多々ある。
動作には問題が無いが、ライブラリのバージョンが上がり機能が増えてこれまで32KBのスケッチ容量に収まっていたのに 収まらなくなった、なんて事もある(u8glibとか)。
このため、スケッチが正常に動作する様になったら、覚え書きとしてスケッチのヘッダの部分に使用しているライブラリと、バージョンを 明記しておくとよい。ライブラリも同じ名称で異なる作者のものがあったりするので、作者名やgithubのURLもメモしておくと安全である。
Arduinoのライブラリは基本的にドキュメントフォルダーのArduinoの下のlibrariesフォルダーに管理されている。 Zipファイルからインストールしてもここにインストールされる。
上にも書いたが、ライブラリに起因するトラブルとしては以下の様なものがある。ある環境や、過去にはビルドが通っていたのに 、ビルドが通らなくなった、正常に動作しなくなった場合は以下の事が考えられる。
- 間違ったライブラリがインストールされている(似た名前の違うライブラリなど)。
- 同じヘッダーファイル名を持つ複数のライブラリがインストールされている(想定と違うライブラリが使われている)。
- ライブラリのバージョンで挙動が変わっている(仕様の変更)。
例として、RTC系のライブラリが複数インストールされている環境で、いずれも同じ rtc.h というファイル名とクラス・関数を持っていると言った事がある。全く種類が異なるライブラリでも同じヘッダーファイル名を使っている事があるので注意が必要だ。
ヘッダーファイル名が同じ、関数名が同じ、でも処理内容と返す結果が異なるとビルドが通り動作もするのに何かがおかしい、と言う事になる。
混乱防止のために、スケッチが正常に動作している状態でバックアップ目的や他人に渡しても正常動作する様関連ライブラリも纏めて 固定しておきたい、という場合にはスケッチのフォルダーにライブラリを入れておく方法がある。
スケッチによりライブラリ側に手を入れたいが、オリジナルのライブラリには手を加えたくない場合にも使える方法である。
ライブラリはライブラリフォルダーの中にソースコード、サンプルスケッチ、関連ドキュメントの構成で含まれている事が多い。
これをスケッチに入れるには、
- ソースファイルをスケッチと同じフォルダーに入れる。
- スケッチのフォルダにsrcフォルダーを作成し、ライブラリフォルダーごとコピー。
と言った方法がある。ソースファイルはヘッダファイルとcppファイル構成が多いので、これらのファイルをinoファイルと同じフォルダーにコピーしてしまう。
ライブラリのインクルードは通常
#include <RTClib.h>
の様に記述する。<>で囲むとビルド時 ドキュメント/Arduino/libraries やボードパッケージのライブラリフォルダー内を探しに行くため、スケッチと同じフォルダーにファイルを置いても見つからずエラーとなる。
スケッチと同じフォルダーにあるファイルを参照するには、
#include "RTClib.h"
RTC_Millis rtc;
void setup() {
rtc.begin(DateTime(F(__DATE__), F(__TIME__)));
}
void loop() {
}
の様にincludeをダブルクオテーションで記述する。
フォルダーごとライブラリをスケッチのフォルダーにコピーしたい場合には、src サブフォルダーを作成し、その下に ライブラリのフォルダーをコピーする。src フォルダー以外に置いた場合ビルド時エラーとなる(srcフォルダーのみ特殊扱いとなっている)。
そしてincludeを下記の様に記述する。
#include "src/RTClib/RTClib.h"
RTC_Millis rtc;
void setup() {
rtc.begin(DateTime(F(__DATE__), F(__TIME__)));
}
void loop() {
}
エラー発生時やライブラリ競合時、出力メッセージにも色々ヒントが表示されているので良く読んで見ると良い。