技術約7分で読めます

StackChanの頭上タッチが触っていないのに反応し続けたので物理キーに戻した

いけさん目次

2026-09-27 追記: 部屋の空気情報(CO2・温湿度)を音声チャットに渡す新APIの検証と、頭上タッチ撫で誤反応の調査、感情に合わせた首振り動作の続編 → StackChanにCO2センサーをつないで部屋の空気情報を音声チャットに反映させた

前回は、StackChanの音声チャットをESP-IDFでビルドし直し、Tailscaleで音声サーバーへ直結した。
話しかけるきっかけは頭上タッチの叩きで、起動直後は手を触れていないのに叩きと判定されるため、起動後しばらく叩きを受け付けない「準備中」の状態を足していた。

翌日、起動から約22時間たったStackChanが、勝手に録音して返事をしゃべった。
誰も触っておらず、ログも取っていなかった。
誤判定は起動直後だけではなかったので、どこで発生しているのか切り分けてみた。

検証環境

項目使用した環境
実機M5Stack CoreS3(ESP32-S3)、StackChan Body(CoreS3を取り付けるロボット筐体)
頭上タッチBody上面の3ゾーン静電タッチ(静電容量式タッチセンサICのSi12T、CoreS3の内部I2Cに接続)
音声チャットのファームESP-IDF 5.5.4、arduino-esp32 3.3.10、M5Unified 0.2.17、StackChan-BSP 1.1.0
比較した公式ファームm5stack/StackChan の firmware(ESP-IDF 5.5.4)
置き場所机の上。周りに触れるものはない

録音が始まる経路は頭上タッチしかない

音声チャットのファームで録音を始めるのは、頭上タッチの叩きか、シリアルから送るテスト用のコマンドだけだった。
このときシリアルはつないでいない。
持ち上げて動かしても反応しないので、外から何かが触れている様子もなかった。

頭上タッチのチップが、触れていないのに「触れた」とCoreS3へ返していた。
叩きの判定は、3つのパッドの強さ(0〜3)の最大が3に届いたら、という条件にしていた。

接触ごとの状況を残す

強さ3の接触が出るたびに、時刻、起動からの経過、最後に顔を描き直してからの時間、首のサーボ・スピーカー・録音の状態、Wi-Fiの電波強度をログに出した。

項目準備中の17回準備中明けの14回
サーボが動いている11回5回
スピーカー・録音すべて止まっているすべて止まっている
描き直しからの時間42ms〜66秒でばらばらばらばら
電波強度-55前後-55前後

起動後に首を動かすのは、ホーム位置へ戻す1回だけのはずで、サーボが「動いている」と返す理由は分からなかった。
ほかの項目とも、時間の重なりは確認できなかった。

2回叩きでも見分けられない

誤判定と本人の入力を分けるため、1.5秒以内に2回叩いたら録音を始めるようにした。
1回目のあとは画面に「もう1回」と出す。

準備中が明けてから1分半で、「2回叩き」が4回成立して、4回とも録音まで進んだ。
誤判定は1回ずつ離れて来るのではなく、短い間隔でまとまって来る。
触れていないのに画面に「もう1回」が出続け、実用にならない。

頭上タッチでは録音を始めず、記録だけにすると、約10分で接触504回、うち強さ3が257回だった。

公式ファームは叩きを使っていない

公式ファームの頭上タッチの処理(hal_head_touch.cpp、head_pet.h)を確認した。

項目公式ファーム音声チャットのファーム
反応する操作撫でだけ。叩き1回には何も割り当てていない叩きで録音開始
センサーの省電力スキャン有効無効(軽い叩きを取りこぼすので切っていた)
基準の取り直ししないWi-Fi接続後、会話のあとなどで頻繁に
読み取りの間隔専用タスクで50msおきメインのループで約10msおき

撫では、3つのパッドの強さから重み付きの位置(-100〜100)を出し、触れ始めから40を超えて動いたら、という判定だった。
公式ドキュメントにも、上部のタッチ部分を縦にスワイプすると喜ぶとある。
感度(LOWのレベル3)と検出の設定は、こちらと同じだった。

Keyユニットで話しかける

叩く必要はないので、話しかけは物理スイッチに戻した。
以前使っていた1ボタンのボタンスイッチであるKeyユニット(U144)を、Body頭上のGroveポートに挿した。

StackChanのGroveポートは3つあり、公式の端子割り当て(PinMap)では PORT.A がG2/G1、PORT.B がG9/G8、PORT.C がG17/G18になっている。
本体横のPORT.AはCO2センサー用に空けておき、頭上のポートを使う。
以前のファームと同じく、Port B/Cの4ピンを見張って、最初に押されたピンをキーにする処理を戻すと、Port C(G18)と判定された。

区間実測
録音(話し始めまで1.3秒)4,132ms
送信(64,187バイト)295ms
返事の感情が届くまで4,035ms
1文目の音声のダウンロード(39,724バイト)186ms
1文目の再生開始7,869ms
会話の終わりまで11,726ms

頭上タッチの「2回叩き」の判定はこの間も出ていたが、記録だけにしていたため録音は始まらなかった。

ただ、頭上に挿したケーブルがまっすぐ上に出て、頭を撫でようとすると指に当たる。
L字のGroveケーブルは既製品で見つからず、「Grove L型」として売られているのは基板に付ける差し込み口だった(秋月電子、Seeed Studio)。
足元のUSB-CはCoreS3本体の給電とデータの端子なので、スイッチには回せなかった。

撫でだけ残しても誤判定が出る

叩きはやめて、撫でたときだけ喜ぶ顔を2.5秒出すようにした。
撫で判定でも誤判定が出るなら、タッチセンサー自体を使えない。

誰も撫でていないのに、約20分で撫での判定が40回以上出た。

この検証中、キーを押しても反応せず、顔が半目のまま固まる現象が起きた。
ログ収集用のPC側プログラムがシリアルポートを不正に閉じたことによるDTR/RTS信号の影響で、タッチセンサーの異常ではなかった。PC側のプログラムを直して検証を続けた。

公式と同じ設定と判定にする

省電力スキャンを有効に戻し、基準の取り直しをやめ、読み取りを50msおきにした。
それでも、会話のあとの約17分で、撫での判定26回、接触1,034回が出た。

撫での判定そのものも、公式のコードを移した。
すると、起動から約75秒で撫での判定が42回出て、ずっと喜んだ顔になった。
公式の判定は強さ1以上を接触とみなすので、触っていないのに各パッドが1〜2の値を出し続けると、重み付きの位置計算が変動し、そのまま撫での移動判定になっていた。
顔の反応は止めて、記録だけにした。

読み取るレジスタ、値の解釈、初期化の順序と値(感度、検出、省電力スキャンの設定)は、公式とすべて同じになっている。

公式ファームのタッチ処理だけを動かす

公式ファームをESP-IDF 5.5.4でビルドして書き込むと、「ID:(本体のMACアドレス)」「Look for me in the app to start setup.」の画面から進まなかった。
スマホの公式アプリでWi-Fiを設定するまで、撫でに反応する顔の画面は出なかった。

手元のコピーの main.cpp だけを書き換え、電源やI2C、頭上タッチの読み取りタスクまでは公式のまま起動し、撫でと接触の回数を1分ごとにログへ出すようにした。
書き込む前に、Tailscaleの鍵が入っている本体の設定領域(NVS: 不揮発性ストレージ)をバックアップした。

時間接触撫で
音声チャットのファーム(公式と同じ設定)約17分1,034回26回
公式のコード20分0回0回

0回が読み取れていないだけでないことを確かめるため、撫でてもらうと3回とも取れた。
叩きは7回中5回で、1回は撫でと判定された。
省電力スキャンでは読み取りが約200msおきになり、短い叩きは取りこぼしていた。
叩いた指がパッドの上でずれると、位置が動いて撫でになっていた。
公式が撫でにしか反応しないのも、このためかもしれない。

何を止めても消えない

音声チャットのファームのほうで、動いているものを1つずつ止め、1分ごとの接触回数を比べた。

止めたもの1分ごとの接触
なし62、77
本体の更新処理(M5.update)53、27、48、11
サーボの力54、26、60
Wi-Fiの送信出力(20dBm→2dBm)63、28、63
スピーカー69、69、70
顔の描き直し75、68、64

I2Cの読み取りの失敗は0回で、チップが本当に「触れた」と返していた。
どれを止めても、その場では消えなかった。

誤判定には波があり、起動によって1分に55〜80回出るときも、最初から0回のときもあった。
ある起動では、約7分後から急に0回になり、止めたもの(バックライト)を戻しても0回のままだった。

公式ファームを一晩動かす

公式の20分で0回も、たまたま静かな時間に当たっただけかもしれない。
公式のタッチ処理だけを動かす版で、20:39から0:31まで、約3時間50分記録した。

時間接触撫で
公式のコード約3時間50分4回3回
音声チャットのファーム(多い時間帯)1分数十回十数回

公式でも、誰も触っていないのに1時間に1回ほど撫でが出た。
センサーは完全に静かになるわけではなく、音声チャットのファームでは、それが桁違いに増える時間帯があった。
何が増やしているのかは、まだ分かっていない。

話しかけはKeyユニットに任せ、頭上タッチは叩きも撫でも記録だけにしている。