M5Stack にZephyr(RTOS)とEdge Impulseを実装してみました。
内蔵の加速度センサを使って、ジェスチャー認識をさせています。
Zephyr(RTOS)でEdge AIっぽいテストをした内容を紹介します。
M5Stack にZephyr(RTOS)とEdge Impulseを実装してみた
M5Stack にZephyr(RTOS)とEdge Impulseを実装してみました。
内蔵の加速度センサを使って、ジェスチャー認識をさせています。


RTOSでEdge AIっぽいテストをした内容を紹介します。
実際のデモ動画が下記となっています。
今回の内容は「M5 Japan Tour 2026 Spring Nagoya」で発表させていただきました。
発表スライドは下記となります。
M5Stack CoreS3 + Zephyr
M5Stack CoreS3でZephyr(RTOS)を始めてみた内容は下記で紹介しています。
M5Stack CoreS3でZephyr(RTOS)を始めてみた



M5Stack CoreS3 + Edge Impulse
M5Stack CoreS3の内蔵センサを使ってのAIモデル作成例は下記で紹介しています。
M5Stackの加速度センサ値をEdge Impulseにアップしてみた


GitHub
実際のテストしたリポジストリが下記となっています。
Edge Impulseのモデルに関しては、ライセンスの関係上、各自で作成お願いします
概要の紹介
今回は、IoTデバイス開発で大人気の M5Stack CoreS3 に、本格的な組み込み向けOSである Zephyr RTOS と、エッジAI開発プラットフォームの Edge Impulse を組み合わせて、デバイスの動きを認識する「ジェスチャー認識AI」を実装してみました。

単にAIを動かすだけでなく、リアルタイムOS(RTOS)の強みを活かしたマルチスレッド処理や、組み込みGUIライブラリ「LVGL」を使った画面表示まで踏み込んでみたので、その実装のポイントを紹介します!
今回作ったもの
M5Stack CoreS3に内蔵されている6軸IMU(BMI270)から加速度データを取得し、デバイスが今どんな状態かをAIが推論します。
推論結果は本体の液晶ディスプレイに、かわいい顔文字(アスキーアート)と一緒にリアルタイム表示されます。
- Idle(放置状態):
( -_- ) zzz💤 - Flick(横に振る):
( >_< )💦 - Updown(上下に振る):
( @o@ )↕️ - Knock(叩く):
( O_O )!✊
システム構成
- ハードウェア: M5Stack CoreS3 (ESP32-S3搭載)
- センサー: Bosch BMI270(内蔵IMU・加速度を使用)
- OS: Zephyr RTOS
- AIモデル: Edge Impulse (C++ SDK)
- GUI: LVGL (Zephyr標準サポート)
従来のArduino IDE環境ではなく、モジュール性が高くマルチスレッドに強い Zephyr RTOS を採用したのが今回のこだわりの一つです。

実装のポイント
実装したポイントの概要を紹介します。詳細はGitHubのmain.cppを参照ください。

Zephyr RTOSによるマルチスレッド制御
AIの推論計算(数百ミリ秒かかる)を行っている間も、センサーデータの取得(100Hz = 10ms周期)を絶対に取りこぼさないようにする必要があります。
そこで、Zephyrのスレッド機能を使って処理を完全に分離し、優先度(Priority)を設定しました。
sensor_tid(優先度5: 高): 10msごとに確実にセンサーデータを取得gui_tid(優先度6: 中): LVGLによる画面描画の更新inference_tid(優先度7: 低): 溜まったデータを使ってEdge Impulseで推論
|
1 2 3 4 |
// スレッドの定義(数値が小さいほど優先度が高い) K_THREAD_DEFINE(sensor_tid, 2048, sensor_thread_fn, NULL, NULL, NULL, 5, 0, 0); K_THREAD_DEFINE(gui_tid, 4096, gui_thread_fn, NULL, NULL, NULL, 6, 0, 0); K_THREAD_DEFINE(inference_tid, 8192, inference_thread_fn, NULL, NULL, NULL, 7, 0, 0); |

LVGLを使った表情豊かなディスプレイ表示
Zephyrは強力なGUIライブラリである「LVGL」を標準サポートしています。prj.conf で CONFIG_LVGL=y を設定するだけで簡単に組み込めます。
AIの推論結果(最も確率の高いラベル)を見て、画面の顔文字を切り替えるロジックを入れました。
|
1 2 3 4 5 6 7 8 9 10 11 |
// 推論結果のラベルに応じた顔文字を選択 const char *face_str = "( '_' )"; if (strcmp(best_label, "m5_flick") == 0) { face_str = "( >_< )"; } else if (strcmp(best_label, "m5_idle") == 0) { face_str = "( -_- ) zzz"; } else if (strcmp(best_label, "m5_knock") == 0) { face_str = "( O_O )!"; } else if (strcmp(best_label, "m5_updown") == 0) { face_str = "( @o@ )"; } |
フォントサイズも CONFIG_LV_FONT_MONTSERRAT_48=y で大きくし、デバイスに命が吹き込まれたようでとても可愛いです!
応用編でLVGLを使った顔に変更、またバー表示など対応してみました。
ビルド・書き込み
ZephyrのWestによるビルド・書き込み例は下記となります。
|
1 2 |
west build -p -b m5stack_cores3/esp32s3/procpu west flash |
ビルド結果・各使用率は下記となりました。
|
1 2 3 4 5 6 7 |
iram0_0_seg: 66308 B 343552 B 19.30% dram0_0_seg: 147968 B 327168 B 45.23% irom0_0_seg: 498555 B 32 MB 1.49% drom0_0_seg: 749688 B 32 MB 2.23% rtc_iram_seg: 0 GB 8 KB 0.00% rtc_slow_seg: 0 GB 8 KB 0.00% IDT_LIST: 0 GB 8 KB 0.00% |
実行結果
冒頭でも紹介した下記デモ動画のように、ジェスチャー認識の結果をLCDに表示します。
USBシリアルからは詳細のログも確認できます。
|
1 2 3 4 5 6 7 8 9 10 |
[00:02:30.827,000] < inf> main: Data collection complete. Actual avg rate: 96.62 Hz (Target: 100 Hz) [00:02:30.827,000] <inf> main: Collecting 100 samples for the next inference... [00:02:30.827,000] <inf> main: --- Running inference on data window: 146.0s - 148.1s (Period: 1035 ms) --- [00:02:30.851,000] <inf> main: Predictions (DSP: 22 ms, Classification: 1 ms, Anomaly: 1 ms): [00:02:30.851,000] <inf> main: m5_flick: 0.00000 [00:02:30.851,000] <inf> main: m5_idle: 0.99609 [00:02:30.851,000] <inf> main: m5_knock: 0.00000 [00:02:30.851,000] <inf> main: m5_updown: 0.00000 [00:02:30.851,000] <inf> main: anomaly score: -0.077 |
CPU・スレッド負荷もモニタリングしてみました。
加速度センサのI2C自体がゆっくりなので、ほぼIdle状態でした。
(LVGLで文字・バーのアニメーションを追加するとguiが≒20%まで負荷高まりました。)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
--- 13 messages dropped --- : Total CPU cycles used: 706576083 input : STACK: unused 688 usage 336 / 1024 (32 %); CPU: 0 % : Total CPU cycles used: 3404 inference_tid : STACK: unused 6592 usage 1600 / 8192 (19 %); CPU: 2 % : Total CPU cycles used: 2601884922 gui_tid : STACK: unused 656 usage 3440 / 4096 (83 %); CPU: 2 % : Total CPU cycles used: 2422874564 shell_uart : STACK: unused 832 usage 1216 / 2048 (59 %); CPU: 0 % : Total CPU cycles used: 114105647 sysworkq : STACK: unused 688 usage 336 / 1024 (32 %); CPU: 0 % : Total CPU cycles used: 1408 logging : STACK: unused 544 usage 480 / 1024 (46 %); CPU: 0 % : Total CPU cycles used: 22199211 idle : STACK: unused 816 usage 208 / 1024 (20 %); CPU: 94 % : Total CPU cycles used: 102761967788 main : STACK: unused 7248 usage 944 / 8192 (11 %); CPU: 0 % : Total CPU cycles used: 2189198 ISR0 : STACK: unused 1600 usage 448 / 2048 (21 %) |
M5 Japan Tour 2026 Spring Nagoya
2026/4/27にM5 Japan Tour 2026 Spring Nagoyaが開催されました。
名古屋にあるSTATION Aiにて開催されました。Connpassのリンク先は下記です

●後日イベントの様子を記載します。
まとめ
M5Stack にZephyr(RTOS)とEdge Impulseを実装してみました。
内蔵の加速度センサを使って、ジェスチャー認識をさせています。
Zephyr(RTOS)でEdge AIっぽいテストをした内容を紹介しました。

コメント