Arduinoの自作ライブラリを作成するには?

投稿者: | ↻ : 2019年1月28日

目次

はじめに

知らなくてもスケッチでLチカとか出来るけど、自作ライブラリを作成しようとすると、色々な疑問が出てきます。これが、調べると意外と時間がかかるので、後で思い出せるようにまとめました。
内容は出来るだけ一次資料に近い情報から集め、参照元へのリンクを付けています。

元の資料に、ライブラリを作成する準備、サンプルライブラリの作成、ZIP形式の配布ファイルからのインストールについての内容を追記しました。

Arduinoのライブラリが保存される場所は?

通常、非標準ライブラリのファイルが保存される場所は、スケッチブックフォルダの”libraries”サブフォルダになります。

ライブラリが保存される場所

ライブラリは、OSに関係なく3つの場所で管理されます。

ArduinoのGithubリポジトリの、Arduino Build ProcessのCompilationを参照。

  • IDEインストールフォルダの”libraries”サブフォルダ
  • 現在選択されているボードのハードウェアパッケージの”libraries”サブフォルダ
  • スケッチブックフォルダの”libraries”サブフォルダ

macOSの場合を例に、実際の場所をまとめます。

IDEインストールフォルダの”libraries”サブフォルダの場所

このフォルダには、標準ライブラリのファイルが管理されます。
IDEのアップグレードで消えてしまわないように、非標準ライブラリは別の場所で管理します。

IDEインストールフォルダの場所は次の通りです。(インストーラを使用した場合)
/Applications/Arduino.app

ライブラリファイルが保存される場所は次の通りです。(直下ではないので分かりづらいです)
/Applications/Arduino.app/Contents/Java/libraries/

ハードウェアパッケージの”libraries”サブフォルダの場所

ライブラリの、ハードウェアごとに異なる部分を吸収するファイルを管理します。

IDEインストールフォルダの”./hardware/arduino/{architecture}/libraries”となります。
(ここは自分の環境を調べた結果なので、もっと正式なルールがあるかもしれません)

Arduino Uno 3 ならば、チップにATmega328pが使われているで以下の場所になります。
/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/libraries

スケッチブックフォルダ内の”libraries”サブフォルダの場所

ZIP形式のライブラリをインストールや、手動インストールを行う非標準ライブラリを管理します。

スケッチブックのデフォルトの場所は次の通りです。
/Users/{username}/Documents/Arduino/

なので、ライブラリファイルが保存される場所は次の通りです。
/Users/{username}/Documents/Arduino/libraries/

開発言語は基本的にはC/C++言語

FAQ:Can I program the Arduino board C?を参照。

Arduinoのライブラリは、avr-gccとavr-g++が対応している範囲のC言語とC++言語で記述します。

arv-gccとarv-g++が対応している範囲

Atmelサイト(Microchipに買収後に残っていたAtmelサイトからアドレスが変わりました)Microchipサイトの「AVR Libc Reference Manual Frequently Asked Questions」Can I use C++ on the AVR?を参照。

  • C++関連の標準関数、クラス、およびテンプレートクラスは利用できません。
  • new演算子とdelete演算子は実装されていません。外部参照でエラーとなります。
  • 付属のインクルードファイルの中にはC++セーフではないものは、
    extern "C" { ... }
    

    で括る必要があります。

  • 例外はサポートされません。

スケッチに対して行われる前処理

Arduino Build ProcessのPre-Processingを参照。

Arduino IDEは、avr-gccコンパイラに渡す前にスケッチに変換を行います。

  • スケッチフォルダ内のすべての.inoファイル(拡張子のないタブとしてIDEに表示されます)は連結され、.cpp拡張子がファイル名に追加されます。
  • #include スケッチに追加されます。このヘッダファイル(現在選択されているボードのコアフォルダにあります)には、標準Arduinoコアに必要なすべての定義が含まれています。
  • プロトタイプがまだない.inoファイル内のすべての関数定義に対して、プロトタイプが生成されます。プロトタイプの自動生成が敗する場合、プログラマが明示的にプロトタイプの定義を記述すれば回避できます。

前処理は、始めから拡張子が.ino以外のファイルには行われません。
ライブラリはスケッチに行われる前処理が無いので、C言語かC++言語で記述します。

自作ライブラリ作成の準備

ライブラリ作成途中にも動作確認を行えるように環境を準備します。

動作確認はArduino IDEで実際の利用時と同じようにスケッチを描いて行います。

自作ライブラリの開発を行うフォルダの作成

Arduino IDEが非標準ライブラリを認識する場所は3つあり、Arduino IDEの更新などに影響を受けない「スケッチブックフォルダ内の”library”サブフォルダ」以下に、自作ライブラリのフォルダを作成し開発を行います。”library”サブフォルダ以下でフォルダー名が衝突するとインストール出来ないので、他のライブラリと名前が衝突しないようにします。

プロパティファイルの作成

ライブラリが保存される場所にファイルを配置すればスケッチから利用できるようになりますが、配布を考えてライブラリの情報を記述したプロパティファイルが必要となります。

詳細はArduino IDE 1.5: Library specificationの「1.5 library format (rev. 2.1)」として公開されています。

概要は以下の通りです。

プロパティファイルは、ファイル名は”library.properties”とし、Key=Value形式のプロパティリストで、UTF-8でエンコーディングされたファイルです。

プロパティ一覧

#key説明
1nameライブラリの名前
ライブラリ名には、基本文字(A- Zまたはa- z)と数字(0- 9)、スペース()、アンダースコア(_)、ドット(.)、ダッシュ(-)のみを使用する必要があります。スペースで開始または終了することはできず、番号で始めることもできません。
2versionライブラリのバージョン。
バージョンはsemver準拠(後述)でなければなりません。
1.2.0が正しい。1.2が受け入れられる。r5、003、1.1cは無効です。
3author名と著者のニックネームと、メールアドレス(必須ではない)。
4maintainerメンテナーの名前と、メールアドレス。
5sentenceライブラリの目的を説明する文章。
6paragraphライブラリの目的より長い説明。
sentenceの後に付加されるので、ここではsenteneceに続く文章。
7category次の値のいずれかを設定する。
Display
Communication
Signal Input/Output
Sensors
Device Control
Timing
Data Storage
Data Processing
Other
8urlライブラリプロジェクトのURL、githubなど。
9architecturesライブラリによってサポートされるコンマ区切りのアーキテクチャのリスト。ライブラリにアーキテクチャー固有のコードが含まれていない場合、*を設定すると、すべてのアーキテクチャーとなります。
10dot_a_linkagetrueに設定した場合、コンパイル後のオブジェクトファイル(.o)を、静的ライブラリ(.a)にまとめてからリンカへ渡します。不要なら定義しない。
11includesヘッダファイルが複数あり、特定のヘッダファイルだけをインクルードさせたい場合にカンマ区切りで指定します。この定義が無ければ、srcフォルダの全てのヘッダがインクルード対象となります。
12precompiledコンパイル済みの静的ライブラリ(.a)と共通ライブラリ(.so)を使えるように設定します。
13ldflagsリンカへ渡すフラグを設定します。

10〜13は無くてもよい。

semver(Semantic Versioning:セマンティック バージョニング)

バージョンナンバーは、メジャー.マイナー.パッチとし、バージョンを上げるには、

  1. APIの変更に互換性のない場合はメジャーバージョンを上げる
  2. 後方互換性があり機能性を追加した場合はマイナーバージョンを上げる
  3. 後方互換性を伴うバグ修正をした場合はパッチバージョンを上げる

設定例

Adafruit ST7735 Libraryのlibrary.properties

name=Adafruit ST7735 Library
version=1.0.8
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=This is a library for the Adafruit ST7735 SPI displays.
paragraph=This is a library for the Adafruit ST7735 SPI displays.
category=Display
url=https://github.com/adafruit/Adafruit-ST7735-Library
architectures=*

キーワードハイライトの定義ファイル

Arduino IDEのエディタ上でハイライト表示させたいキーワードを定義するファイルです。

ファイル名は”keywords.txt”として作成し、タブ区切りでキーワードと識別子を並べます。

指定できる識別子は以下の通りです。標準ライブラリのkeywords.txtを見ると識別子に決まった規則はなさそうです。KEYWORD1、KEYWORD2、LITERAL1が下記の用途で使用されています。

  • KEYWORD1 – 型 (Datatypes, Class)
  • KEYWORD2 – メンバー関数と関数 (Methods and Functions)
  • KEYWORD3
  • LITERAL1 – 定数 (Constants)
  • LITERAL2
  • RESERVED_WORD
  • RESERVED_WORD2
  • DATA_TYPE
  • PREPROCESSOR

ハイライト時の色はLITERAL1が緑色で、その他は橙色です。

設定例(SDライブラリのkeywords.txt)

#######################################
# Syntax Coloring Map SD
#######################################

#######################################
# Datatypes (KEYWORD1)
#######################################

SD	KEYWORD1	SD
File	KEYWORD1	SD
SDFile	KEYWORD1	SD

#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin	KEYWORD2
exists	KEYWORD2
mkdir	KEYWORD2
remove	KEYWORD2
rmdir	KEYWORD2
open	KEYWORD2
close	KEYWORD2
seek	KEYWORD2
position	KEYWORD2
size	KEYWORD2	

#######################################
# Constants (LITERAL1)
#######################################
FILE_READ	LITERAL1
FILE_WRITE	LITERAL1

キーワード、識別子の後に3つ目が書かれていますが機能的な意味はなくコメントのようです。

ライブラリのフォルダとファイルの配置

ライブラリのフォルダ直下に全てのファイルを配置してもライブラリとして利用できますが、下位互換として残されている方法なので、ドキュメントで推奨されている配置に従います。

詳細はArduino IDE 1.5: Library specificationの「Layout of folders and files」に記載されています。

必要なフォルダは以下のフォルダです。

  • ライブラリのソースファイルを格納するsrcフォルダ
  • サンプルスケッチを格納するexamplesフォルダ
    さらにサンプル別にサブフォルダを作成して、サンプルスケッチを格納します。

プロパティファイルと、キーワードハイライトの定義ファイルはライブラリフォルダの直下に配置します。

配置例(標準ライブラリのLiquidCrystal)

LiquidCrystal
LiquidCrystal/keywords.txt
LiquidCrystal/library.properties
LiquidCrystal/README.adoc
LiquidCrystal/src
LiquidCrystal/src/LiquidCrystal.cpp
LiquidCrystal/src/LiquidCrystal.h
LiquidCrystal/examples
LiquidCrystal/examples/Autoscroll
LiquidCrystal/examples/Autoscroll/Autoscroll.ino
LiquidCrystal/examples/Blink
LiquidCrystal/examples/Blink/Blink.ino
... examplesの省略

サンプルライブラリの作成

ライブラリのフォルダ作成

[ ~/Documents/Arduino/libraries ]
ringo@stupiddog  $ mkdir -p jpzukin_sample_library/{examples/Lchika,src}

[ ~/Documents/Arduino/libraries ]
ringo@stupiddog  $ tree jpzukin_sample_library/
jpzukin_sample_library/
├── examples
│   └── Lchika
└── src

2 directories, 0 files

プロパティファイルの作成

~/Documents/Arduino/libraries/jpzukin_sample_libraryフォルダに以下の内容でlibrary.propertiesファイルを作成します。

name=Sample Library
version=1.0.0
author=Stupiddog
maintainer=Stupiddog <info@example.com>
sentence=This is a sample library.
paragraph=This is a sample library.
category=Other
url=https://github.com/jpzukin/jpzukin-sample-library
architectures=*

キーワードファイルの作成

~/Documents/Arduino/libraries/jpzukin_sample_libraryフォルダに以下の内容でkeywords.txtファイルを作成します。

#######################################
# Syntax Coloring Map Sample library
#######################################

#######################################
# Datatypes (KEYWORD1)
#######################################
Sample		KEYWORD1

#######################################
# Methods and Functions (KEYWORD2)
#######################################
on			KEYWORD2
off			KEYWORD2

プログラム作成

~/Documents/Arduino/libraries/jpzukin_sample_library/srcフォルダに以下の内容でSample.hファイルを作成します。

プログラムの内容は、コンストラクタで指定されたピンを、on()でHIGHに、off()でLOWにするだけです。指定のピンにLEDが接続されていればLチカとなります。サンプルなのでチェック処理はありません。

/*
 * Sample.h
 */
#ifndef JPZUKIN_SAMPLE_LIBRARY
#define JPZUKIN_SAMPLE_LIBRARY
#include <Arduino.h>

class Sample {
public:
  Sample(uint8_t pin=LED_BUILTIN);
  on();     // LED ON
  off();    // LED OFF
  
private:
  uint8_t _pin;
};

#endif

~/Documents/Arduino/libraries/jpzukin_sample_library/srcフォルダに以下の内容でSample.cppファイルを作成します。

/*
 * Sample.cpp
 */
#include <Arduino.h>
#include "Sample.h"

Sample::Sample(uint8_t pin) {
  _pin = pin;
  pinMode(pin, OUTPUT);
}

Sample::on() {
  digitalWrite(_pin, HIGH);
}

Sample::off() {
  digitalWrite(_pin, LOW);
}

サンプルスケッチの作成

~/Documents/Arduino/libraries/jpzukin_sample_library/examples/Lchikaフォルダに以下の内容でLchika.inoファイルを作成します。必ずフォルダ名とスケッチファイル名を同じにします。

#include "Sample.h"

Sample led = Sample();

void setup() {
  led.off();
}

void loop() {
  led.on();
  delay(500);
  led.off();
  delay(500);
}

ここまでのファイルが揃ったらArduino IDEを立ち上げて、スケッチ例からサンプルスケッチ「Lchika」を呼び出せます。

[ ~/Documents/Arduino/libraries ]
ringo@stupiddog  $ find jpzukin_sample_library/
jpzukin_sample_library/
jpzukin_sample_library//examples
jpzukin_sample_library//examples/Lchika
jpzukin_sample_library//examples/Lchika/Lchika.ino
jpzukin_sample_library//keywords.txt
jpzukin_sample_library//library.properties
jpzukin_sample_library//src
jpzukin_sample_library//src/Sample.cpp
jpzukin_sample_library//src/Sample.h

呼び出したサンプルスケッチでキーワードのハイライトが行われていることが確認できます。

Arduino UNO R3を接続してプログラムを書き込むとボード上のLEDが点滅します。

githubで管理する

ライブラリをローカルリポジトリで管理します

[ ~/Documents/Arduino/libraries/jpzukin_sample_library ]
ringo@stupiddog  $ git init
Initialized empty Git repository in /Users/stupiddog/Documents/Arduino/libraries/jpzukin_sample_library/.git/

[ ~/Documents/Arduino/libraries/jpzukin_sample_library ]
ringo@stupiddog  (master) $ git add .

[ ~/Documents/Arduino/libraries/jpzukin_sample_library ]
ringo@stupiddog  (master) $ git commit -m "first commit"
[master (root-commit) 9a11085] first commit
 5 files changed, 77 insertions(+)
 create mode 100644 examples/Lchika/Lchika.ino
 create mode 100644 keywords.txt
 create mode 100644 library.properties
 create mode 100644 src/Sample.cpp
 create mode 100644 src/Sample.h
 

githubに新しいリポジトリを作成します

ローカルリポジトリからリモートリポジトリへpushします

[ ~/Documents/Arduino/libraries/jpzukin_sample_library ]
ringo@stupiddog  (master) $ git remote add origin https://github.com/jpzukin/jpzukin-sample-library.git

[ ~/Documents/Arduino/libraries/jpzukin_sample_library ]
ringo@stupiddog  (master) $ git push -u origin master
Counting objects: 10, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (10/10), 1.18 KiB | 1.18 MiB/s, done.
Total 10 (delta 0), reused 0 (delta 0)
To https://github.com/jpzukin/jpzukin-sample-library.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

ZIPファイルからライブラリがインストール出来ることを確認します

ローカルのライブラリを削除します

githubへ登録したので、ローカルにライブラリが無い状態を作ります。

[ ~/Documents/Arduino/libraries ]
ringo@stupiddog  $ rm -fr jpzukin_sample_library/

githubからZIP形式でリポジトリをダウンロードします

(README.mdを追加しています)

Arduino IDEを起動し直して「ZIP形式のライブラリをインストール…」からダウンロードしたZIPファイルを読み込みます。

正常にライブラリが追加されるとメッセージが表示されます。

追加されたライブラリが確認できます。

まとめ

配布可能な非標準ライブラリを作成し、Aruduino IDEにインストールする方法が分かりました。

完全なるC/C++言語には対応していませんが、スケッチも最終的に「arv-gcc/arv-g++」によりC++言語としてコンパイルされることが分かったので、コードが考え易くなりました。