AtomS3 で Mini Unit OLED を M5GFX を活用して動かしたメモ

AtomS3 で Mini Unit OLED を M5GFX を活用して動かしたメモ

AtomS3 で Mini Unit OLED を M5GFX を活用して動かしたメモです。

背景

M5Stack用 0.42インチ Mini OLEDユニット — スイッチサイエンス

Atom EchoS3R で音声録音サーバーを作ってみたメモ で、音のインタラクションもいいのですが、やはりエラー表示など音だけでは表現しにくい繊細なものを視覚的にも出したいなということで、ちょっとディスプレイもあるといいなということで、外付けの小さいディスプレイとして Mini Unit OLED がよさそうなので、やってみました。

Unit Mini OLED

ただ、こちらを見ていると M5Stack/examples/Unit/MiniOLED/MiniOLED.ino at master · m5stack/M5Stack のサンプルだと U8g2lib.h を使って頑張って表示するような形だったので、どうにか M5GFX に乗っかって書けないかなあということを調べつつやってみました。

AtomS3 + Mini Unit OLED のM5GFX統合 - 開発記録

実際のコード

実際に出来上がったコードはこちらです。

こちらの仕組みを活用しています。

/*
 * AtomS3 + Mini Unit OLED (M5UnitMiniOLED版)
 * 
 * M5UnitMiniOLEDライブラリを使用した実装
 * M5.Displays(1)でMini OLEDにアクセス
 * M5GFXの全機能(print、println、printf)がそのまま使える
 */

// 重要: M5UnitMiniOLEDはM5Unifiedより前にインクルード必須!
#include <M5UnitMiniOLED.h>
#include <M5Unified.h>

void setup() {
    auto cfg = M5.config();
    
    // Unit Mini OLEDの設定(AtomS3のPORT.A: SDA=G2, SCL=G1)
    cfg.unit_mini_oled.pin_sda  = GPIO_NUM_2;
    cfg.unit_mini_oled.pin_scl  = GPIO_NUM_1;
    cfg.unit_mini_oled.i2c_addr = 0x3C;
    cfg.unit_mini_oled.i2c_freq = 400000;
    
    M5.begin(cfg);
    
    // シリアル通信開始
    Serial.begin(115200);
    Serial.println("AtomS3 + Mini OLED (M5UnitMiniOLED) Setup");
    
    // 接続されたディスプレイ数を確認
    int display_count = M5.getDisplayCount();
    Serial.printf("Display count: %d\n", display_count);
    
    // メインディスプレイ(AtomS3内蔵)の初期表示
    M5.Display.setRotation(0);
    M5.Display.setTextSize(2);
    M5.Display.fillScreen(TFT_BLACK);
    M5.Display.setTextColor(TFT_WHITE);
    M5.Display.setCursor(10, 10);
    M5.Display.println("AtomS3");
    M5.Display.setCursor(10, 30);
    M5.Display.println("M5GFX");
    
    // 全ディスプレイに初期表示
    for (int i = 0; i < display_count; ++i) {
        M5.Displays(i).setTextSize(1);
        M5.Displays(i).fillScreen(TFT_BLACK);
        M5.Displays(i).setTextColor(TFT_WHITE);
        M5.Displays(i).setCursor(0, 0);
        M5.Displays(i).printf("Display %d", i);
    }
    
    // Mini OLEDに追加メッセージ(接続されている場合)
    if (display_count > 1) {
        M5.Displays(1).setCursor(0, 15);
        M5.Displays(1).println("Hello!");
        M5.Displays(1).println("M5Stack");
    }
    
    Serial.println("Setup Complete");
}

void loop() {
    M5.update();
    
    static int count = 0;
    
    // メインディスプレイ更新
    M5.Display.fillScreen(TFT_BLACK);
    M5.Display.setCursor(10, 10);
    M5.Display.setTextSize(2);
    M5.Display.printf("Cnt:%d", count);
    
    // セカンドディスプレイ(Unit Mini OLED)更新
    if (M5.getDisplayCount() > 1) {
        M5.Displays(1).fillScreen(TFT_BLACK);
        M5.Displays(1).setCursor(0, 0);
        M5.Displays(1).setTextSize(1);
        M5.Displays(1).println("Count:");
        M5.Displays(1).setCursor(0, 15);
        M5.Displays(1).setTextSize(2);
        M5.Displays(1).printf("%d", count);
    }
    
    // シリアル出力
    Serial.printf("Count: %d\n", count);
    
    count++;
    delay(1000);
}

今回の実装で、以下のことができるようになります。

  • M5GFX の統一された API(print(), println(), printf())で Mini OLED を動かせる
  • M5.Display と同じ書き方で外付けディスプレイもいける
  • M5.Displays(0) で内蔵ディスプレイ、M5.Displays(1) で Mini OLED にアクセスできる

U8g2 の独自記法(u8g2.drawStr() など)を覚えなくても、いつもの M5GFX の書き方でそのまま書けます。

PlatformIO の設定例 platformio.ini はこんな感じです。

[env:atoms3-mini-oled]
platform = espressif32
board = m5stack-atoms3
framework = arduino
build_src_filter = +
lib_deps = 
    m5stack/M5Unified@^0.2.11
    m5stack/M5GFX@^0.2.2

動かしてみる

ビルド&書き込みできたら、AtomS3 の内蔵ディスプレイと Mini OLED の両方にカウンターが表示されます。

M5.Display でいつも通り内蔵ディスプレイに書きつつ、M5.Displays(1) で外付けの Mini OLED にも同じ感覚で書けるのは、なかなか便利ですね~。