m5stack-avatarをPC上で動かそう!

M5Stack製品の最強ライブラリであるM5Unified、使ってますか?
ご存知の方も多いでしょうが、M5UnifiedやM5GFXの一部機能はWindows, Mac, Linux上で実行・デバッグできます(PlatformIOに限りますが)。

スタックチャンのフロントエンド(?)である m5stack-avatarもM5Unified対応されています。
ということはPCで動かせます!ヤッター!

準備

まずは環境の構築です。

具体的な手順はこちらのドキュメントに記載されています。Windowsだけちょっと手作業が多いですが落ち着いてやれば大丈夫です。

github.com

2024/1/1 追記(Windowsのみ)

MSYSを最新のドキュメントでセットアップした場合、SDL2のコピー先はC:\msys64\ucrt64にすると良いようです。

実装

冒頭で「m5stack-avatarはM5Unified対応してるから・・」と書きましたが、実はちょっとだけライブラリの変更が必要です(Arduino環境でしかない関数やオブジェクトを差し替えたりという軽微な変更)。

forkして対応しておきましたので、こちらのライブラリを使用しましょう。

2024/1/7 更新 リリースされたのでlib_depsを変更しました。

2024/1/4 更新 PullRequestが通ったのでlib_depsを本家のdevelopブランチに変更しました。

では実際のコードです

まずはplatformio.ini

[platformio]
default_envs = native

[env]
lib_deps = meganetaaan/M5Stack-Avatar @ ^0.9.2

[env:native]
platform = native
build_type = debug
build_flags = -O0 -xc++ -std=c++14 -lSDL2
  -I"/usr/local/include/SDL2"                ; for intel mac homebrew SDL2
  -L"/usr/local/lib"                         ; for intel mac homebrew SDL2
  -I"${sysenv.HOMEBREW_PREFIX}/include/SDL2" ; for arm mac homebrew SDL2
  -L"${sysenv.HOMEBREW_PREFIX}/lib"          ; for arm mac homebrew SDL2
  -DM5GFX_BOARD=board_M5Stack

[env:esp32_arduino]
build_type = debug
platform = espressif32
framework = arduino
board = esp32dev
upload_speed = 1500000
monitor_speed = 115200

そしてmain.cpp

#include <M5Unified.h>
#include <Avatar.h>

using namespace m5avatar;

Avatar avatar;

void setup() {
  M5.begin();
  avatar.init();
}

void loop() {
}

また、ネイティブ実行時のmain()が必要なのでM5GFXのexampleから持ってきてsrcディレクトリに置きます。
場所がわからなかったら下記のリンク先のコードをコピペしてください。

github.com

2024/2/14 更新 リンクで失敗する場合、こちらの記事を参考にしてみてください。

hollyhockberry.hatenablog.com

実行

nativeの環境を選択して、uploadをクリックしましょう。
どこにアップロードするんだろう?とか考えちゃダメです!

動きました!やったね!

ちなみにesp32_arduinoの環境を選択してM5Stack実機に書き込んでみるとちゃんと同じ動きのバイナリが出来上がっています。

応用

platformio.ini-DM5GFX_BOARD=board_M5Stackの行を
-DM5GFX_BOARD=board_M5Dial
に変更してM5Dialで動作させてみましょう。

あ、位置がズレてますね。実機に書き込む前に確認できるので効率良くて助かります。

アバターの位置をLCDのサイズから自動調整するコードを書いてみました。
下記のコードをsetup()にコピペして実行してみてください。おそらく良い感じの位置に表示されるはずです!

// LCDに合わせてAvatarの位置とサイズを調整します.
const auto r = avatar.getFace()->getBoundingRect();
const auto scale_w = M5.Display.width() / (float)r->getWidth();
const auto scale_h = M5.Display.height() / (float)r->getHeight();
const auto scale = std::min(scale_w, scale_h);
// 縦横小さい方に合わせてScaleを設定します.
avatar.setScale(scale);
const auto offs_x = (r->getWidth() - M5.Display.width()) / 2;
const auto offs_y = (r->getHeight() - M5.Display.height()) / 2;
// 中心になるように位置をオフセットします.
avatar.setPosition(-offs_y, -offs_x);

で、何が嬉しいの?

Avatarをデフォルトで使う場合は先ほどの位置調整時にちょっと嬉しいかな?程度ですが、ボタン操作に応じて表情を変えたりと凝ったことをするときに役立つかもしれません。

また、AvatarはFaceにDrawableというクラスを派生したパーツを並べることで顔を描画しています。

自前のクラスに差し替えてオリジナルなAvatarを作る際、私のような雑な性格だと微修正→書き込み→再度微修正→・・のサイクルで大変効率が悪いです。
わざわざ書き込む必要なくPC上ですぐに動作確認できると効率良い開発ができますよ!

以前M5Dialで動くSNSアイコン名札を作った際、全て実機でやってたら途中で投げ出してたと思います。ありがとうM5Unified!

終わりに

PCで動かしたりデバッガ使ったりは初心者にハードルが高いかもー!って思うかもですが、ステップ実行で動きを確認できるのでソース眺めるより理解しやすいのでは?と思います。

表示周りの調整の繰り返しはPC上でササっとやってどんどん面白いものを作ってください!