M5StackCore2、M5Dialをトラックパットとして使う自作キーボードSparrowDialを作ったよ

tl;dr

  • M5StackCore2、M5Dialはタッチパネルが付いていて、タッチパネルの精度がかなり良いよ
  • これをトラックパッドとして使うために、I2Cトラックパッドバイスファームウェアを作ったよ。I2Cトラックパッドの仕様は独自仕様だけど、QMK Firmwareに対応したよ。
  • 電源供給するために、USBドーターケーブルを作ったり、MBus経由で給電できるようにしたり、工夫したよ
  • 操作感のチューニングはかなり頑張ったよ、2点タッチとか、ドラッグとか
  • GH60互換ケースにM5Dialを収めるには、かなりの加工が必要だけど、できることはできたよ!
  • キーケットで販売して完売、今はBOOTHにて販売を続けているよ

M5StackCore2、M5Dialはタッチパネルがついているよ

M5DialはM5Stackが販売する、ESP32-S3を搭載した、M5StampS3を内蔵する、ロータリーエンコーダデバイスです。大きなロータリーエンコーダの他に、円形のLCDが付いており、この部分はタッチパネルになっています。

公式Webサイトより引用

M5Stack Dial ESP32S3 スマートロータリーノブwww.switch-science.com

ESP32-S3には、USBデバイス機能が付いており、USBデバイス機能を使ってトラックパッドバイスを作ったことを以前記事にしました。

74th.hateblo.jp

この記事でも書いていましたが、M5Dialを自作キーボードにモジュールとして組み込みたいと考えていました。

一方、M5StackCore2はM5Stackが販売するESP32を搭載したモジュールです。M5StackCore2はM5StackBasicと異なり、LCDにはタッチパネルが付いています。前面下部のボタンもタッチパネルの一部となっています。そして、このタッチパネルは2点タッチに対応しています。

公式サイトより引用

M5Stack Core2 v1.1www.switch-science.com

M5Dialをトラックパッド化したときの感触が非常に良かったため、この2つのトラックパッド機能のあるM5Stackを使って、本格的に自作キーボードに組み込んでみたいと思っていました。

QMK Firmwareを使う作戦

M5Dial/M5StackCore2を使うならば、ESP32というマイコンが積まれているため、キーボードに関する処理をやらせようと思えば可能です。以前、Arduinoファームウェアを作り、Bluetoothテンキー電卓 Sparrow24 BLE Calculatorを作っていました。

しかし、QMK Firmwareを使いたいとなるとESP32/ESP32-S3には対応していません。なので、あくまでM5Dial/M5StackCore2は、トラックパッドバイスとして作り、別途RP2040等のマイコンからトラックパッドバイスを利用することで、QMK Firmwareが使えるのではないかと思いました。

そして、その間の通信には、Sparrow60C/StickPointVでも使っているI2Cを使おうと思いました。

I2Cトラックパッドバイスを作る

Sparrow60C/StickPointVでは、PIMORONI TrackballのI2Cのプロトコルを利用して、デバイスを作り、QMK Firmwareで使えるようにしていました。M5Dial、M5StackCore2でも同様にしようと思ったのですが、トラックボールモジュールとしての仕様のため、ホイールに相当する情報を送ることができなかったり、右ボタンクリックに相当する情報を送れなかったりすることがわかりました。そりゃそうです、トラックボールなのですから。加えて、いくつかPIMORONI Trackballに向けてチューニングされているQMK Firmwareの機能が使い辛く思っていました。

そのため、Simple Pointerと呼んでいるI2C通信の仕様を作りました。やっていることは、QMK Firmwareでマウスの命令として送るべき情報をそのままのせたもになっています。1回似受け取るデータは以下の構造体です。

typedef struct
{
    uint8_t click;
    int8_t pointer_x;
    int8_t pointer_y;
    int8_t wheel_h;
    int8_t wheel_v;
} p74_data_t;

これをQMK Firmwareに対応させることで、マウスモジュールのチューニングをM5Dial/M5StackCore2側で行えるようになります。

また、M5StackのライブラリはArduinoベースでできています。そのため、I2C SlaveデバイスとしてArduinoで実装できる必要があります。以前のESP32用のArduino FrameworkではI2C Slaveが実現できなかったようですが、現在は機能が実装され、問題なくできるようになりました。M5Dialではこれを有効にすると、USB CDC(UART)によるログが取れないことを確認しています。

このSimple Pointerとしてのファームウェアは、オープンソースとしてGitHub上にあげています。そこには、QMK Firmwareで有効にさせる方法も記述されているため、私の作るキーボード以外であっても、良ければ使ってみてください。

github.com

ちなみに、このQMK Firmwareへの対応については、既に記事にしているため、こちらも見てみてください。

M5Dial/M5StackCore2への給電

今回、M5Dial/M5StackCore2はあくまでI2Cスレーブデバイスであり、USBはRP2040が繋がるキーボードマイコンとPCBの方に接続されており、M5Dial/M5StackCore2には別途キーボードPCBの方から給電する必要が出てきました。

M5Dialへの給電はUSBで

M5Dialへの給電として、バッテリー接続用のポートが付いています。

ただし、こちらはバッテリーのための実装がされており、入力電圧は5.3V以上必要です。USBの5Vでは対応していない、と言うわけです。実際にやってみて動かなかったわけではないのですが、かなり不安定でした。

そこで、USB経由で給電することを考えました。USB-CソケットとGroveコネクタ(HY2.0)が付いたドーターケーブルを作り、PCBからGroveポート経由で給電しようと思いました。これには成功しました。どのくらいの電圧が必要であるかは、以下で記事にしています。

74th.hateblo.jp

M5StackCore2への給電はMBus経由で

続いて、M5StackCore2です。

このデバイスにはGrove PortAが付いていますが、こちらは電源出力専用で、このポートから電源供給することはできませんでした。

M5StackCore2はその名前の通り、積み重ねることで機能を足すことができます。これはデバイスの下面にMBusと呼ばれるポートが付いており、ボトムの部品を外すことでここにアクセスできます。ここから5V、GNDのポートに給電することができました。

また、I2Cの通信に関しても、Grove PortAに対応するポートがMBusにもあるため、MBusから電源供給とPortAへのアクセスを行うアダプタを作成しました。このアダプタにはGroveポートが付いており、ここにGroveケーブルでキーボードPCBから給電とI2Cでの通信を受けることができます。

なお、このモジュールを作るに当たって、利用する2x15ピンピンヘッダを選定しました。しかし、TaoBaoで購入した物はプラスチックの部分の高さが高く、結局M5Stack公式のピンヘッダを利用することにしました。これはかなりプラスチックの部分が低くできており、ボトムを取り除いても、上面ケースの高さにアダプターPCB含めて収まりました。

操作感のチューニング

主にトラックパッドで実現したい機能は以下の通りと思いました。

  • ポインタ移動
  • 左クリック
  • 右クリック
  • ホイール操作
  • ドラッグ(左クリック+ポインタ移動)

これらをM5Dial/M5StackCore2でどのように実現するかを考えました。最終的に以下の操作になりました。

  • M5Dial
    • ポインタ移動: タッチパネルスライド
    • 左クリック: タッチ
    • 右クリック: ボタン
    • ホイール操作: ロータリーエンコーダー
    • ドラッグ(左クリック+ポインタ移動): タッチされた状態でボタン押下しつつスライド
  • M5StackCore2
    • ポインタ移動: タッチパネルスライド
    • 左クリック: タッチ
    • 右クリック: 2点タッチ
    • ホイール操作: 2点タッチスライド
    • ドラッグ(左クリック+ポインタ移動): 左下領域タッチ+スライド

M5Dialは2点タッチに非対応(対応している情報が得られなかった、M5Unifiedが2点タッチにまだ非対応??)のため、下部にある物理ボタンと連携させることで、右クリックとドラッグに対応しました。若干ドラッグが操作しにくく、難しい物になってしまいました。

M5StackCore2は2点タッチに対応していたのですが、2点タッチの精度がかなり怪しいです。特に指を並べる方向によって反応しないことがわかりました。最終的には、M5StackCore2の向きを変えることで対応しました。

また、ドラッグ操作に関しては、右手で使うことを前提に、タッチしにくい左下の領域をタッチ中は左クリックと見なされる領域にしました。これにより、この領域をタッチしたまま、スライドでドラッグを実現しました。

ただ、M5Dial/M5StackCore2ともドラッグ動作ができるという程度で、実用性に足るレベルまでは行かなかったように思います。それよりも、左クリックボタンやスクロールボタンをキーボード上に用意し、デバイスは基本的なマウス操作に絞った方が操作しやすいように思いました。

また、移動量の調整にはいろいろ試行錯誤していました。これには、M5Dial/M5StackCore2のタッチパネルモジュールが、扱いやすいようにかなりライブラリでチューニングされたものになっており、それとかちあって繊細な操作が入力できなかったり、体感以上にマウスが動いたりするものになっていました。この辺りはかなりチューニングしました。

M5Dialを収めるためにケースを加工

M5Dialはかなり奥行きのあるデバイスです。これをGH60互換ケースに収めようと思うと、深さが足りなかったり、支柱が邪魔になったりします。ですが、GH60互換プラスチックケースは、プラスチックのため非常に加工がしやすく、邪魔な部分をニッパで取り除くことで実現することができました。

以下はビルドガイド中のケース加工に関する記述です。

ちょっと収まりづらいですが、収めることは可能と言った形で落ち着きました。

使用感はどうか?

トラックパッドとしての使用感はなかなか快適です。くわえて、M5Dialの大きなロータリーエンコーダでスクロールするのもやみつきになります。実用に困らないレベルのものになったと自負しております。

ただ、右クリック、ドラッグや、M5StackCore2での2点タッチでのホイール操作は不満があり、キーボードにマウスキーを作ったり、スクロールキーを設けた方が操作しやすいように感じており、私自身そのようにしています。キーボード自体にも、デバイスの下に1キー増やしてあり、それを左クリックにしたりすることを想定しています。もう少しコンパクトに、TrackPointの3ボタン(左クリック、スクロール、右クリックボタン)程度の余裕があれば良かったのかもしれません。

キーケットで頒布して完売、BOOTHでも販売中

このキットはキーケットで体験可能な形で展示し、販売しました。

多くの方にこの操作缶を体験して貰い、良いと感じて貰えました。さらにこのキットは予定していた6つを完売しました。キーケットの前にBOOTH上で予約販売という形をとっていたのですが、それも3つほど注文がありました。

現在でもこのキットはBOOTH上で販売しております。よければ手に入れてみてください。

74th.booth.pm

今後、M5Stack関連のイベントでも展示、販売できればと思っています。

GH60互換ケースを使ったレバーレスジョイスティック付きゲームコントローラSparrowG21を作った

tl;dr

  • GP2040-CEというRaspberry Pi Picoを使ったゲームコントローラファームウェアで、レバーレスコントローラを作るのが流行っているようだよ
  • GH60互換ケースを使って、GP2040-CEを使ったレバーレスを作ってみたよ
  • ジョイスティック、RGB LED、OLED、Turbo LED、Board LED等の機能を使えるようにしたよ。
    • ジョイスティックはADCのピンに繋ぐよ
    • 電子工作で用いられるOLEDモジュールは2種類あってピン配置が違うことに戸惑ったよ
    • Turbo LEDはActive Low、Board LEDはActive Highだったよ
    • トッププレートにLEDを渡すためにQwiicソケットを使ったよ
  • キーケットで展示販売したところ、興味を持ってもらえたよ。現在もBOOTHで販売中だよ。

GP2040-CEというゲームコントローラファームウェア

GP2040-CEというRaspberry Pi Picoを使ったゲームコントローラファームウェアがあります。

gp2040-ce.info

GP2040-CEの特徴は以下の通りです。

  • Raspberry Pi Picoを使うため簡単に導入できる
  • 反応速度が速い
  • PC(XInput、DirectInput)、Switch、PS4/5に対応(ただしPS4/5は別途認証アダプタが必要)
  • ターボ、プロファイル、マクロなど、多くの機能が備わっている
  • Webブラウザで設定を変更可能(USB Ethernetバイスとして動く)

多くの機能が備わっているため、現在DIYゲームコントローラーを作るならばこれを使わない手はありません。Webブラウザで設定が変更できるというのも、ユーザは再ビルド等の手間がなくとても扱いやすいと言えます。

私自身は、過去に音楽ゲーム用コントローラDive9を作ったことがあり、この時にはProMicro(ATMega32U4)を使い、ファームウェアにはQMK Firmwareで作っていましたが、今作るのであればこちらになったと思います。

汎用自作キーボードケースで作ってみたくなり、作ったよ

私自身は格闘ゲームはしないのですが、よく2Dジャンプアクションゲームをしています。配信などを観ると、Dead Cellsのようなジャンプアクションであったとしても、PCキーボードでプレイする方がおられます。さらに最近マウスとキーボードで操作するRusted Mossをプレイしたため、キーボードベースのゲームコントローラーも悪くないのではないかと思うようになりました。

ただ、必ずしもキーボードだけで自分のプレイするゲームが完結できるかというとそうでもなさそうでした。Dead Cellsでも遠距離系のアイテムを拾ったときには照準のためのスティック操作が欲しくなります。前にプレイしていたローグレガシー2でも弓系のアイテムがあるとジョイスティックが必要になります。

さらに、多くのゲームコントローラでは左手が4ボタン(←↓→↑)になっています。しかし、Rusted Mossで親指のキーにはスペースバーによるジャンプを割り当てたいため、4ボタンでは不足します。よってソレを補うようなボタン配置が必要になりました。

結果として、以下のような配置になりました。

  • 左手中指で無理なく↑↓の2ボタンを入力できるようにして、左手で5ボタンを使えるようにすること
  • 上位スティックを備えること

例えば、Hollow Knightでは以下のような配置にしてプレイしました。

これに更に、A1、A2、S1、S2、L3、R3キー追加し、更に設定ボタンとして Turbo、Functionボタンを追加しました。これらのキーは操作の邪魔にならないところに置いています。

おまけで、薄型スイッチLOFREE x KAILH Full POM Low Profile Switchesを使うために、Kailh Choc v2とMXの両対応にしました。RGB LEDをなんとか入れたかったため、MXのみソケット対応として、薄型スイッチの場合にはスイッチを直接実装する使用としました。

GP2040-CEの機能のサポート

GP2040-CEの機能のサポートとして、いくつかPCBに実装を行いました。

基本のスイッチ

まず、GP2040はキーボードのようにボタンマトリックスを組むようにはなっておらず、各ピンがプルアップインプットとなっており、GNDとピンをスイッチで繋ぐことでボタンとして機能するようになります。そのように各ピンを配線しました。

プロファイル等Functionキー

これらはただスイッチを追加すれば良いため、そのようにしました。

ターボキーと、ターボ用LEDライト

ターボキー自体は普通のキーと同じようにGNDとピンをスイッチで繋ぎます。一方、ターボ入力がされていること表示するターボLEDがあります。ターボLEDはActive Lowとして振る舞うため、3V3-抵抗-LED-Pin の順に繋げば良いです。

ボードLED

Raspberry Pi Picoにはボード上にLEDが実装されており、これを現在のモードを表示するようなLEDとして利用することができます。ロゴの横にこのLEDを配置しました。

なお、このLEDはActive Highとなっており、ターボLEDと仕様が違うため注意が必要でした。

LEDをトッププレートに盛ってくる

LEDですが、PCB上にあると、その上にトッププレートがあるため、穴を経由してみることになり見づらくなります。そこで、Qwiic(SH1.0)ソケットを使って、PCBとトッププレートの橋渡しをして、トッププレート上にLEDを実装することにしました。

いつも使っているGrove(HY2.0)ではなく、Qwiic(SH1.0)を使ったのは、QwiicソケットであればトッププレートとPCBの間の3.5mmに高さ的に収まるためです。

ただ、Qwiicソケットの実装は1.0mmピッチのためそれなりに難度があったようです。実装にはフラックスが必須に思います。

ここで注文するケーブルを誤ってしまい、ピンの並びが同じになるように両端で表裏が逆向きにされたケーブルではなく、同じ向きになっているケーブルを購入してしまいました。この部分は2種類のソケットの実装箇所を用意しておき、どちらもケーブルも使えるようにしました。購入者が組み立て時に誤ってしまわないように、このQwiicソケット予め実装済みにしておきました。

ジョイスティック

ジョイスティックには、モジュールとしてStickPointVにも使っているスライド型ジョイスティックを使い、RP2040のADCで読み取らせます。

akizukidenshi.com

ADCを安定させるため、ジョイスティックのVCCのまわりにキャパシタを追加していました。

また、ジョイスティックのキャップとして、3Dプリンタで印刷したものを用意しました。上面のグリップ力をあげるために、マウス用のグリップテープを貼り付けました。

OLED

押しているボタンやモード等を表示できるOLEDを追加しました。OLED自体は電子工作でよく使われるモジュールです。

このOLEDですが、TaoBaoで購入しようとしたのですが、2種類の使用が存在していルことがわかりました。左端がVCCの旧版と、GNDの新版です。

これに対して、回路上ではジャンパで接続するようにしました。

結局、頒布版ではピンヘッダが予め実装されていないものが手に入る旧版を使いました。

このOLEDはトッププレートの窓から覗く形にしました。おかげで、モジュールっぽさがなくなって綺麗になったように思います。

Neo Pixel

キーを光らせるNeo PixelタイプのRGB LEDに対応しています。やはりゲーミングデバイスには光ることが必要でしょうと導入しました。

しかし、GP2040-CE v0.7.5からv0.7.7に変更したとき、光らなくなってしまいました。これは、Raspberry Pi Pico用のファームウェアを利用して、IO24を利用していることに起因しているようでした。Picoでは、IO24はUSBからの給電(VBUS)に使われます。おそらくそのためにINPUTに設定されてしまっていたと思われます。他のボードの設定を使っても良かったのですが、すると今度はBoard LEDがピンが異なっていて動作しなくなってしまいます。

これはGP2040-CEのファームウェアをセルフビルドすることで解決しました。これについては別途記事にしています。

74th.hateblo.jp

頒布版の工夫

頒布版では、RP2040 MCUはと、SMD部品は私の方で実装済みにしました。購入者には組み立て時に、スイッチソケット、OLED、ジョイスティックなど、大きい部品のみを実装すればよいようにしました。ただし、Qwiicソケットだけは、薄型スイッチを利用しようとした場合に利用できないため、実装して貰う形にしました。

RP2040の実装は大変でしたが、頑張りました。

キーケット後に追加PCBを発注した際には、手はんだ実装サポートアダプタをつくり、こちらで実装しかなり楽になりました。このアダプタについてはまた記事にします。

使用感はどうか?

現在、Hollow KnightのDLCをプレイしていなかったことに気づき、このデバイスを使ってプレイしています。慣れたゲームパッドよりも操作が難しいですが、面白く使っています。

最初は、反応するまでのポイントが近く設計されているスピードタイプのリニアスイッチDurock Splash Brothersを使っていたのですが、しっくりきませんでした。キーボードと違って、ゲームの時には「離すタイミング」が重要であり、離す時にどのくらい指をあげれば良いのか感触でわかりにくい気がしています。このために、タクタイルスイッチであるDurock Ice King Tactileに変えたところ、離すときの感触がタクタイルの山として得られて、良い感じに操作することができるようになりました。

だいぶプレイしましたが、十字キーをレバーレスとしてボタンで操作するのはまだ慣れません。↑↓を考えないと操作できない感じです。でも、楽しく操作できています。

キーケットで頒布したよ

こちらをキーケットでも頒布しました。キーボード以外の出品ということで、興味を持ってもらえるか心配でしたが、目に留まるときになる方が多かったようで、触らせてもらえますかと何度も声をかけていただきました。数も用意した6つのうち4つを販売できました。

現在もBOOTHで販売中

こちらの商品はBOOTHでも販売中です。これは、私の2Dアクションゲームをするために作ったデバイスですが、格ゲー等にも使えると思いますので、お試しいただければ嬉しいです。

74th.booth.pm

ジョイスティックをマウスとして使うSparrow60Cキーボードの頒布版ができたよ

tl;dr

  • ジョイスティックをポインタとして使うためのモジュールStickPointVを搭載したキーボードを作ったよ
  • ケースが合った方が、操作が安定するのを感じるよ
  • もう1年以上使っているけれど、マウスと併用して、活用しているよ
  • キーケットで販売したよ、継続してBOOTHでも販売しているよ

ジョイスティックをポインタとして使う StickPointV

私が制作、販売している、ジョイスティックをチューニングしてQMK Firmwareなどのキーボードファームウェアから利用可能にした、StickPointVについては以前の記事で紹介しました。

74th.hateblo.jp

このモジュールでやっていることは以下のようなことです。

  • モジュール自体にマイコンが付いていて、ここでマウス操作に変換して、I2Cで伝えるので、操作感のチューニングがモジュール側マイコンでできるようにしてあるよ
  • I2CのプロトコルはPIMORONI Trackballと同一にしてある(元は、パレットシステムさんのAZ1UBALLのアイディア)ので、キーボードファームウェアがPIMORONI Trackballをサポートしていれば、簡単に導入できるよ
  • TrackPointキャップをアダプタを付けてジョイスティックに持たせることで、グリップがよく操作しやすくなっている。
  • あまりジョイスティックでは、細やかな移動量の操作が難しいため、基本は移動量を小さくして、2 回コツコツっと操作することで、ダッシュモードを実装しているよ

このようにいろいろ手を加えることで、操作しやすくしたモジュールです。モジュール単体でBOOTHで販売中です。

74th.booth.pm

このモジュール専用キーボードを設計

このモジュールを使うための専用キーボードを設計しました。以前、汎用ケースを使ったSparrow59を設計しましたが、その延長戦で汎用ケースを使ったキーボードを作りたいと思っていました。

74th.hateblo.jp

StickPointVには、裏にGroveポートが付いていて、I2Cで通信するようになっています。このGroveポートをキーボードにも足して、さらにケーブルを通すための穴を開けてました。これをSparrow60Cと名付けました。

Raspberry Pi Pico利用も回り道したが、RP2040直接実装へ

安価なGH60互換プラスチックケースの空間を計り、ロープロファイルソケットを使って、ピンヘッダのピンのみを付けた方法ならば、Raspberry Pi Picoが交換可能ながらケースに収まることを発見し、その方法をとっていました。ロープロファイルソケットをコンスルーピンヘッダの代わりにする記事を以前書いており、その手法を使った次第です。

74th.hateblo.jp

しかし、プラスチックのGH60互換ケースならば収めることができましたが、アルミ削り出しケースでは収めることができませんでした。天キーで多くのキーボードを観た私は、アルミ削り出しケースに憧れており、このケースに対応したPCBとして、RP2040を直接実装するように変更しました。

そこでできたのが、Sparrow60 v1.3になります。

GH60対応PCBのスタートはRP2040直接実装だったのですが、実装の困難さからPicoの利用にシフトし、またRP2040直接実装にも取ってきた形になりました。この間に、RP2040の直接実装にかなり慣れたのもあります。

74th.hateblo.jp

使用感は?

プラスチックケースの時にはDurock Black Lotusを使っていたのですが、アルミ削り出しケースに変えてからはHHKB Studioに憧れてKailh Deep Sea Silent Box Switch Isletに置き換えていました。

このスイッチの感触が凄く良く、とても満足の高い打鍵感になりました。

肝心のStickPointVはどうかというと、特に問題なく使えています。やはりケースに収まって、ケースの重さがあるため安定性が増しているように思います。

キーケットで販売しました

制作したSparrow60Cは、自作キーボードの展示即売会、キーケットにて販売しました。

74th.hateblo.jp

本商品を2セット購入いただきました。ありがとうございます! 更に体験していただいて、StickPointVモジュールも完売する結果になりました。

現在はBOOTHにて販売中

このキットは現在、BOOTHにて販売中です。StickPointVモジュールが付属します。

74th.booth.pm

ジョイスティックモジュールStickPointV自体も販売しております。

74th.booth.pm