golden-luckyの日記

ツイッターより長くなるやつ

30キー左右分離キーボードfoobarをPico Micro Cで作った

はやりの自作キーボードの記録です。 きっかけは、2年前のpyspa忘年会でこちらのキーボードの基盤を手にしたことでした。

リンク先の写真からわかるとおり、キーが30個しかありません。HHKBのおよそ半分です。さらに分割式。 もともとフットプリントが小さいキーボードが好きで長年にわたりHHKBを使用、しかし1台を両手で使うには肩と背中に限界を感じて2台でスプリット、しかし2台だと入力できるファンクションキーが限られてしまうので最初から左右分割で設計されたキーボードとしてErgoDoxを導入、しかしErgoDoxはデカくて机が狭い…、という遍歴の自分にとって、この「foobar」という雑な名前の自作キーボードはかなり魅力的な存在でした。

とはいえ、電子工作はずいぶん昔に少しかじった程度で、PCへの入力をあつかったこともなかったので、「まずは動作の原理を理解しないとゴミができるだけだな」とおもいながら、キースイッチだけ入手してなかなか着手できていなかったのでした。

ここにきて気持ちが高まり、Arduinoのノリもちょっとだけわかった気になったので、思い切って手を付けることにしたのが一昨日のことです。 先達の記事を見ながら脳内で実装の手順などをイメージトレーニングしまくったことが功を奏したのか、そもそもキー数が少ないからか、実際にハンダ付けに要した時間は二時間ちょっとでハードウェアはあっさり完成しました。

f:id:golden-lucky:20201213190147j:plain

ただ、ファームウェアにはちょっとはまりました。 もともと情報が少なかったうえに、自分の理解もあやふやなまま「とりあえずハードができてから試行錯誤でなんとかなるだろう」と甘く見てたのもあって、案の定トラブった感じです。

分割式キーボードのファームウェアはどうなっているのか

準備の最中からいまいちもやもやしていた点に、「左右2台のArduinoのどちらにどんなファームウェアを書き込めばいいのか?」というものがあります。 考えられるのは以下の三通りです。

  1. 両方のArduinoに、同一のファームウェアのデータを、それぞれのUSB端子から書き込む
  2. 両方のArduinoに、別々のファームウェアのデータを、それぞれのUSB端子から書き込む
  3. 片方のArduinoのUSB端子から、単一のファームウェアのデータを書き込む

このうち、Arduinoというか(AVR)でデータピンをとおして書き込みデータを転送できる気がしないので、3はないと考えられます(実は同じAVRなマイコンを使っているErgoDoxが片側からファームウェアを書き込むので、もしかしたらと思ったのだけど、単純にErgoDoxは1台のマイコンで制御する方式だった)。

公式ではTMKというファームウェアをベースとしたファームウェアが公開されていて、これは上記2の方式のようです。厳密にいうと、フラッシュメモリには同一のhexデータを書き込むものの、EEPROMには左右で別々のデータを入れておくような手順であることがドキュメントからは読み取れます。 そこで、まずは以下のようにデフォルトのキーマップを書き込んでみることにしました。 "40percentclub_foobar_default.hex" がデフォルトのキーマップ、 "eeprom-righthand.eep" が公式で用意されている右手用のEEPROMデータ(左手用は "eeprom-lefthand.eep" )です。

$ sudo avrdude -c avr109 -p m32u4 -P <COM> -e -U flash:w:"40percentclub_foobar_default.hex":a -U eeprom:w:"eeprom-righthand.eep":a 

(なお、Debian 10にインストールしたavrdudeではうまく書き込みが終わらなかったので、Windows用のavrdudeにGUIをかぶせたAVRDUDESSという便利なソフトウェアで書き込みを実行しました。(追記:ModemManagerが動いていると邪魔されて書き込みできない、ということに気づきました。その場合は sudo systemctl stop ModemManager とかでModemManagerを止めると書き込み可能になります。) あと、書き込み先の <COM> を知るには、ボードのリセットボタンを2回(まっさらなArduinoなら1回)押してからすばやく dmesg なりGUIの操作なりを実行する必要があります。 これはもちろん書き込みのときも同様。)

両方に書き込みできたところで、左右をTRRSケーブルでつなぎ、左手用のUSBコネクタをPCに接続してみます(デフォルトのキーマップは左手につなぐことになっている)。 ところが、なぜか左手側に実装したキーしかPCに反応しません。 ひょっとしてどこか接続を間違えているか、ハンダが甘いか、マイコンが死んでいるのか。 しかし全体に導通を確認しても特にあやしいところも見つからず、右側用もUSBケーブルでPCと直接接続すれば(上下左右が逆の状態で)左側として問題なく動くので、どうやらハードウェア的な問題でもなさそうです。

そこで qmk という別のファームウェアを試してみます。 こちらは左右分離式を含むさまざまなキーボードの種類に対応していて、それぞれに書き込み方法が異なるようなのですが、foobarについては上記でいうと1の方式で、同じファームウェアを書き込むようになっているようです。 そこでqmk のGitHubディレクトリをクローンしてきて その中で次のようにデフォルトのキーマップを生成し、生成された .hex ファイルのみをやはりavrdudeで書き込みます。

$ make 40percentclub/foobar:default
$ avrdude -c avr109 -p m32u4 -P <COM> -e -U flash:w:"40percentclub_foobar_default.hex":a

しかし、こんども同じ症状です。 USBでPCと接続しておらTRRSケーブルの先につながっている右手側は、Arduino上のLEDは点灯していますが、キーの押し下げにはまったく反応しません。

ただ、この時点でようやく1つの原因に思い当たりました。

USB type CのArduinoボードは、qmkの左右分離用ファームウェアのデフォルトでは動かせない

foobarをはじめ、AVRマイコンをコントローラとして利用している自作キーボードでは、一般に入手しやすいPico Microと呼ばれるArduinoボードとその互換機が利用されています。 これらPico Microたちは、(有線接続では)つい最近までUSB type Bが主流でしたが、ここ数年でtype Cの製品も手に入りやすくなりました。 type Bもtype Cもマイコンとしての動作は同じなので、自作キーボードでも問題なく使えると期待して今回の制作ではtype Cを使ったのですが、ひょっとしたらこれが「左右が連携できない」ことの原因かもしれません。

最悪はArduinoをtype Bに差し替えることも覚悟しつつ、その線に絞ってWeb検索をかけてみると、はたしてそのものずばりtype CなPico Micro互換ボードを左右分離型の自作キーボードで利用できるかどうか検討している記事が見つかりました。

要約すると、「ボードによってはqmkで左右のマスター/スレーブ識別に使っている方法(コネクタの近くのダイオードにおける電圧をみる)が使えないことがある」という内容です。 比較的新しいPico Microのtype Cのボードがこれに該当する可能性は、いまの症状からしてもありえそうに思えます。

幸い、qmkには、この状況をソフトウェア的に解決する手段が用意されているということも上記のブログからわかりました。 具体的には、ファームウェアコンパイル時に以下のマクロを有効にするだけです。

#define SPLIT_USB_DETECT

あらためてこの方法で生成したキーマップの .hex を左右両方のボードに転送したところ、無事に左右が連携してキーボードとして動作するようになりました。 こうして先人たちによる苦労のおかげで、さしたる苦労もなく、個人的な理想形の最北ともいえるキーボードが実装できました。 ありがたいことです。

f:id:golden-lucky:20201213190255p:plain