1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

M5Stack Tab5を使い倒す(GUI編-1)

1
Last updated at Posted at 2026-01-27

1. 導入・概要

この記事はM5Stack Tab5をArduino環境で活用するための情報を共有するものです。M5Stack Tab5の10.1インチ大画面とタッチスクリーンを活用した、高機能なGUIアプリケーション開発を目指す方向けに、実践的な情報を提供します。

この記事は「Tab5を使い倒す(1_基礎編)」からの続きとなる3_GUI編です。それぞれのプロジェクトは独立しているため、どこから始めていただいても問題ありません。

GUI編ではEEZ StudioLVGL 8.3.11を使用した、視覚的なUIデザインとプログラミングの方法を解説します。

No 記事 コード
1 基礎編 Github
2 ネットワーク編 Github
3 GUI編1 / GUI編2-解説 Github

2. プロジェクトの前提条件

2-1. ハードウェア要件

  • M5Stack Tab5 (ESP32-P4)
    • 10.1インチディスプレイ(1280×720ピクセル)
    • 静電容量式タッチスクリーン
    • 8MB PSRAM(必須)
    • 公式ドキュメント

2-2. 開発環境

  • Arduino IDE 2.x

2-3. 必要なライブラリ

ライブラリ バージョン 必須/オプション 説明
M5Unified >= 0.2.10 必須 M5Stack統合ライブラリ(ハードウェア制御)
LVGL 8.3.11 必須 高機能GUIライブラリ

重要: LVGLは8.3.11を必ず使用してください。最新バージョン(9.xなど)はEEZ Studioとの互換性がありません。

2-4. GUIエディタ

  • EEZ Studio
    • 公式サイトからダウンロード
    • 視覚的なUIデザインとFlow言語によるプログラミングが可能
    • Windows、Mac、Linux対応

image.png

3. テンプレートを使ったはじめてのLVGL

3-1. プロジェクト概要

このプロジェクトは、M5Stack Tab5向けのEEZ Studio + LVGLアプリケーション開発用テンプレートです。コードはGitHubにMITライセンスとして公開しています。

プロジェクト構成

リポジトリには以下のプロジェクトが含まれています:

  1. EEZ_Template - 基本テンプレートプロジェクト
    • LVGL 8.3.11ベースのUIテンプレート
    • EEZ Studio Flow言語サポート
    • タッチ入力対応
    • SPIRAM最適化による高速描画
  2. LV8wF_Clock - 時計アプリケーション例
  3. LV8wF_Native - Native変数実装例

image.png

3-2. テンプレートの構築手順

EEZ Templateを使って最初のアプリケーションを動かすまでの手順を説明します。以下のフローチャートに従って進めていきます。

4. 詳細手順

上記のフローチャートに沿って、詳しい手順を説明します。まずは環境のセットアップから始めます。

Step1 環境構築

1-1. EEZ Studioのインストール

EEZ Studioはテスト・測定機器や組み込みデバイスのインタラクティブアプリケーション用のユーザーインターフェース構築のために開発された、ビジュアルプログラミングおよびUIデザイン環境です。

インストール手順:

  1. 公式サイトから、自身のOSに対応するインストーラを選択してダウンロードしてください
  2. インストーラを起動して、手順に従ってインストールします(Windows、Mac、Linux対応)
  3. インストール完了後、EEZ Studioを起動して動作確認を行います

image.png

1-2. Arduino IDEのインストールと初期設定

Arduino IDEのインストール:

  1. Arduino公式サイトから自身のOSに対応するインストーラを選択してダウンロードしてください
  2. インストーラを実行して、Arduino IDEをインストールします
    image.png

ESP32ボードサポートの追加:

  1. ファイル環境設定を開き、追加のボードマネージャのURLに以下を追加し、OKをクリックします

    https://espressif.github.io/arduino-esp32/package_esp32_index.json
    
  2. ツールボードM5StackM5Tab5を選択して、開発ボードの設定を反映させます

必要なライブラリのインストール:

  1. スケッチライブラリをインクルードライブラリを管理を開きます

  2. M5Unifiedで検索して、バージョン0.2.10以上をインストールします

  3. lvglで検索して、バージョン8.3.11をインストールします

重要: LVGLは8.3.11を必ず使用してください。最新バージョン(9.xなど)はEEZ Studioとの互換性がありません。このドキュメントはLVGL 8.3.11をベースとしており、他のバージョンでの動作は検証していません。

image.png

1-3. テンプレート・サンプルコードのダウンロード

以下のいずれかの方法でコードを取得してください:

方法1: Git Clone(推奨)

git clone https://github.com/macole/Tab5_GUI.git
cd Tab5_GUI

方法2: ZIPダウンロード

  1. GitHubリポジトリにアクセス
  2. CodeDownload ZIPをクリック
  3. ZIPファイルを解凍

1-4. プロジェクト構造の確認

ダウンロード後、以下のような構造になっていることを確認してください:

Tab5_GUI/
├── EEZ_Template/                # EEZ テンプレート(開発用ベース)
│   ├── EEZ_Template.ino         # メインプログラム
│   ├── LV8wF_Template.eez-project # EEZ Studio プロジェクト
│   ├── lv_conf.h                # LVGL 設定ファイル
│   ├── LICENSE                  # ライセンスファイル
│   ├── README.md                # プロジェクト概要
│   └── src/ui/                  # EEZ Studio 生成ファイル

Step2 EEZ StudioでGUIを作成

2-1. EEZ Studioでテンプレートプロジェクトを開く

既存のテンプレートプロジェクトを使用する場合(推奨):

  1. EEZ Studioを起動します
  2. FileOpen Projectを選択します
  3. EEZ_Template/LV8wF_Template.eez-projectを選択して開きます

新規プロジェクトを作成する場合:

  1. EEZ Studioのプロジェクト上部でCreateを選択します
  2. LVGL with EEZ Flowをクリックします
  3. 隣接するPROJECT SETTINGセクションで必要なパラメータを設定します

image.png

EEZ Studioの画面構成:

  • エディット画面: UI要素を視覚的に配置・編集できます
  • ツールバー: 各種UI要素(ボタン、ラベル、スライダーなど)を追加できます
  • Propertiesパネル: 選択した要素のプロパティを編集できます
  • Flowパネル: Flow言語で動作を定義できます

2-2. EEZ Studioプロジェクト設定

EEZ StudioでのLVGLベースのUI描画のための基本設定について説明します。M5Stack Tab5は解像度1280×720のディスプレイですが、EEZ Studioでの設定は異なります。

プロジェクト設定の変更:

  1. **設定(歯車アイコン)**をクリックして、Settingを開きます

  2. Setting > Generalタブで以下を設定:

    • Display Width: 720(横向き表示時の幅)
    • Display Height: 1280(横向き表示時の高さ)
    • Dark Theme: 背景を暗くしたい場合はチェックを入れる
  3. Setting > Buildタブで以下を設定:

    • LVGL include: lvgl.hlvgl/lvgl.hから変更)
    • Output folder: 生成ファイルの出力先を指定(デフォルトで問題ありません)

画面サイズの設定:

  1. 編集画面に戻り、PropertiesPOSITION AND SIZEから画面サイズを確認・調整します
  • EEZ Studioで生成されたファイルはsrc/ui/フォルダに保存されます(フォルダ名の変更は不要です)
  • テンプレートプロジェクトを使用する場合は、AruduinoIDEのテンプレートファイルからファイルが参照できるように既に適切な設定が行われています

Step3 EEZ StudioでCコードを出力

3-1. UIの編集(オプション)

必要に応じて、UIを編集できます:

  1. メインインターフェイスに戻り、UI要素を配置・編集します
  2. STYLEタブで、フォントサイズや色を調整します
  3. Flowタブで、動作を定義します

3-2. プロジェクトのビルドとエクスポート

テンプレートは基本設定だけでGUIは元からあるラベルだけですが、スパナマーク(Build)を押して、試しにコードを生成させてみましょう。

image.png

  1. Buildボタン(歯車アイコンの横)をクリックします
  2. OUTPUTパネルにエラーが表示されないことを確認します
  3. ビルドが完了すると、指定した出力フォルダにC/C++コードが生成されます

EEZ Studioから出力したファイルがsrc/ui/フォルダに正しく配置されていることを確認してください。

生成されるファイル:

  • ui.c / ui.h - UI初期化コード
  • screens.c / screens.h - 画面定義
  • eez-flow.cpp / eez-flow.h - Flow言語エンジン
  • styles.c / styles.h - スタイル定義
  • images.c / images.h - 画像データ
  • fonts.h - フォント定義
  • structs.h - 構造体定義
  • vars.h - 変数定義
  • actions.h - アクション定義

Step4 Arduino IDEでテンプレートプロジェクトを開く

EEZ Studioで作成したCコードを実行するためのArduinoプロジェクトを開きます。テンプレートプロジェクトには、M5Stack Tab5とLVGLの初期化コードなどが既に記述されています。

プロジェクトを開く手順:

  1. Arduino IDEを起動します
  2. ファイル開くを選択します
  3. EEZ_Template/EEZ_Template.inoを選択します
  4. 開くをクリックします
/*******************************************************************************
 * M5Stack Tab5 - EEZ Studio テンプレートプロジェクト
 ******************************************************************************/

#include <M5Unified.h>
#include <lvgl.h>
#include "src/ui/ui.h"
#include "src/ui/screens.h"
#include <esp_heap_caps.h>

// ============================================================================
// 定数定義
// ============================================================================

// ディスプレイ設定
#define SCREEN_WIDTH 720        // 実際の物理的な幅(縦向き時)
#define SCREEN_HEIGHT 1280      // 実際の物理的な高さ(縦向き時)
#define SCREEN_BUFFER_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT)

// LVGL設定
#define LVGL_TIMER_DELAY_MS 50   // LVGLタイマー遅延(ミリ秒)

// アプリケーション設定(カスタマイズ可能)
#define APP_UPDATE_INTERVAL_MS 100  // アプリケーション更新間隔

// ============================================================================
// グローバル変数
// ============================================================================

// LVGL描画バッファ(SPIRAMに確保)
static lv_disp_draw_buf_t g_draw_buf;
static lv_color_t *g_color_buf = nullptr;

// アプリケーション状態
static unsigned long g_lastUpdateTime = 0;

// ============================================================================
// LVGLコールバック関数
// ============================================================================
/**
 * @brief ディスプレイフラッシュコールバック
 * 
 * LVGLから呼ばれ、描画バッファの内容をディスプレイに転送します。
 */
void lv_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
    const uint32_t width = area->x2 - area->x1 + 1;
    const uint32_t height = area->y2 - area->y1 + 1;
    
    M5.Display.pushImageDMA(area->x1, area->y1, width, height, (uint16_t *)&color_p->full);
    lv_disp_flush_ready(disp);
}

/**
 * @brief タッチ入力コールバック
 * 
 */
static void lv_indev_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data)
{
    const auto touch_detail = M5.Touch.getDetail();
    
    // isPressed()とwasPressed()の両方をチェックすることで、
    // タッチ開始時だけでなく、ドラッグ中も連続的に検出できる
    if (touch_detail.isPressed() || touch_detail.wasPressed()) {
        data->state = LV_INDEV_STATE_PR;
        data->point.x = touch_detail.x;
        data->point.y = touch_detail.y;
    } else {
        data->state = LV_INDEV_STATE_REL;
    }
}

// ============================================================================
// 初期化関数
// ============================================================================
/**
 * @brief SPIRAMにディスプレイバッファを確保
 * 
 * 全画面バッファ(1280x720x2バイト = 約1.8MB)をSPIRAMに確保します。
 */
bool allocateDisplayBuffer()
{
    g_color_buf = (lv_color_t *)heap_caps_malloc(
        sizeof(lv_color_t) * SCREEN_BUFFER_SIZE,
        MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT
    );
    
    if (g_color_buf == nullptr) {
        M5.Display.setCursor(0, 0);
        M5.Display.println("Error: SPIRAM allocation failed!");
        return false;
    }
    
    return true;
}

/**
 * @brief ディスプレイドライバの設定
 */
void configureDisplayDriver(lv_disp_drv_t &disp_drv)
{
    lv_disp_drv_init(&disp_drv);
    disp_drv.hor_res = SCREEN_WIDTH;
    disp_drv.ver_res = SCREEN_HEIGHT;
    disp_drv.flush_cb = lv_disp_flush;
    disp_drv.draw_buf = &g_draw_buf;
    disp_drv.sw_rotate = 1;              // ソフトウェア回転有効
    disp_drv.rotated = LV_DISP_ROT_90;   // 90度回転(横向き表示)
    lv_disp_drv_register(&disp_drv);
}

/**
 * @brief LVGLディスプレイ初期化
 * 
 * LVGL、描画バッファ、ディスプレイドライバを初期化します。
 */
bool initLvglDisplay()
{
    lv_init();
    
    if (!allocateDisplayBuffer()) {
        return false;
    }
    
    lv_disp_draw_buf_init(&g_draw_buf, g_color_buf, NULL, SCREEN_BUFFER_SIZE);
    
    static lv_disp_drv_t disp_drv;
    configureDisplayDriver(disp_drv);
    
    return true;
}

/**
 * @brief LVGLタッチ入力初期化
 * 
 * LVGLタッチスクリーン入力デバイスを初期化します。
 */
void initLvglTouch()
{
    static lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = lv_indev_read;
    lv_indev_drv_register(&indev_drv);
}

// ============================================================================
// アプリケーション機能
// ============================================================================
/**
 * @brief アプリケーション更新処理
 * 
 * 定期的に実行されるアプリケーション固有の処理を記述します。
 * この関数をカスタマイズして独自の機能を追加してください。
 * 
 */
void updateApplication()
{
    unsigned long currentTime = millis();
    
    // 指定間隔で更新
    if (currentTime - g_lastUpdateTime < APP_UPDATE_INTERVAL_MS) {
        return;
    }    
    g_lastUpdateTime = currentTime;
    
    // ここにアプリケーション固有の処理を追加
}

// ============================================================================
// Arduino標準関数
// ============================================================================

void setup()
{
    // M5Unified初期化
    auto cfg = M5.config();
    M5.begin(cfg);
    delay(100);
    
    // LVGL初期化
    if (!initLvglDisplay()) {
        while(1) { 
            M5.Display.fillScreen(TFT_RED);
            delay(500);
            M5.Display.fillScreen(TFT_BLACK);
            delay(500);
        }
    }
    initLvglTouch();
    
    // EEZ-Studio UI初期化
    ui_init();
}

void loop()
{    
    M5.update();          // M5Unifiedの更新(ボタン、タッチなど)
    lv_timer_handler();   // LVGLタイマーハンドラ(UIの更新)
    ui_tick();            // EEZ Flow Tickハンドラ(Flow言語の実行)
    updateApplication();  // アプリケーション機能の更新
    delay(LVGL_TIMER_DELAY_MS);    // LVGL処理のためのわずかな遅延
}

Step5 コンパイル・アップロード

5-1. ボード設定

ツールメニューで以下を設定します:

ボード: M5Tab5
Upload Speed: 921600
Flash Mode: QIO
Flash Frequency: 80MHz
Partition Scheme: Default 4MB with spiffs
PSRAM: Enabled ← 必須!これがないと動作しません
USB CDC On Boot: Enabled
USB Mode: Hardware CDC and JTAG

5-2. シリアルポートの選択

  1. M5Stack Tab5をUSBケーブルでPCに接続します
  2. ツールシリアルポートで接続されたポートを選択します
    • Mac: /dev/cu.usbmodem*****
    • Windows: COM*
    • Linux: /dev/ttyACM*

5-3. コンパイル

  1. **検証(✓)**ボタンをクリックします
  2. コンパイル完了を待ちます(初回は数分かかる場合があります)
  3. エラーが表示されないことを確認します

5-4. アップロード

  1. **アップロード(→)**ボタンをクリックします
  2. アップロード完了を待ちます(進行状況が表示されます)

5. 参考資料

公式ドキュメント

チュートリアル

関連プロジェクト

6. まとめ

この記事では、M5Stack Tab5向けのEEZ Studio + LVGLアプリケーション開発の基礎を説明しました。テンプレートプロジェクトを使用することで、迅速にGUIアプリケーションを開発できます。このテンプレートをベースに自分用のアプリ開発にカスタマイズするための情報をGUI-解説編としてこちらで解説しています

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?