Upgrade to Pro — share decks privately, control downloads, hide ads and more …

M5Unifiedの紹介

 M5Unifiedの紹介

2023年5月1日~5月5日、M5JPTour2023 にて使用したスライドです。
M5Stack公式ライブラリのM5Unifiedを紹介します。

Other Decks in Programming

Transcript

  1. M5Unified の紹介
    Core, Core2, Tough, StickC/CPlus, CoreInk, Paper, Station, Atom, Stamp…
    すべてに使える共通ライブラリ

    View Slide

  2. 登壇者の自己紹介
    ・ハンドルネーム : @lovyan03 / らびやん / 古井凡人
    ・約25年程 Windows用 業務アプリ開発の会社に在籍。 (稀にマイコン向け案件も…)
    ・2018年夏頃、個人的にM5Stackを購入、見事にハマる。
    ・2020年春頃、自作のグラフィックライブラリ LovyanGFX を公開。
    ・2021年春頃より、スイッチサイエンス経由で
    M5Stack製品のソフト開発を受託。
    ・2023年4月、スイッチサイエンスに入社。

    View Slide

  3. 今回の発表内容の前提条件…
    ・Arduino 環境 (および ESP-IDF )を対象とします。
    ・UIFlow (MicroPython) をお使いの方には直接の関係はありませんが…
      今後、UIFlow2.0 に移行する際には、少し関係があります。

    View Slide

  4. M5StackをArduinoIDE環境で使用するには?
    (一般的に知られている手順)
    ・M5Stack + Arduino というキーワードで検索すると すぐ見つかる手順はこんな感じ。
    ・ボードマネージャに Espressif 公式の
      (またはM5Stack公式の)
     ボード定義をインストールする。
    ・ライブラリマネージャで「 M5Stack」
     ライブラリをインストールする。

    View Slide

  5. M5StackをArduinoIDE環境で使用するには?
    (一般的に知られている手順)
    ・ボードの設定と、ライブラリの準備ができたら …
    ・「M5Stack.h」ライブラリを include すると、
     「M5」オブジェクトが使用可能になる。
    ・例:画面へのテキスト表示はこんな感じ。⇒
    #include
    void setup() {
    M5.begin();
    }
    void loop() {
    M5.update();
    M5.Lcd.print("Hello M5Stack!");
    }

    View Slide

  6. M5StackCore2や他の機種を使用するには?
    ・「M5Stack」ライブラリは M5StackCore専用。
    ・機種ごとに専用のライブラリが個別に用意されており、使い分けが必要。
    ・また、使用する機種に合ったボード定義をメニューから選ぶ必要がある。
    M5Stack.h M5Core2.h M5Tough.h M5StickC.h M5StickCPlus.h M5CoreInk.h M5EPD.h

    View Slide

  7. 複数の機種に対応するには?
    ・基本的には、どの機種で使うかを予め決め、
     その機種の専用のコードを書いていく。
    ・「複数の機種に対応したい 」と思った場合…
     どれをinclude するか、手作業で変更する …?
    // #include
    #include
    // #include
    // #include
    void setup() {
    M5.begin();
    }
    void loop() {
    M5.update();
    M5.Lcd.print("Hello M5Stack!");
    }

    View Slide

  8. 複数の機種に対応するには?
    ・ボードマネージャの選択に応じて、
     ARDUINO_M5STACK_Core2 のような
     機種別のdefine値が自動生成される。
    ・# if defined で値の有無を判定すれば、
     機種別の分岐を作ることができる。
    ・うまく書ければ、ひとつのソースで
     複数機種に対応することも …一応可能。
    #if defined (ARDUINO_M5STACK_Core2)
    #include
    #elif defined (ARDUINO_M5Stick_C)
    #include
    #elif defined (ARDUINO_M5Stick_C_Plus)
    #include
    #else
    #include
    #endif

    View Slide

  9. 複数の機種に対応するには?
    ・しかし、仕様が異なる部分がたくさんあるため、完全な共通化はとても難しい。
     ・LCD搭載モデル・CoreInk・M5Paperの3種類の描画関数が統一されていない。
     ・スピーカーがI2Sオーディオ・アナログ・ブザー…と異なる方式になっている。
     ・ボタンの数が異なる。また、タッチパネル搭載モデルにはボタンがない。
     ・「M5Stackにある あの関数がCore2には無い…!?」という状況が頻繁に生じる。

    View Slide

  10. どうにか統一する方法はないか…?
    ・どの機種でも対応できるソフトを書きたい …と思っても、簡単にはできない。
    ・各製品のハードウェア構成の内容を比較していくと、
     全く別の構成・仕様になっており、共通点が殆どない。
    ・ライブラリを修正するとしても、製品個別にライブラリがあるため数が多い。
     全部の相違点を統一化するためのメンテナンスは困難を極める。
    ・既に大勢に使われているライブラリの仕様を大幅に変更するのは望ましくない。

    View Slide

  11. どうにか統一する方法はないか…?
    ・どの機種でも対応できるソフトを書きたい …と思っても、簡単にはできない。
    ・各製品のハードウェア構成の内容を比較していくと、
     全く別の構成・仕様になっており、共通点が殆どない。
    ・ライブラリを修正するとしても、製品個別にライブラリがあるため数が多い。
     全部の相違点を統一化するためのメンテナンスは困難を極める。
    ・既に大勢に使われているライブラリの仕様を大幅に変更するのは望ましくない。
    もういっそ 
    新規に作ろう
     ライブラリ

    View Slide

  12. というわけで全機種共通の統合ライブラリ
    「M5Unified」を作成しました…!
    ・これひとつで全機種共通!
    ・ディスプレイがLCDでもEPDでも共通操作!
    ・スピーカーがI2Sオーディオでもアナログ接続でもブザーでも共通操作!
    ・Arduino環境だけでなく、ESP-IDF 環境でも使用可能!
    M5Unified.h M5Unified.h M5Unified.h M5Unified.h M5Unified.h M5Unified.h M5Unified.h

    View Slide

  13. というわけで全機種共通の統合ライブラリ
    「M5Unified」を作成しました…!
    ・ATOMS3やSTAMPC3にも対応!
    ・外部画面にも対応可能!
    ※UnitRCAはG25orG26が必要
     ESP32-S3は非対応
    M5Unified.h M5Unified.h M5Unified.h M5Unified.h M5Unified.h M5Unified.h

    View Slide

  14. ・本体内蔵画面+外部接続画面の複数画面にも対応可能!※RCAはG25orG26が必要、S3は非対応
    というわけで全機種共通の統合ライブラリ
    「M5Unified」を作成しました…!
    M5Unified.h M5Unified.h M5Unified.h M5Unified.h M5Unified.h M5Unified.h M5Unified.h

    View Slide

  15. ・カラーもモノクロも区別なく同じ方法で使用できます!
    ・自動的にモノクロ減色処理が行われるため、カラー LCDとの違いを気にしなくて OK!
    画面がモノクロの場合はどうなるの…?

    View Slide

  16. ・もちろん外付けスピーカにも対応。
     ・HAT SPK
     ・HAT SPK2
     ・ATOMIC SPK
     ・Module RCA
     ・Module Display
    ・上記以外の独自に接続したスピーカも、
     設定を少し記述すれば対応可能。
    スピーカーが外付けの場合はどうなるの…?

    View Slide

  17. UIFlow も v2からM5Unifiedを採用
    ・UIFlow (MicroPython) は ESP-IDF 用。Arduino ではビルドできない。
    ・M5StackライブラリはArduino用。ESP-IDF ではビルドできない。
    ・このため、Arduino用ライブラリとUIFlowの仕様には共通点がなく、別々のものだった。
    ・一方、M5UnifiedならArduinoでもESP-IDFでもビルド可能。
    ・ただし従来のUIFlowとは仕様が大きく変更となる
    …。
    ・メジャーバージョンを刷新し、
    M5Unifiedを採用したUIFlow2の開発をする運びとなった。

    View Slide

  18. M5Unifiedを使用するには?
    ・ライブラリマネージャから “M5Unified” をインストールする。
    ・”M5Unified” の依存ライブラリとして “M5GFX” もインストールする。
    ※ ArduinoIDE および PlatformIO のライブラリに登録済みです。

    View Slide

  19. M5Unifiedを使用するには?
    ・どの機種でも「#include 」でOK。
    ・しかもボード選択で対象機種を間違えていても、
     大抵の場合は普通に動作する。
     (例:M5StickCを選択してCore2に書いてもOK)
     注:16MB Flash設定で4MB Flashモデル機に書いたり、
      ESP32-S3,C3 等 異なるMCUを選んだ場合は…
      さすがに動作しませんが …。
    #include
    void setup() {
    M5.begin();
    }
    void loop() {
    M5.update();
    M5.Display.print(
    "Hello M5Stack!");
    }

    View Slide

  20. M5Unifiedで後付けの画面を使うには?
    ・外部画面を使う場合は、
     先頭に#includeの記述を追加すると動きます。
     ※ M5Unified.hより前に記述が必要。
    #include
    #include
    #include
    #include
    void setup() {
    M5.begin();
    }
    void loop() {
    M5.update();
    M5.Display.print(
    "Hello M5Stack!");
    }

    View Slide

  21. M5Unifiedで複数の画面を使うには?
    ・複数の画面を使う場合は …
     M5.getDisplayCount 関数で画面の数を取得し、
     M5.Displays(番号). に対して操作を行えば OK。
    #include
    #include
    #include
    #include
    void setup() {
    M5.begin();
    int c=M5.getDisplayCount();
    for(int i=0;iM5.Displays(i).print(i);
    }
    }
    Displays(0) Displays(1) Displays(2) Displays(3)

    View Slide

  22. M5Unifiedで音を鳴らすには?
    ・音の再生も共通に。
    ・単純な音であれば、 M5.Speaker.tone 関数。
     引数1で周波数、引数2で再生時間を設定。
    ・別タスクで動作するので自動的に止まる。
    ・右の例はド・ミ・ソの3つの音を順に
     500 msec間隔で開始、各音を2秒再生。
      ( 和音になります! )
    ・最大8音まで重ねることが可能。
    #include
    void setup() {
    M5.begin();
    M5.Speaker.tone(523.251, 2000);
    delay(500);
    M5.Speaker.tone(659.255, 2000);
    delay(500);
    M5.Speaker.tone(783.991, 2000);
    }

    View Slide

  23. M5Unifiedで後付けスピーカを使うには?
    ・外部スピーカを使用したい場合は M5.begin 関数の実行時に設定を行えば OK。
    #include
    void setup() {
    auto cfg = M5.config();
    // 使用するスピーカに true を設定する
    cfg.external_speaker.hat_spk = true;
    cfg.external_speaker.hat_spk2 = true;
    cfg.external_speaker.atomic_spk = true;
    cfg.external_speaker.module_rca = true;
    cfg.external_speaker.module_display=true;
    M5.begin(cfg);
    }

    View Slide

  24. 複数機種に対応したコードを書くコツ
    ・どの機種でも使えるライブラリですが …
    コードを書くときに工夫が必要な部分があります。
    ・例えば…
    ・画面への描画座標は自前で座標計算をする。
    ・画面の比率に応じて 画面のレイアウトを切り替える。
    ・機種に応じて ボタンの操作方法を切り替える。
    ・外部画面の有無によって 描画先を切り替える。

    View Slide

  25. 複数機種に対応したコードを書くコツ
    (例:画面中央に円を描くには?)
    ・例えば、右のコードのような書き方をした場合 …
     画面サイズが 320×240 ならば、
     狙い通り、画面の中央に表示される。
    M5.Display.fillCircle(
    160, // 中心X座標
    120, // 中心Y座標
    60, // 円の半径
    TFT_GREEN // 円の色
    );

    View Slide

  26. 複数機種に対応したコードを書くコツ
    (例:画面中央に円を描くには?)
    ・しかし画面サイズが異なると …
     画面サイズが 320×240 以外では、
     位置がずれてしまう。
    M5.Display.fillCircle(
    160, // 中心X座標
    120, // 中心Y座標
    60, // 円の半径
    TFT_GREEN // 円の色
    );

    View Slide

  27. 複数機種に対応したコードを書くコツ
    (例:画面中央に円を描くには?)
    ・計算で求めればOK!
     M5.Display.width() : 画面の幅
     M5.Display.height() : 画面の高さ
     2で割ると中心座標が得られる。
    M5.Display.fillCircle(
    M5.Display.width() / 2,
    M5.Display.height() / 2,
    M5.Display.height() / 4,
    TFT_GREEN
    );

    View Slide

  28. 複数機種に対応したコードを書くコツ
    (例:画面の縦横比で配置を変えるには?)
    ・例えば、画面を半分に分け、別々の表示をしたい …
     しかし、縦長の画面の場合、細長く分割される。
     なるべく正方形に近い形に分割するには …?
    M5.Display.fillRect(
    0,
    0,
    M5.Display.width() / 2,
    M5.Display.height(),
    TFT_BLUE);
    M5.Display.fillRect(
    M5.Display.width() / 2,
    0,
    M5.Display.width() / 2,
    M5.Display.height(),
    TFT_YELLOW);

    View Slide

  29. 複数機種に対応したコードを書くコツ
    (例:画面の縦横比で配置を変えるには?)
    ・画面の幅と高さを比較して分岐すれば OK。
     横長なら 左右に分割して描画する。
     縦長なら 上下に分割して描画する。
    if (M5.Display.width()
    >= M5.Display.height()) {
    // 画面が正方形~横長の場合
    // 左右に分割する描画をする
    } else {
    // 画面が縦長の場合
    // 上下に分割する描画をする
    }

    View Slide

  30. 複数機種に対応したコードを書くコツ
    (例:画面の縦横比で配置を変えるには?)
    ・より実践的には…
     分岐の中では座標計算のみを行う。
    ・描画は分岐の外で行うと、一か所に纏められる。
    ・さらに、描画処理を自作関数化しておくと、
     呼び出し側の記述をシンプルにできます。
    ・この例では fillRect1 と fillRect2 が自作関数。
     関数内で、引数の座標に描画すれば OK!
    int w = M5.Display.width();
    int h = M5.Display.height();
    int x = 0, y = 0;
    if (w >= h) {
    w /= 2; // 描画幅を半分に
    x = w; // X座標を変更
    } else {
    h /= 2; // 描画高さを半分に
    y = h; // Y座標を変更
    }
    fillRect1(0, 0, w, h);
    fillRect2(x, y, w, h);

    View Slide

  31. 複数機種に対応したコードを書くコツ
    (例:操作方法を共通化するには?)
    ・例えばメニュー画面を自作するとき、
     「ボタンA」= 左移動
     「ボタンB」= 決定
     「ボタンC」= 右移動
     という操作方法を実装した場合 …
    if (M5.BtnA.wasClicked()){
    // 左移動操作
    }
    if (M5.BtnB.wasClicked()){
    // 決定操作
    }
    if (M5.BtnC.wasClicked()){
    // 右移動操作
    }
    A B C

    View Slide

  32. 複数機種に対応したコードを書くコツ
    (例:操作方法を共通化するには?)
    ・CoreInkやPaperは そのままでも大丈夫そう。
    ・しかしStickC/CPlusにはボタンCがないので、
     右移動の操作ができない。
     また、できればボタン Aを決定操作にしたい。
    A
    B
    C
    A B C A
    B
    PWR
    EXT
    PWR
    if (M5.BtnA.wasClicked()){
    // 左移動操作
    }
    if (M5.BtnB.wasClicked()){
    // 決定操作
    }
    if (M5.BtnC.wasClicked()){
    // 右移動操作
    }

    View Slide

  33. ・M5.getBoard関数で機種別に分岐を作れば OK!
    ・StickC/CPlusの場合のみ判定内容を変えて、
     PWR = 左移動 A = 決定 B = 右移動 とする。
    A
    B
    C
    A B C A
    B
    PWR
    HAT
    PWR
    複数機種に対応したコードを書くコツ
    (例:操作方法を共通化するには?)
    switch (M5.getBoard()) {
    case m5gfx::board_M5StickC:
    case m5gfx::board_M5StickCPlus:
    // StickC/CPlus用の操作判定
    // PWR=左移動,A=決定,B=右移動
    break;
    default:
    // それ以外の機種用の操作判定
    // A=左移動,B=決定,C=右移動
    break;
    }

    View Slide

  34. ・例えばM5StackにModuleDisplayを取り付けても、
     M5.Displayに描画すると内蔵画面に描画される。
    ・ModuleDisplayが接続されている場合には
     そちらに描画できないか …?
    複数機種に対応したコードを書くコツ
    (例:外部画面を優先して使うには?)
    #include
    #include
    void setup() {
    M5.begin();
    M5.Display.print(”which?”);
    }
    M5.Display

    View Slide

  35. ・M5.setPrimaryDisplayType関数を使って、
     メインで使いたい画面タイプを指定すれば OK!
    ※画面が見つからない場合は効果を及ぼさない。
    複数機種に対応したコードを書くコツ
    (例:外部画面を優先して使うには?)
    #include
    #include
    void setup() {
    M5.begin();
    M5.setPrimaryDisplayType({
    m5gfx::board_M5ModuleDisplay});
    M5.Display.print(”which?”);
    }
    M5.Display

    View Slide

  36. まとめ…
    M5Unifiedのメリット・デメリット
    メリット:
    ・どの機種でも同じコードで動作でき、複数機種への対応が簡単にできる。
    ・実行時に機種判定を行うため、ひとつのバイナリで複数機種に対応できる。
    ・Arduino環境でもESP-IDF環境でも、M5Unifiedの機能は同じように呼び出せる。
    デメリット:
    ・名称が製品名と一致していないことや、後発ライブラリであることから、知名度が低い。
    ・従来のライブラリと完全互換ではなく、機種固有の機能への対応がまだ万全ではない。
    ・起動時に一瞬だけ、機種判別のための信号がGPIOから出ることがある。

    View Slide

  37. M5Unifiedを是非ご活用ください!
    ご清聴、ありがとうございました!

    View Slide