作ったもの
M5StackのStack-chanを土台に、サマターゲの顔で反応し、話しかけると会話やエアコン操作ができるデスクトップロボットを作っています。
重要だったのは、公式ファームを別物へ置き換えないことでした。マイク、スピーカー、タッチ、カメラ、サーボ、Wi-Fi、瞬き、視線、発話アニメーションの経路を残し、サマターゲ固有の処理を薄い統合層として追加しています。
既存機能を残したまま、机の上のキャラクターを家電操作端末へ。
変更範囲を小さく保つための設計記録です。
M5StackのStack-chanを土台に、サマターゲの顔で反応し、話しかけると会話やエアコン操作ができるデスクトップロボットを作っています。
重要だったのは、公式ファームを別物へ置き換えないことでした。マイク、スピーカー、タッチ、カメラ、サーボ、Wi-Fi、瞬き、視線、発話アニメーションの経路を残し、サマターゲ固有の処理を薄い統合層として追加しています。
Stack-chanの画面は320×240です。Web版の絵を縮小すると細部が読めなくなるため、サマターゲの特徴を次の四つへ絞りました。
公式の小さな目全体を動かす処理から、固定した目の中で瞳だけを動かす構成へ変更しました。ただし、呼吸、瞬き、頭をなでた反応、IMUによる傾きは既存のmodifierをそのまま登録しています。
感情を切り替えた直後、瞬き処理が変更前の目の状態へ戻す問題がありました。感情変更時に瞬き側の基準値も同期することで、二つのアニメーションが同じ部品を奪い合わないようにしています。
現在の構成では、「サマターゲ」と毎回呼ぶ必要はありません。本体はローカルの音声フロントエンドで、一定時間続く発話だけを検出します。発話があったときだけ所有者のVPSへ一つのセッションを開き、処理後はローカル検出へ戻ります。部屋の音を常時VPSへ流し続ける構成ではありません。
日本語の文字起こしはVPS上の faster-whisper で行います。処理先を区別しました。
APIキーは本体にもGitHubにも置かず、VPSのサービス用環境ファイルだけに保存します。
エアコンの赤外線信号は、短いオン・オフを正しい長さで並べる必要があります。CPUの待機だけで波形を作ると、Wi-Fiや音声タスクの割り込みでタイミングが伸びる可能性があります。
そこで、DAIKIN312形式のフレームをESP32-S3のRMT symbolへ先に変換し、搬送波を含む一つのDMAバッファとして送ります。実装した操作は、自動、冷房、暖房、停止、温度上げ、温度下げの6種類です。
RMTの1 symbolに入らない長い区間は、CPUで待たず、Lowのsymbolを複数へ分けます。1回の命令につき赤外線フレームは1回だけ送信し、同じ操作が二重に実行されないようコマンドIDも確認します。
スマートフォンから操作するときも、Stack-chanや自宅ルーターへ外部から直接接続しません。認証付きのVPSキューへスマートフォンが命令を登録し、本体が外向きHTTPSで定期確認します。
管理画面、本体ポーリング、音声セッションには別々のトークンを使います。命令にはUUIDと作成時刻を付け、本体は古すぎる命令と直前に実行したIDを拒否します。これにより、再読込や通信再試行で同じ赤外線が繰り返し出る可能性を下げます。
音声処理中にTLS接続を始めると音が途切れる可能性があるため、遠隔操作のポーリングは本体がidleになってから行います。
全面的に書き直す方が、最初は速く見えます。しかし、カメラ、タッチ、サーボ、音声、OTAなどを同じ品質で作り直す必要が生まれます。今回は次の境界を決めたことで、公式機能を利用しながら独自部分を追えました。
キャラクターを追加することより、既存のライフサイクルを壊さない境界を探すことの方が、この実装では大きな作業でした。