M5Stack Core S3などで、音声認識ライブラリESP-SRを使う

tl;dr

  • ESP-SRはESP32でウェイクアップワードと命令認識が使えるEspressif社のライブラリです
  • ESP-SRに"Hi! StackChan"というウェイクアップワードが含まれており、スタックチャン製作に活用できます
  • M5UnifiedでESP-SRが使えるようにライブラリを作りました

すぐに使いたい人はこの記事を読まずに、以下のライブラリのページを見て、導入手順を読んで導入してみてください。

github.com

経緯

過去にスマホから家電を操作できるスマートホームを作っていましたが、お家の中で気軽に使えるAIエージェントが欲しくなりました。 M5Stack公式スタックチャンが発売されるにあたり、スタックチャンをスマートホームAIエージェントにしたら面白くて便利そうと思いました。 そのために、ESP32上で動作するウェイクアップワード技術を調べていたところ、EspressifからESP32向けの音声認識エンジンESP-SRを見つけました。

スタックチャンで利用したM5Stack CoreS3は、ESP32-S3を搭載したコアモジュールです。 Core2からマイクが搭載されるようになりましたが、CoreS3から本体に載るようになり、マイクを利用しやすくなりました。 なお、CoreS3には、CoreS3、CoreS3 SE、CoreS3 Liteの3種類がありますが、どれにもマイクが搭載されています。 私はCoreS3 SEを使いました。

M5Stack CoreS3 SEwww.switch-science.com

ESP-SRとは

ESP-SRとは、Espressif社が提供しているESP32上で動作する音声認識ライブラリです。Espressif社がAIプロダクト開発に便利なように提供してくれているようです。

github.com

ノイズキャンセルなどの機能を持っており、結構しっかりと作られています。

  • エコーキャンセル
  • ノイズキャンセル
  • 音声アクティビティ検出
  • 自動ゲイン制御
  • ウェイクワード検出エンジン
  • 音声コマンド検出エンジン

ウェイクアップワード検出の利用には、任意のウェイクアップワードを認識するわけではなく、モデルが必要です。 リポジトリのREADMEにありますが、「Hi,ESP」など多数のモデルが公開されています。 その中に「Hi, Stack Chan」が含まれています。

スタックチャン製作にはこれを使わない手はないと思い、試してみました。

なお、ESP-SRのウェイクアップワード自体はESP32-S3以外のESP32でも動作しますが、ESP32のArduinoライブラリにESP32-S3、ESP32-P4でのみ有効になるように作られています。私のテストではESP32-S3である、CoreS3、Atom S3R+Atomic Echo Base、Atom EchoS3Rでのみ動作しました。

モデルファイル

ESP-SRでは、srmodels.binというモデルファイルを作成し、それをmodelsパーティションに入れ、それを読み込んで動作します。 モデルファイルは、esp32-arduinoにも含まれていますが、こちらは「Hi,ESP」と英語コマンドのモデルが入っていました。 「Hi,Stack Chan」を動かしたい場合、srmodels.binを作る必要があります。

このファイルを作成する方法は、以下のリポジトリに記載してあります。 こちらを参照してください。

github.com

esp32-arduinoにはESP-SR用のパーティションファイルが作られています。 このパーティションファイルを使うと適用できます。

github.com

パーティションにsrmodels.binを書き込むには以下のように、ファームウェアアップロードに追加でコマンドを実行する必要があります。

esptool.py --chip esp32s3 --port "/dev/cu.usbmodem114401" --baud 1500000 write_flash 0xd10000 "srmodels.bin"

ArduinoのESP-SRライブラリを使おうとしたが、よく分からなかった

esp32-arduinoに付属するESP-SRライブラリを使おうとしました。 このライブラリでは、I2Sを操作する部分もライブラリに含まれていました。

私の場合、I2Sを操作する部分はM5Unifiedの機能を使いたいと思っていました。 それと組み合わせる方法が、私にはできませんでした。

M5Unifiedのマイクから得たバイナリを渡すように変更

esp32-arduinoに含まれるESP-SRライブラリを変更し、ESP-SRライブラリからはI2Sを操作せず、音声データのバイナリだけを渡すようにすれば、I2Sの制御で競合せずに動くのではないかと思いました。

M5UnifiedではM5.Mic.record()でint16_tの配列データの形でデータが手に入ります。

#define AUDIO_SAMPLE_SIZE 256

void loop() {
  M5.update();

  // 音声の取得
  static int16_t audio_buf[AUDIO_SAMPLE_SIZE * 2];
  bool ok = M5.Mic.record(audio_buf, AUDIO_SAMPLE_SIZE, 16000, true);
}

その方法で実装し、試行錯誤したところ、無事動くようになりました。

最後にハマっていたのは、ESP-SR側のモノラル指定の仕方のあたりでした。

英語のコマンドも動きました。

英語のコマンドは以下のように、命令を作っておくと、検出してくれます。

static const sr_cmd_t sr_commands[] = {
    {0, "Turn on the light", "TkN nN jc LiT"},
    {0, "Switch on the light", "SWgp nN jc LiT"},
    {1, "Turn off the light", "TkN eF jc LiT"},
    {1, "Switch off the light", "SWgp eF jc LiT"},
    {1, "Go dark", "Gb DnRK"},
    {2, "Start fan", "STnRT FaN"},
    {3, "Stop fan", "STnP FaN"},
};

配列の3つ目の要素であるphonemeは、以下のpythonスクリプトで生成できるようです。

github.com

ライブラリ化

M5Unifiedで動いた実装を、他でも使えるようにライブラリ化しました。

github.com

このライブラリでは、PlatformIOと、Arduino IDEでの利用方法を載せています。 日本語用のドキュメントも用意したので、使ってみたい方はこちらを参照して使ってみてください。

github.com

なお、PlatformIOを使う場合、PlatformIO公式のESP32 Platform はesp32-arduinoの更新が2系で止まっているため、3系がメンテナンスされているpioarduino/platform-espressif32 を使う必要がありました。設定方法はライブラリのドキュメントに記載しています。

Atom S3R+Atomic Echo Base、Atom EchoS3Rでも動作確認した

M5Stack CoreS3で動作を確認しましたが、同じくPSRAM付きのESP32-S3を搭載したAtom S3R+Atomic Echo Baseの組み合わせと、Atom EchoS3Rでも動作を確認しました。

Atom Echo S3R - スマートスピーカー開発キットwww.switch-science.com

ATOMS3R AI Chatbotキット(8 MB PSRAM)www.switch-science.com

ただし、AtomS3RはFLASHが8MBと、CoreS3の16MBの半分しかありません。 ESP-SR用のパーティションはFLASH 16MB用しか提供されておらず、自作しました。

github.com

イベント会場で使ってみた

第三回スイッチサイエンス大感謝祭というイベントに参加し、その時にESP-SRの機能を付けたスタックチャンを見せていました。 ある程度騒がしい会場でしたが、ウェイクアップワードは動作していました。

ぜひ使ってみてください

ぜひ音声で認識するスタックチャンを作ってみたいならば、便利なので使っていきましょう!

2026年4月に開催される技術書典20では、スタックチャンでスマートホーム音声AIエージェントを作った技術についての解説、製作記となる本を作ろうと思います。現在鋭意製作&執筆中です。

techbookfest.org

カインズ工房でレーザー加工機を使って自作キーボード用のプレートを作成した 2026

tl;dt

  • カインズ工房ではレーザー加工機を使って自作キーボード用のプレートを作成できます
  • 利用条件にAdobe Illustratorで作成したデータが必要ですが、無料で利用できるInkscapeでも問題なく作成できました
  • 前に利用したときと制御ソフトウェアが変わっていました
  • いろいろはまりポイントがありますが、この記事にまとめました

自作キーボードでのアクリルでのプレート製作

遊舎工房さんなどのレーザーカットサービスを使って、アクリルをカットして自作キーボードのプレートを作ることがよく行われます。私自身も遊舎工房さんのサービスを利用したり、地元にあるホームセンターのカインズ工房のレーザー加工機を利用して、アクリルのプレートを作成しました。

今回、新たな自作キーボードを作るにあたり、久しぶりにカインズ工房のレーザー加工機を利用しました。その時にやったことをまとめます。

4年前の記事の補強板となっています。

74th.hateblo.jp

カインズ工房のレーザー加工機

カインズ工房ではレーザー加工機時間貸しサービスを提供しています。 2026年2月現在、30分2,500円の料金で利用できます。

diy-style.cainz.com

このサイトで予約して利用できます。 こちらのサイトにマニュアルがあり、事前にどのような操作をするのか確認できます。

この利用には、事前にAdobe Illustratorで作成したデータが必要になります。 しかし、筆者はAdobe Illustratorを持っていないため、無料で利用できるInkscapeで作成したデータを利用しましたが、問題なく利用できました。

まず大前提

ここに書かれていることはカインズ工房の公式の情報ではありません。

カインズ工房から、公式のマニュアルは前節の通り公開されています。 こちらをよく読んで、利用してください。 当日も、こちらのマニュアルを見ながら操作するようにしましょう。

また、カインズ工房ではIllustratorで作成したデータが必要とされていますので、Inkscapeで作成したデータでダメと言われた場合には諦めてください。 利用できない場合やトラブルに対して、本記事の執筆者は責任を負いません。 自己責任で行ってください。

初回利用時には、カインズ工房のスタッフの方が操作方法を教えてくれます。 特に、レーザー加工機の焦点合わせの方法は一度教わりましょう!

カインズ工房のレーザー加工機に必要なデータ

カインズ工房のレーザー加工機で利用するのに必要なSVGデータの形状は以下のようになります。

  • 1箇所のくりぬきのためのパスは、1つのパスでできていること
  • 1つのパスは、ノード(点)同士が全て繋がっていること
    • つまり、ノード(点)を1個動かすと、ノードに繋がった2つの線が動く状態です。2つのノード(点)が同一座標に置かれている状態とは異なります)
  • グループ化されていないこと
  • 線の太さは、0.01mmまたは0.003pxであること
  • 線の色は、#ff0000(赤単色)であること
  • 各オブジェクトの塗りつぶしは、なしであること

この状態のSVGデータを作成し、Adobe Illustratorで開いて利用できました。

KiCadからカットデータとなるSVGファイルを作成する

筆者の場合には、まずトッププレートのデータをKiCad上でEdge.Cutsレイヤーとして作成しています。 KiCadを使う理由は、事前にロジックPCBのデータをKiCad上で作成しているため、ロジックPCBのスイッチの位置に重ねる形でトッププレートのデータを作成できるためです。

KiCadで製作したデータ

既にトッププレート用のEdge.Cutsレイヤーだけのfootprintを作成してあり、それを配置しています。 なお、このfootprintはGitHub上で公開しています。 ここのSwitch_MXSwap_1.25u_Top.kicad_modなどのファイルがそれに当たります。

github.com

次にこのデータをSVGに出力します。

メニューバー->ファイル->プロットから、以下を設定して、プロットを押します。

  • 出力フォーマット:SVG
  • 含めるレイヤー:Edge.Cutsのみ
  • 全般オプション:基本的に全部オフ(図画用紙等を描画させない)
  • SVGオプション:
    • 出力モード:モノクロ

SVGへのプロット

ここで作成されたSVGは、線分ごとにパスが作られ、ノード(点)が繋がっていない状態になっています。

このパスを繋げるには、まず、1つのくりぬきのパスを全て選択して、メニューバー->パス->結合を行います。 しかしこの状態では、線分同士が繋がっていない状態になっています。 各線分の重なっているノード(点)を選択し、「選択した端点ノードを連結」し、ノードを繋げて、1つのパスにしていきます。

単一パスにするのとノードを繋げる作業がなかなか骨の折れる作業です。 これをスクリプト化したものを下記に置いています。 このスクリプトは、ひとまず私の環境で動いたものであり、必ず利用できることを保証する物ではありません。 実行後、期待通りのファイルになっているか、Inkscape上で確認してから利用してください。

https://github.com/74th/74th-kicad-parts/blob/main/scripts/convert_edge_cuts_svg/convert_edge_cuts_svg.py

その後、以下を行います。(上記スクリプトは、グループ化までは行いますが、色設定までは仕込んでいません)

  1. グループ化を解除して、全てのパスが並列に並んだ状態にする
  2. パスの内、最も外側のパスを最後に移動する(最も外側のパスが最初にカットされると材料が動いてしまうため)
  3. 全てを選択し以下を設定する

この状態のSVGファイルを持ち込みました。 カインズ工房設置のPCでAdobe Illustratorで開いて、aiファイルとして保存しました。

これまで遭遇したデータ周りのトラブル

カットとして認識されない

2回目のレーザーカッターを利用した時に、カットとして認識されない問題が発生しました。カットではなく彫刻としては認識されているようでした。

Ctrl+Aでオブジェクトの全選択をしてみると、「塗りつぶし」の所が「透過(斜線表示)」になっていませんでした。「塗りつぶし」があるとカットラインとしては認識しないようです。「塗りつぶし」を「透過」にすると認識するようになりました。

あとからInkscapeSVGファイルを開き直して全選択をしてみると、確かに「フィル」が「x(なし)」になっていませんでした。

Illustratorで開いた時に一部の図形が表示されない

3回目のレーザーカッターを利用した時に、Illustratorで開くと一部の図形が表示されませんでした。

表示されたものと差を見ていくと、グループ化されていると表示されていないようでした。

グループ化を1つ1つ解除することで、カットラインとして使えるようになりました。

カインズ工房のIllustratorにて、スウォッチライブラリがない

Rubyを用いたマニュアルでは、スウォッチライブラリでspeedyを選択するように指示があります。 しかし、私の利用した店舗のIllustratorにはスウォッチライブラリにありませんでした。 ひとまず、そのままで利用できました。

カットの順序として、外側を最後にカットして欲しいがそうなってない

カットの際には、ずれないようにするためにも、内側を先にカットし、外周部を一番最後にカットすると良いです。

Ruby(レーザ加工機操作用ソフトウェア)の操作中に、カット順序が表示されるのですが、確認すると外側が一番最後になっていませんでした。 Ruby中のカット順序の表示にて、順序を入れ替えることができ、そこで一番最後に持ってくることができました。

おそらくSVGファイル内のレイヤーの表示で、外周のパスを一番最後に持ってきていれば良かったのだと思います。

カインズ工房でのレーザー加工機の操作手順

カインズ工房提供のマニュアルの通り操作していきましょう!

diy-style.cainz.com

現地にもこのマニュアルを印刷した物が置かれており、これを見ながら操作しました。 繰り返しになりますが、初回利用時には、カインズ工房のスタッフの方がレーザーカッターの操作について教えてくれます。 かならず教わってその通りやりましょう。

パラメータの設定

素材によってカットに必要なパワーやスピードのパラメータ設定が異なります。 ショップにあるマニュアルにはパラメータの設定例が載っていますので、そちらを参考にしてください。

アクリル2mmのパラメータ設定例

2021年当時は、以下のパラメータで利用していました。

  • パワー: 100
  • スピード: 0.55
  • Hz: 1000

その時は、スピード0.6では一部の箇所のみ切断できない(力を加えれば折れるので、使えなくはない)ところがあったので、最終的に0.55にしていました。

しかし、2026年2月に利用した際には、同じパラメータ設定で、わずかに一部が切断できないところがありました。 よって次回はさらにスピードを落として、0.50で利用してみようと思います。

  • パワー: 100
  • スピード: 0.50
  • Hz: 1000

カットにかかる時間

操作中に、カットに要する時間が記載されます。以前の私のデータの場合は4分40秒でした。

しかし、このカットを始める前に、「レーザーカットのデータの送信」、「アクリルの設置」、「焦点合わせ」を行う必要があり、データの送信は同一のものを出力する場合には省略できますが、「データの送信」に慣れても3分、「アクリルの設置」、「焦点合わせ」に1分程かかります。

さらに、レーザーカットの後には排気が行われ、材料が取り出せるまでに時間がかかります。さらに切断後の素材のため、いろいろカットした部分がポロポロ落ちるため、取り出して折り曲がらないところに挟み込むまでにも時間がかかります。慣れても1分ほどかかると思います。

よって、1枚あたりの作業は、カット約5分+前後2分で、7分ほどかかる計算になります。すると、30分でできる加工は4枚セット分程度だろうという試算になりました。

今回利用したときも、データセットアップに7分程度かかり、30分で2枚カットがぎりぎりでした。

加工する時に別途用意するもの

次に加工する時に別途用意するべきと思ったものは以下の通りです。

  • 完成部品を入れておくケースを用意しておくこと。段ボールを2枚用意し、長めの輪ゴムで巻いたもので挟んで持ち運びしました。
  • 端材を入れる袋を用意しておくこと。スイッチの穴があり、大量に小さな端材が出ます。

レーザーカットサービスか、時間利用で自分で加工するか

このようにレーザー加工機でどのような生産ができるか見積もれるようになりました。

今ボトムプレート10セット分、トッププレート5セット分を作成したいのですが、そのコストは以下と試算できます。

  • レーザー加工機レンタル2時間(16セット分)2,500円x4=10,000円
  • アクリル材料費 アクリル板透明2mm 300x450mm(3セット作れるサイズ)x5枚(15セット分)=2,673円+送料
  • +交通費

アクリルの購入先

アクリルははざいやで購入しました。様々な種類のアクリルを販売してくれます。

www.hazaiya.co.jp

今回の製作

今回は、アクリルをトッププレートにした自作キーボードを製作しました。 3Dプリントしたケースと共に利用して、天板がアクリルで綺麗なため、見た目がとても良くなりました。

激安マイコンCH32V003を使って、キーストロークを入力する1%キーボードを作る

tl;dr

  • CH32V003は秋月で60円で買える激安マイコンですが、USBデバイスペリフェラルはありません
  • CH32V003にはrv003usbというUSBデバイススタックがあり、USBキーボードを簡単に実装できます
  • キーストロークを入力する1%キーボードを作りました
  • 呼び出しボタン付きの収まりの良いケースに入れた

できたものと経緯

x.com

タイプすると、"74th!"と入力されます。パスワードとか、特定の操作を素早く行いたいときに便利なものを作ろうとしました。

サイズを小さくしたく、マイコンボードではなくマイコン単体を組み込みたいと思いました。 そこで激安マイコンCH32V003を使うことにしました。

CH32V003とは

CH32V003は74thが愛用している激安マイコンです。過去に解説書を書いてしまうほど、自分の電子工作に欠かせないマイコンです。

74th.booth.pm

CH32V003には、USBデバイスペリフェラルがありません。 CH32V003のファームウェア開発ではch32funを利用していますが、その中にrv003usbというUSBデバイススタックがあり、USBキーボードを簡単に実装できます。

設計した基板

作成したKiCadファイルは以下で公開しています。

ポイントはrv003usb用のUSB周りの配線です。PD3、PD4をUSBのD+、D-に接続し、USBのプルアップ抵抗(1.5kΩ)をPD5に接続します。

後から気づいた反省点としては、RGB LEDをSPIのPC6に接続しなかったことです。 RGB LEDのドライバとして、SPI DMA転送を使えたのですが、SPI MOSIであるPC6に接続していなかったために、ch32funに含まれているSPI DMAドライバが使えませんでした。 代わりに、CPUでbitbangしてRGB LEDを制御するドライバを使用することになりました。 RGB LEDはSPI MOSIに接続する癖を付けたいです。

rv003usbでファームウェアを作る

rv003usbには、マウス、キーボードのサンプルコードがあります。

github.com

このコードは、1秒ごとに"B"キーを押して離す動作を繰り返すコードになっています。

これを書き換えて、以下の機能を付けました。

  • キーの押下を検出する
  • RGB LEDを点灯する
  • ASCIIコードの文字列で組み込んだ文字列をキーストロークとして入力する

TinyUSBのコードの中に、ASCIIコードをキーコードに変換するコードがあり、それを引用して、ASCIIコードの文字列をキーストロークに変換できました。

展示用にケースを作る

せっかく作ったので、天下一キーボードわいわい会Vol.10で展実しようと思い、ケースを製作しました。 アケコン用ボタンを使い、単体でもガジェットっぽく使えるようにしました。 狙い通り、呼び出しボタンのような雰囲気になりました。

コードとケース

製作したコードとケースのデータは以下で公開しています。

github.com

github.com

まとめ

妻に「パスワードを簡単に入力できるデバイスを作ったよ!」と言ったら、「そんな危ないものお家の中に置かないで!」と言われました。 デモでは「74th!」と入力してくれるデバイスになっています。

スイッチにDurock Ice King Tactileを付けたところ、透明なハウジングがよく光を通してパッと光り、癖になり、見ていて飽きないものになりました。

rv003usbでのキーボードは今のところちゃんと動いています。 確実性のあるキーボードを使いたいならばUSBデバイスペリフェラルを持つマイコンを使うことをお勧めします。 普段使い用のキーボードを作るマイコンとしては、QMK Firmwareを使ってカスタマイズしたいので、rv003usbを使うことは私はないでしょう。 SparrowSv3では右手キーボードのマイコンとしてCH32V003を組み込んでいます。

最後に以下は製作したキーボードでタイプした文字列です。

74th!74th!74th!74th!74th!74th!74th!