Skip to content

🧬 内部構造・ハードウェア仕様書

スタックちゃん(Donack)システムを構成する各ハードのスペック対応可能な範囲、 モジュール間の通信経路を 1 枚に集約した技術リファレンス。

このドキュメントの目的

「Module-LLM の TTS はどこまでできる?」「CoreS3 と Module-LLM は何で繋がってる?」 「なぜ母艦 PC に物理接続している?」といった調査のたびに散らばったナレッジを読み直す無駄を なくすための単一の出典 (single source of truth)。数値の確度は次の記号で示す:

  • ✅ 実機で確認済 / コード・ログに裏付けあり
  • 📕 公称スペック(メーカー資料ベース・実測ではない)
  • ⚠️ 未確認 / 推定(実機で要検証)

0. 現行本番構成 (2026-07-14 実機検証済み) ★最新

過去節 (§0.1〜) の図は経緯を含むため、いま動いている構成の要点をここに集約する。 応答ルートの図解と実装記録は LT実装記録 (2026-07)、 図の実体は docs/public/images/voice-route-2026-07.svg / phantom-defense-2026-07.svg (LTスライド流用可)。

[スタックちゃん本体]
  聞く: CoreS3 ES7210マイク ──UDP(WiFi)──▶ Module-LLM 注入器 → VAD(0.70) → whisper-base(NPU)
        専用FreeRTOSタスク20ms / 自己発話は実再生フラグ(/tmp/koko_playing)でゼロ埋め / 幻聴5層防御
        wake「ねえドナック」→ 即「はい、聞いてますよ」(0ms事前PCM) + 傾聴窓15s
  話す: CoreS3 が agent.delta を文境界チャンク化 (delta後25〜142msで送出)
        → HTTP /say?async=1 → Module-LLM 常駐 Kokoro(:8900, jf_alpha) がキュー直列・重畳合成
        melotts(UART) は Kokoro 不達時のフォールバック
     │ WSS (Tailscale Funnel /stackchan/ws)
[Mac Studio] bridge :7780  DEFAULT_BACKEND=jcarvis / TTS_ENGINE=none / wake句ゲート
     │ HTTP/SSE
[JCARVIS :8185] CommanderEngine (JCARVIS#324)
  ├─ Gemma4(E4B, ollama常駐, keep_alive=-1) が1コールで難易度分類+生成 {"difficulty","text"}
  ├─ easy → そのまま回答 — Agent SDK 不使用・課金ゼロ・1〜2秒で発話開始
  └─ hard → Donack人格フィラー即答 → Agent SDK(Claude) が非同期で正式推論 →
            push.js speak (bridge MCP) で100字以内の話し言葉を音声プッシュ (JCARVIS#328)
項目現行値備考
マイクCoreS3 ES7210 → UDP → pcm-inject-udp.servicepio env m5stack-cores3-micstream (#116)。AMIC 復帰手順は mac-studio/scripts/module-llm-audio-inject/README.md
マイク切替✅ firmware が毎ブート検証ゲート付き自動ダンス/mic/release→setup→/mic/status 購読確認→/mic/takeover。失敗時 AMIC 自動フォールバック
発話(TTS)Module-LLM 常駐 Kokoro :8900 文境界チャンク重畳 (#132/#133)フィラー/相槌は事前レンダPCM=0ms。-DKOKORO_CHUNK_TTS=0 で旧一括
自己発話対策✅ 注入器が実再生フラグでゼロ埋め (#133)firmware 推定ガードは目安に格下げ → 発話後 ~0.4-1s で受付復帰
幻聴対策✅ VAD閾値0.70 + firmware3層 + bridge + jcarvis 自己防衛 (#150)whisper no_speech_prob は NPU バイナリ未実装 (改造案は #150 に記録)
頭脳✅ JCARVIS CommanderEngine (Gemma4 司令官, JCARVIS#324)easy はローカル完結。hard のみ Agent SDK (サブスクOAuth)。5s タイムアウトで SDK 直行
旧構成 (§0.1) からの主変化AMIC→CoreS3 マイク / melotts→Kokoro / 全問SDK→Gemma4 先鋒旧 #76「AMIC 品質ブロッカー」はマイク乗り換えで解消

0.1. 旧・本番構成 (2026-06-18 時点, 経緯参照用)

当時動いていた構成の要点。§0 に置き換え済み (マイク/TTS/頭脳ルートが変更)。

[スタックちゃん本体]  ねえドナック→ASR(whisper)→wake判定はbridge側
  CoreS3 ── UART ── Module-LLM(AX630C)        発話: Module-LLM 単体 on-device melotts(UART)
     │  Wi-Fi(iPhoneテザリング otani_iPhone15P)        ※VOICEVOX/adb 不使用
     ▼  WSS (Tailscale Funnel /stackchan/ws)
[Mac Studio: takehiromac-studio]
  bridge :7780   DEFAULT_BACKEND=jcarvis / TTS_ENGINE=none / WAKE_PHRASES(日本語)
     │ HTTP/SSE
  JCARVIS :8185 (※:8181はevan-live-translateのwhisper-serverが占有→8185で運用)
     │ Claude Agent SDK = サブスクOAuth (ANTHROPIC_API_KEY未使用=従量課金なし)
     ├─ 応答: Donackペルソナ注入 + 音声は簡潔(100字)・詳細はDiscordスレッド
     ├─ skill: weather(Open-Meteo,APIキー不要,IP位置推定+地名) / task / report / issue-notify
     └─ Discord webhook ミラー(どなっくチャンネル: 会話 + 詳細解説)
項目現行値備考
頭脳ルーティングbridge DEFAULT_BACKEND=jcarvisclaude だと bridge内蔵Haikuに行き JCARVIS を素通り(要注意)
発話(TTS)bridge TTS_ENGINE=none → CoreS3 on-device melotts(UART)VOICEVOX 不要。voicevox/melotts(adb) はデバッグ用代替
JCARVIS ポート:8185:8181 はポート競合。bridge .env JCARVIS_ENDPOINT=…:8185/agent
Claude 認証サブスク(Claude Code OAuth)DONACK_ENGINE=claude 必須(未設定でEchoEngine=オウム返し)
端末接続先wss://takehiromac-studio.tail3ab66f.ts.net/stackchan/wsplatformio.ini build flag
Wi-Fi複数プロファイル+優先度(#27)。primary=iPhoneテザリングserial wifi:/wifi-add:

既知の未解決 (前提依存)

マイク音声入力品質 (#76): WSS〜発話は全て正常だが、AMIC の信号品質が低く whisper が日本語発話を [音楽] と誤認識し wake が成立しない (gain 70/100/120/ALC いずれも改善せず)。voice 入力に依存する機能 (連続会話セッション等) の前提ブロッカー。claude: シリアル投入経路はマイクを介さず完全動作する。

運用手順は demo-runbook-2026-06-18 を参照。


1. システム全体図

現行の本番構成(ハイブリッド: ASR=Module-LLM / LLM=Claude / TTS=VOICEVOX or melotts)。

┌──────────────────────────── スタックちゃん本体 (Donack) ────────────────────────────┐
│                                                                                      │
│   ┌─────────────────────────┐         UART 115200bps          ┌──────────────────┐   │
│   │  M5Stack CoreS3 (K151)  │◀────────(StackFlow/M5lib)───────▶│  Module-LLM      │   │
│   │  「指揮者」ESP32-S3      │   RX=GPIO18 / TX=GPIO17          │  「言語脳」AX630C │   │
│   │  ・状態機械 / LCD / Avatar│                                  │  ・マイク(PDM)    │   │
│   │  ・スピーカー(I2S)        │                                  │  ・KWS/VAD        │   │
│   │  ・Wi-Fi (2.4GHz)        │                                  │  ・Whisper ASR    │   │
│   │  ・サーボ / センサ統合    │                                  │  ・(LLM/TTS は予備)│  │
│   └───────────┬─────────────┘                                  └────────┬─────────┘   │
│               │ Wi-Fi / Tailscale Funnel (WSS)                          │ USB-C        │
└───────────────┼─────────────────────────────────────────────────────── │ (ADB/RNDIS) ─┘
                │                                                          │ ※デバッグ/現状の発話経路
                ▼                                                          ▼
   ┌────────────────────────── Mac Studio (母艦 / 常時起動ホスト) ──────────────────────┐
   │  bridge :7780 (WSS) ── Backend Router ── JCARVIS :8181 (Claude サブスク)            │
   │       │ TTS_ENGINE=voicevox → VOICEVOX(満別花丸) → PCM を WSS で CoreS3 へ          │
   │       │ TTS_ENGINE=melotts  → adb forward :5055 → Module-LLM の melotts_server.py   │
   │  MCP  :8787                                                                         │
   └────────────────────────────────────────────────────────────────────────────────────┘

訂正 (2026-06-20, #111): 旧記述「Module-LLM の IP 到達手段は USB-ADB のみ」は不正確。 現状 eth0NO-CARRIER(リンク無し)なだけで、Module-LLM(AX630C) は ADB / UART / SSH / Ethernet / USB WiFi ドングルで IP 到達できる:

  • WiFi: USB-C ハブ越しに USB ドングル(例 TL-WN725N / RTL8188EU)→ wlan0 → 同一網へ。USB は OTG ホスト切替対応。
  • Ethernet: LLM Debug Board の RJ45(100M)に LAN を挿すと eth0 自動 UP。
  • SSH: 上記でIP取得後 ssh root@<ip>(user=root / pass=123456)。

→ Module-LLM を iPhone テザリング網に載せれば bridge に IP 直結でき、melotts standalone(§6) や 話者照合のクラウド側実装(#108) の選択肢が開ける。詳細・PoC は #111。 (現行デモ構成では引き続き USB-ADB を使用。Wi-Fi をネイティブに持つのは CoreS3 のみ。)


2. ハードウェア仕様

2.1 M5Stack CoreS3 (K151) — 「指揮者」

項目仕様確度
SoCESP32-S3 (Xtensa LX7 デュアルコア @240MHz)📕
Flash / PSRAM16MB Flash / 8MB PSRAM (QSPI)📕
無線Wi-Fi 802.11 b/g/n 2.4GHz のみ / BLE 5.0📕
ディスプレイ2.0" 320×240 IPS (ILI9342C) + 静電容量タッチ📕 / ✅(LCD 320×240)
スピーカーI2S → AW88298 アンプ(顔から音が出る)📕
マイクデュアル (ES7210 ADC) ※本構成では未使用(Module-LLM のマイクが主役)📕
カメラGC0308 0.3MP(未使用)📕
IMU / PMICBMI270 6軸 / AXP2101📕
拡張microSD / USB-C / M-Bus / GROVE (Bottom3 経由)📕
役割状態機械・Avatar 表示・Wi-Fi/WSS クライアント・スピーカー再生・センサ統合

ピン割当(このプロジェクト)firmware/include/stackchan_config.h:

用途ピン
Module-LLM UARTRX=GPIO18 / TX=GPIO17baud 115200
Bottom3 Port.A (I2C)SDA=12 / SCL=11TMOS PIR(0x5A) / ToF(0x29)
Bottom3 Port.B (GPIO)OUT=8 / IN=9Unit IR
Bottom3 Port.C (UART)RX=7 / TX=6Unit MIDI
WSS heartbeatping 15s / pong timeout 30s ✅

2.2 Module-LLM (LLM630 / AX630C) — 「言語脳」

項目仕様確度
SoCAxera AX630C📕
CPUデュアル Arm Cortex-A53 (~1.2GHz)📕
NPU公称 3.2 TOPS @INT8(INT4 で 12.8 TOPS 相当)📕
メモリLPDDR4 4GB / eMMC 32GB📕 ⚠️実機要確認
OSUbuntu (aarch64, jammy) + M5Stack StackFlow フレームワーク
ネットワークeth0 = NO-CARRIER(Wi-Fi/有線とも実質不通)
IP 到達手段USB-C OTG 経由の ADB / RNDIS のみ
マイクPDM(本システムの主入力)
スピーカーALSA card0、再生 pcmC0D1p / 録音 pcmC0D0c(別サブデバイス=同時可)
音声再生制約AO コーデックは 48kHz / stereo / 16bit のみ通る(44.1k/mono は失敗)
NPU メモリCMM 予約。LLM skip で +307MB 確保しても melotts crash は別要因
エンジンpyaxengine が /opt/lib/libax_engine.so を ctypes で呼ぶ
役割(現行)マイク + KWS + VAD + Whisper ASR(ja)。LLM/TTS は予備(理由は §4 / §6)

USB-C の二重用途による干渉

Module-LLM body の USB-C は ADB と StackFlow UART が同居しており、 ADB 接続中は CoreS3↔Module-LLM の UART 通信が不安定になることがある(要追加検証 ⚠️)。

2.3 センサ / アクチュエータ Unit

詳細・在庫は パーツ資産管理 を参照。要点のみ:

Unit型番接続アドレス/ピン
TMOS PIR (人感)U185 / STHS34PF80I2C0x5A
ToF 測距U010 / VL53L0XI2C0x29
ENV-Pro (温湿度/気圧/空気質)U169 / BME688I2C0x76
DLight (環境光)U094I2C0x23
Unit IRU002GPIOPort.B
Unit MIDIU098UARTPort.C

2.4 将来の重思考プラットフォーム(未導入)

機材スペック想定役割
Raspberry Pi 5 (16GB)高性能ローカル LLM サーバ候補
AI HAT+ 2 (Hailo)NPU 26 TOPSWhisper / Qwen / Llama 高速実行 → Backend Router の local

3. 通信トランスポート・マトリクス

システム内に3 系統の通信経路が同居する。どれが何に使われ、standalone(PC 非接続)運用で 生き残るかを整理する。

経路物理プロトコル用途帯域/速度standalone 可否
A. CoreS3 ↔ Module-LLMUART (GPIO17/18)M5Module-LLM lib / StackFlow JSONKWS/VAD/Whisper(ASR) 結果の授受、本来は LLM/TTS も115200 bps ✅✅ 完全ローカル
B. CoreS3 ↔ bridgeWi-Fi (2.4GHz)WSS (/ws) / プロトコル v0.4ASR テキスト→頭脳、応答テキスト/PCM、状態Wi-Fi 依存△ Wi-Fi のみで可(bridge は遠隔/クラウドでよい)
C. bridge ↔ Module-LLM melottsUSB-C (ADB)TCP :5055(adb forward)melotts へ発話テキストを投入localhostPC 物理接続必須

standalone を阻む唯一の経路は C

A・B だけなら「Wi-Fi さえあれば本体単独」で動く(ASR はローカル、頭脳は Wi-Fi 先)。 C(melotts 発話)だけが USB-ADB に依存しており、これが §6 の本質的課題。


4. ソフトウェアスタック

4.1 Module-LLM 側 StackFlow デーモン(日本語化 install 後)

mac-studio/scripts/module-llm-install-japanese.sh でオフライン install(M5 公式 apt repo repo.llm.m5stack.com、Module-LLM はネット不通なので Mac で deb 取得→adb push→dpkg)。

デーモン出荷時install 後備考
lib-llm1.61.8基底ライブラリ
llm-sys1.31.6
llm-audio(稼働)ALSA 管理。止めずに別サブデバイスで再生可
llm-asr1.31.7
llm-kws1.31.8wake word
llm-vad無し1.8新規
llm-llm1.31.8
llm-melotts1.31.8⚠️ ja-jp で crash(§5)
llm-whisper無し1.8新規

4.2 モデルパッケージ

パッケージ用途状態
llm-model-whisper-tinywhisper-base0.4日本語 multilingual ASR(tiny→base で精度改善 #64)✅ 使用中
llm-model-silero-vad0.4VAD
llm-model-sherpa-onnx-kws-...gigaspeech-3.3M0.3英語 KWS("HELLO")
llm-model-melotts-ja-jp0.6日本語 TTS(StackFlow 経路)⚠️ crash(§5)
tinyswallow-1.5b-ax630c (kinneko)1.0.0日本語 LLM 2GB⚪ install 済・未使用(推論 2 分超で実用外)

データ配置(device): /opt/m5stack/data/(モデル)、/opt/m5stack/data/melotts-ja-jp/(ja-jp FST 等)。

4.3 melotts.axera Python ランタイム(オンデバイス TTS の代替経路)

StackFlow の melotts が使えないため導入した別経路(mac-studio/scripts/melotts-onboard/)。

  • 配置: /opt/melotts-py/python/(コード)、/opt/melotts-rt(numpy 等 wheel)、/opt/lib(axengine)
  • モデルは ja-jp パッケージ内の既存ファイルを再利用: encoder-jp.ort / decoder-jp.axmodel / g-jp.bin
  • 常駐サーバ melotts_server.py(TCP :5055)。起動時にモデル+MeCab 辞書を 1 回ロード、間つなぎを事前キャッシュ
  • 日本語正規化は MeCab + pykakasi + tokenizers(自前 G2P。BERT/torch・soundfile は不要)

4.4 Mac Studio 側

サービスポート役割
bridge (mac-studio/bridge)WSS :7780 / MCP :8787WSS サーバ、Backend Router(既定=jcarvis)、wake/エコー判定、WS keepalive、TTS_ENGINE=none(発話は端末委譲)
JCARVIS:8185 (:8181競合回避)Claude(サブスクOAuth)応答 + Donackペルソナ注入 + weather/task/report skill + Discord/Slackミラー(会話+詳細スレッド)
VOICEVOX満別花丸ボイス合成(TTS_ENGINE=voicevox 時のみ=デバッグ用代替。現行は未使用)

起動運用(mac-studio/ops/

bridge / JCARVIS は mac-studio/ops/stackchan-backend.sh {start|stop|restart|status} で起動/停止する。 node は nvm 経由(v24.14.1)で非対話シェルの PATH に載らないため、スクリプトが node と claude CLI のパスを明示し、起動 env を runbook 準拠で内包、Discord webhook は起動時に Keychain から解決する (値をファイルに残さない)。ポート稼働中は start をスキップして二重起動を防ぐ。

  • 自動起動: mac-studio/ops/install-autostart.sh で、ログイン項目アプリ (~/Applications/StackchanBackend.app) と ~/.zprofile 保険ブロックの 2 経路を仕込む。 どちらも Terminal の既存アクセス権を利用し、フルディスクアクセス(FDA)を付与しない。
  • launchd/cron 不採用: コードが外部SSD /Volumes/AIWorkSSD にあり、launchd 起動プロセスは TCC により外部SSDを読めず(Operation not permitted)、回避に FDA が必要になるため。 Terminal は既定で外部SSDにアクセスできるので Terminal 経由で起動する。
  • 詳細手順: mac-studio/ops/README.md

5. 音声出力(TTS)2 経路の比較 — ★task A の調査対象

オンデバイス日本語 TTS には理論上 2 経路ある。現状動くのは ② だけ。

① StackFlow llm-melotts 経路② melotts.axera Python 経路
実行主体C++ デーモン llm-melotts 1.8device Ubuntu 上の Python
呼び出しCoreS3 → UART → StackFlow(理想形)Module-LLM 内で直接(TCP :5055)
日本語正規化WeTextProcessing (FST _tn_/_itn_)MeCab + pykakasi
PC 物理接続不要(UART のみ=standalone 可)現状 adb 必須(§6)
現状ja-jp で ABRT クラッシュ✅ 発話成功

5.1 ① がクラッシュする既知の事実(#67, 2026-05-28 ✅)

-DSKIP_MELOTTS_SETUP=0 で焼くと melotts setup が work_id を返さず、device の llm-melotts ログに:

FstHeader::Read: Bad FST header: /opt/m5stack/data/melotts-ja-jp/
F [wetext_processor.cc:36] Invalid fst prefix, prefix should contain either "_tn_" or "_itn_"
code=killed, status=6/ABRT

判明していること:

  • /opt/m5stack/data/melotts-ja-jp/ja_tn_tagger.fst / ja_tn_verbalizer.fst存在し命名も正しい_tn_ を含む)
  • それでもデーモンがディレクトリパス自体を FST として読もうとして失敗している
  • NPU メモリ不足ではない(LLM skip で 307MB 空けても crash)
  • daemon 1.8 と ja-jp 0.6 の組み合わせの不整合と推定

5.2 task A(StackFlow melotts 修正)の調査ステップ案

いずれも最終確認は実機 + ADB が必要。実機なしでは「仮説と手順の用意」まで。

  1. 設定パスの特定: llm-melotts の設定(モデルディレクトリの指定方法)を確認。デーモンが melotts-ja-jp/FST ファイルとして渡されているのか、内部で結合する prefix が誤っているのか。 → device 上 /opt/m5stack/data/melotts-ja-jp/ の config(json) と、デーモンが期待するキーを照合。
  2. バージョン整合の検証: ja-jp 0.6 と daemon 1.8 が公式に対応する組み合わせか M5 repo の メタ(pool/jammy/ax630c/v1.8/, v0.6/)を確認。別版(ja-jp 別マイナー / daemon 別版)の有無を調査。
  3. WeTextProcessing の FST 期待形: _tn_tagger / _tn_verbalizerファイル名 prefixを デーモンがどう解決するか。シンボリックリンク or rename で _tn_/_itn_ prefix を満たせば通る可能性。
  4. 回避策の優先比較: ① 修正が困難なら §6 案 B(device 側 UART→melotts.axera リレー)に切替。

6. standalone(PC 非接続)運用の現状と到達条件

ユーザー要望: 「デバッグ時のみ PC 接続、通常は本体単独(Wi-Fi のみ)で動く」

6.1 現状の standalone 度合い

機能PC 不要で動く?理由
マイク → KWS/VAD/ASR✅ デバイス単独Module-LLM 内 + UART、PC 不要
ASR → 頭脳(Claude)△ Wi-Fi のみで可CoreS3 が WSS で bridge に到達。bridge は遠隔/クラウドでよい(物理接続不要)
本答 → 発話(melotts)PC(adb) 必須§3 経路 C。Module-LLM に IP が無く、TTS が非 StackFlow な TCP プロセスのため

結論: TTS 出力経路だけが PC 物理接続に依存しており、まだ完全 standalone ではない。

6.2 到達条件(案)

  • 案 A(本命・このタスク): §5 の StackFlow llm-melotts ja-jp crash を修正 → SKIP_MELOTTS_SETUP=0 で焼けば CoreS3 → UART → Module-LLM 発話が復活し、Python・adb 不要。 Python 経路はデバッグ専用に降格。リスク: crash の根が深く #67 で「ライブラリ経路では現状回避困難」。
  • 案 B(次善): melotts.axera Python サーバを残し、device 側に UART→TCP(:5055) リレーを置く。 CoreS3 が WSS で受けた本答を UART で送る → device リレー → melotts。adb 不要・Wi-Fi のみで standalone。 課題: UART は StackFlow が使用中 → 空き UART / 多重化の確保。

7. ナレッジの整合(過去の食い違いの解消)

melotts の StackFlow 経路について過去ドキュメント間で矛盾があったため明記する:

ドキュメント記述実態
module-llm-japanese-pipeline(#50, 05-25)「daemon 1.8 + ja-jp 0.6 で正しく日本語発話 ✅」❌ これは期待値("期待される動作" 節)であり実機未達
hybrid-asr-claude-voicevox(#52)実測ログ「try melotts model=… ← 失敗するが使わない✅ melotts setup は失敗していた
module-llm-onboard-melotts(#67, 05-28)「ja-jp で FST crash(ABRT)」✅ 失敗の原因を特定

: StackFlow llm-melotts 1.8 + ja-jp 0.6 は ja-jp 発話に未到達(FST crash)。 現状オンデバイス日本語発話は melotts.axera Python 経路でのみ成立する。


8. 関連ドキュメント

aieo-product / stack-chan project