これは東工大ロボット技術研究会のアドベントカレンダー rogy Advent Calendar 2022 10日目の記事です。
突然ですが、マイコン(Arduino, ESP32など)のプログラミング環境って独自IDE(Arduino IDEとか)に依存しているものが多いですよね。で、そういうIDEはVSCodeに比べるとやはり↓のような面が物足りないがちです。
- 補完機能
- テキスト編集 (正規表現を用いた検索、置換)
- シンタックスハイライト
- フォント、テーマなど各種設定
また、Arduino IDEなどでは外部のライブラリ(USB_Host_Shield 2.0など)はプロジェクトごとではなくシステム全体で同じものが共有される場合が多く、GitHubなどで他人とプロジェクトを共有するとこの点が問題になることもあります。
PlatformIOはこういった不満を解消することができます。実際に開発してみて特に問題なく快適に進められたので、開発を進めて溜まった知見をここで共有しようと思います。
PlatformIO is 何
What is PlatformIO? — PlatformIO latest documentationなどを参考にまとめたものが↓になります。
IDEの提供するGUIですが、例えばVSCodeではPlatformIOの拡張機能が提供されており、これをインストールすることでVSCodeがPlatformIOの開発環境になります。
(個人的にこの拡張機能は好きじゃないので)ここではこの拡張機能を入れずに、PlatformIOをCLIで使用する方法を紹介します。
開発環境
Raspberry Pi 4B(以下ラズパイ)に(MacBook Airから)SSH接続して、ラズパイ上でPlatformIOを使います。
ラズパイで使用するOS/microSDは次の通りです。
- OS: Ubuntu 22.04.1 LTS (64-bit)
- microSD: 16GB
ラズパイの環境構築では↓の記事を参考にしました。
Installation
シェルで進めていきます。まずはPlatformIOのインストール
$ sudo apt install python3 python3-pip
$ python3 -m pip install -U pip
# ↓のようなエラーメッセージが出た場合は一度シェルを開き直す(SSH接続であればexitしてから再びログインする)
# WARNING: The scripts pip, pip3 and pip3.10 are installed in '/home/pi/.local/bin' which is not on PATH.
$ pip3 install -U platformio
$ pio --version
# エラーが出ないことを確認
次に、ラズパイからPlatformIOでマイコンと通信できるようにします。
$ curl -fsSL https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/system/99-platformio-udev.rules | sudo tee /etc/udev/rules.d/99-platformio-udev.rules
$ sudo service udev restart
$ sudo usermod -a -G dialout $USER
$ sudo usermod -a -G plugdev $USER
Macの場合はhomebrewのパッケージをインストールしてください。
Windowsでやりたい方はInstaller Script (Recommended) — PlatformIO latest documentationを参考にしましょう。
- System Requirements — PlatformIO latest documentation
- Python Package Manager — PlatformIO latest documentation
- 99-platformio-udev.rules — PlatformIO latest documentation
Demonstration
ここではLチカのプロジェクトblink
を作成してPlatformIOの機能を見ていきます。
参考: Quick Start — PlatformIO latest documentation
ボード指定
まずはプロジェクトで使用するボードをPlatformIOに教えてあげる必要があります。そのためにはPlatformIOで設定されているボードのIDを知る必要があるのですが、このIDを知る方法として公式サイトでは次の3つが紹介されています。
- Boardのカタログページを見る
- Boardの検索ページで検索する
-
pio boards
コマンドを使う
ですが、「platformio <ボード名>」のようにググると検索上位にボードの情報が出てきます。例えば、私が「platformio arduino mega」とググった場合は↓のページがトップに出てきました。
このページの途中に、次のような記述があります。
Configuration
Please use
megaatmega2560
ID for board option in "platformio.ini"(Project Configuration File):[env:megaatmega2560] platform = atmelavr board = megaatmega2560
(Arduino Megaを使う場合は)このmegaatmega2560
が、PlatformIOに教えるボードのIDになります。
ググってもPlatformIOのサイトが出てこなかった場合はブログ記事を覗くのもいいでしょう。参考(およびメモ)として、私がよく使うボードのIDを貼っておきます。
-
Arduino Uno:
uno
-
ESP32-Devkit (Espressif ESP32 Dev Module):
esp32dev
プロジェクト作成、確認
ボードのIDがわかったら、次はプロジェクト作成です。
# 適当な場所にcdしてから実行
$ mkdir blink
$ cd blink
$ pio init -b esp32dev
pio init -b esp32dev
のesp32dev
を使用するボードのIDに置き換えましょう。PlatformIOが、指定したIDのボードに対応するツール等がインストールされているか自動で確認してくれます。初めて指定するIDの場合はここで少し時間がかかるので気長に待ちましょう。
それでは、プロジェクト作成時の状態を確認しておきましょう。現時点でのプロジェクト構造は次のようになっているはずです。
$ tree -a
.
├── .gitignore
├── include
│ └── README
├── lib
│ └── README
├── platformio.ini
├── src
└── test
└── README
4 directories, 5 files
各README
にはそれぞれのフォルダの役割が記されています。各フォルダには次のような役割があります。
フォルダ | 役割 |
---|---|
include |
ライブラリとして使用する際に外部に公開されるヘッダーファイルが入る |
lib |
プロジェクト内でのみ使用するヘッダーファイルが入る |
src |
ソースファイルは全てここに入る |
test |
ユニットテストで使用するプログラムが入る |
platformio.ini
はプロジェクトの設定ファイルです。こちらも確認しておきましょう。
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
.gitignore
はgit管理で使用するものです。ここでは省略します。
ぷろぐらみんぐ
src
フォルダ内にmain.cpp
を作り、その中にお馴染みのLチカプログラムを書いていきます。
プログラムの編集にVSCodeを使う場合はblink
ディレクトリ直下でpio init --ide vscode
を実行してからVSCodeでC/C++ Extension Packを入れるといい感じになります。
ラズパイなどでの開発ですが、VSCodeではRemote - SSHを使ってSSH接続先で開発できます。詳細は↓の記事を参照してください。
#include <Arduino.h>
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
いざビルド
コンパイルをして、ボードに書き込むかどうかでコマンドが変わります。
- コンパイルだけする場合:
pio run
- コンパイルしてボードに書き込む場合:
pio run -t upload
プロジェクト作成時と同様、書き込みの際にも必要なツール群の確認/インストールが自動で行われます。
ここまでが基本的なPlatformIOの使い方です。
シリアルモニター
PlatformIOはシリアルモニターを表示するコマンドも提供しています。具体的な方法を確認しましょう。まずはmain.cpp
に次のプログラムを書きます。(お好みで新しいプロジェクトを作成してください)
#include <Arduino.h>
void setup() {
Serial.begin(115200);
}
void loop() {
Serial.println("Hello, world!");
delay(1000);
}
これをボードに書き込んでシリアルモニターを開くと、1秒ごとに"Hello, world!"
が出力されるはずです。それでは実際にやってみましょう。
$ pio run -t upload
$ pio device monitor -b 115200
--- Terminal on /dev/ttyUSB0 | 115200 8-N-1
--- Available filters and text transformations: colorize, debug, default, direct, esp32_exception_decoder, hexlify, log2file, nocontrol, printable, send_on_enter, time
--- More details at https://bit.ly/pio-monitor-filters
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
...
出力が確認できたかと思います。シリアルモニターはctrl + C
で停止できます。
シリアルモニターを開くのにpio device monitor -b 115200
というコマンドを実行しました。-b 115200
はボーレートの設定です。省略すると9600
になります。
git管理
コンパイル時に作られるバイナリファイルなどは全て.pio
フォルダ内に置かれます。このフォルダはプロジェクト作成時にできる.gitignore
に書かれているため、誤ってバイナリファイルをコミットすることは起こりにくいです。安心してgit add .
ができます。
ここでは深掘りしませんが、プロジェクトが依存しているライブラリの情報は全てplatformio.ini
に記述します。そして、PlatformIOはビルド時などに自動的にplatformio.ini
から必要なライブラリを割り出し、.pio
フォルダ内にインストールしてくれます。このように、プロジェクト単位でライブラリのインストールが行われ、その情報も容易にgit管理対象に含まれるため、GitHubなどでプロジェクトを共有したときに発生する問題はほとんどないです。
いかがでしたか
このように、PlatformIOではIDEに依存しない開発が行えます。ここでは紹介しませんでしたが、PlatformIOは以下の機能も備えています。
- ヘッダーファイルを使用したファイル分割
- GitHubなどで公開されているライブラリの使用
- 複数ボードに対するバイナリ生成
- ユニットテスト
- デバッガー
- CI/CD
詳細はPlatformIOのドキュメントを参照してください。
Appendix: 実際に開発で使った例
実は夏休み中にロ技研内でSSR杯という新入生ロボコンが行われたのですが、私が参加したチームではPlatformIOを用いてプログラムの開発を行いました。実際のプロジェクトはGitHubで公開しています。(チームのプログラム担当は私一人だったのでissueやPR、ソースコード内のコメントすらありませんが)
大会本番に使ったのはこのプロジェクトですが、準備期間中の途中までは別のプロジェクトを使用していました。こちらは大会用に自作したライブラリを使用していたのですが、途中で設計に無理があるとわかったので新しくプロジェクトを作成しました。
ライブラリの使い方などで参考になれば幸いです。