いきなり自作キーボードを作る


この記事は、キーボードとマウスとコーヒーとAdventCalendar2018 - Qiita の10日目の記事です。

頭痛が痛い的なタイトルで恐縮ですが、いきなりメカニカルやります!

始まり

ふだん使いのキーボードはThinkPad USB トラックポイントキーボード US (55Y9003) です。

でももう10年くらい使ってて、かなりヘタってきました。
明らかに買い替え時ですが、すでに生産終了してますし、オークションにも新品はめったに出品されないし、おまけに後継モデルはあまりにお粗末な代物でした。

次はどうしようかとウェブを徘徊していると、いつの間にか自作系のサイトに誘われていきます。

redditを延々眺めていると、QMK Firmware というフレームワークを使っている人が多い模様。

へー、このフレームワークって昔X68000のキーボードコンバータ作ってたバブルボブルの人の後継なんや。懐かしいなぁ。じゃあオレもいっちょやってみよか、という感じです。

やりたいこと

まあ最初ということで いきなり変態チックなのを作らずに、ぱっと見フツーなのを というコンセプトでいきたいと思います。

あえて言わせていただきたいのですが、これは世間一般で言われる「むっつり」とは異なります。
強いて言うなら、そう、ギャップというやつです。
賢明なる諸兄姉におかれましては、どうかそこをお間違えなく。キーマップなんて後でどうにでも出来ますんで。

というわけでコンサバ寄りにやりたいことを並べてみます。

  • 基本はフツーにQWERTY
  • 基板配線がめんどくさそうなので、Underglow などの光りモノは無しの方向で
  • エディタが Emacs + Evil なので CtrlMeta キーは親指にしたい
  • ESCShift キーも親指付近にしたいかな
  • 矢印キーはVimっぽく横一列に
  • 職場は Windowsで F5 とか結構押すし、こいつらはレイヤー切替えなしでいきたい
  • Home, End, PageUP, PageDown とかも念のため置いとこうかな

とか言ってると、なんやかんやで 81キー となり、大きめになってしまいました。
スプリット的なのはまた改めてやるつもりなので今は許してください。

ちょっと前のものですが、初期検討時のキーマップを貼っておきます。

あと、どうせ自作するならポインティングデバイス欲しいよねということで、アナログジョイパッドをつけました。

とりあえず部品など

とりあえず試作と割り切って、部品はDIP品だけで構成したい気分です。
家でSMDをはんだ付けするのしんどいので。

あと、マイコン周りは横着して Arduino 互換ボードで済ませます。ただ、ATMEGA328Pのものではなく USBコントローラ内蔵のAVR(ATMEGA32U4など)が載っているものを選ぶのが無難な感じ。

QMK Firmware のソースを見てると、Pro MicroとかTeensy を使ってる人が多いですが、今回は adafruit の ItsyBitsy 32u4を使ってみました。

マウスポインタとスクロール用のアナログジョイパッドにはPSP的なこれを。
ジョイパッドはホームポジションのまま親指で動かしたいので、別基板にしてキーボードの手前に垂直に立てる算段です。

キーキャップはこんなのを選んでみました。DSAプロファイルでPBT素材。FJ のキートップにはふつうは横棒のエンボス加工がしてありますが、これはその代わりに深く凹んでいるもの(Deep Dish)です。

キースイッチには定番の Cherry MX を使います。
キーの個数は81個なので、これをそのまま全部読むと81本ものデジタル入力が必要になってしまいます。

いい年してそんなアホなことをしてると社会的信用を失いますので、ここは素直にキーマトリクスを考えます。(QMK Firmware はキーマトリクス前提なので心配無用です)

今回のキー配列をマトリクスにすると 7rows/14cols という構成になり、必要なデジタルIOピンは 7 + 14 = 21ピンと、かなり少なくなりました。
対して、使うマイコンボード ItsyBitsy 32u4 はデジタルIOとしては計23ピン使えます。

なんとか収まりそうですが、そうは問屋が卸しません。
今回はジョイパッドのアナログ入力が別途4本必要なので、必要なピン数は 21 + 4 = 計25ピンとなり、このままでは 2ピン足らないです。

というわけでI2C接続のIOエキスパンダを使って、14colsぶんのデジタル入力を I2CのSCL, SDAの2本でまかなうことにします。 QMK Firmware のソースを見ると MCP23018 を使っている人がいますが、ここは秋月で買える下位互換品(?)のMCP23017を使うことにします1

その他の細かな部品は適当に選びました。参考までにBOMを置いときます。

まずは回路から

キーマトリクスは、ROW側をマイコンボード(というかAVRマイコン)の PB1〜PB7の出力に割りつけ、COL側をMCP23017のGPA0〜GPB5の入力に割りつけています。

MCP23017のGPA0〜GPB5の入力は、マイコンからプルアップに設定しておき、アクティブローでキー入力を判定することにします。

次にジョイパッド入力です。
回路的には1つのジョイパッドは X,Y 2本の可変抵抗と等価なので、左右で計4本のAD入力が必要となります。

ジョイパッド 用途 X軸 Y軸
マウスポインタ用 PF4 (ADC4) PF5 (ADC5)
スクロール用 PF6 (ADC6) PF7 (ADC7)

こんな感じに割りつけました。

あと、ポートが余ったので設定変更用のDIPスイッチもつけてみました。
実は QMK Firmware にはすでに Bootmagic というソフト的な設定変更機能が実装されています。
なのでまったく不要なのですが、ハード的なのも趣があっていいかなと。



この手の仕事を家でするときは10年以上Eagleを使ってきましたが、今回は流行りのKiCADを使ってみました。

KiCAD、正直ダルいです^^;
ただ、Eagleもautodeskに買収されてからログインを要求したりウザい仕様が増えてきたので、しばらくKiCADを使っていきたいです。

次に基板を

アートワークもKiCADでやりました。

今回は一次試作ということもあり、

  • キースイッチをはめるトッププレート
  • 筐体となるベース板

を基板材料(T=1.6mm, FR-4)で済ませるべく2、同じ板面に面付けしています。

基板が描けたら一晩寝かせて3ガーバーデータを出力し、基板を発注します。
基板の製造は Elecrowさんにお願いしました。
この面付け5枚に黒レジスト指定で価格は1.4万円くらい4
到着は(サイズが大きかったので難儀したとかで)10日程度でした。

仕上がりについては、レジストのノリやシルクもわりと綺麗でしたし、ドリル精度も申し分ない出来でした。

いよいよ実装を

基板が届いたら、電源ライン周りをチェックしたあと、部品を一つずつはんだ付けしていきます。

こういうのは背の低い部品から実装していくものなので、それに沿って寡黙に続けます。

まずメイン基板にダイオード、抵抗、コンデンサ。次にIC、DIPスイッチときて最後にマイコンボードをつけます。
ジョイパッドは別基板に付けておき、あとでL字のピンヘッダでメイン基板につなぎます。

キースイッチはまず、トッププレートに全部挿し込んでおき、それを裏返した上にメイン基板を載せます。

あとは、足を一本づつはんだ付けしていきますが、基板の反りや部品の浮きを避けるため、まず基板中央付近の1つをメイン基板に押さえながらはんだ付け→次にその半分の中央付近→外端という感じで、内→外に向かってつけていきます。

最後はソフト

まず、ビルドに必要な環境をこの辺りを見て作ります。

次に本家の QMK Firmwareをforkして、さらにそれをローカルにcloneし、そこに自分用のブランチを作成します。

今回はキーボードの名前を asceension 5として、それをブランチ名にしています。本家にプルリクする気はありませんけど。

次にベースとするキーボードを選びます。

keyboardsフォルダ配下には膨大な数の派生キーボードのソースがあるので、その中から自分のしたいことに近いものを選びます。

手頃のなものを見つけたら、makeしてみます。

cd /どこか/qmk_firmware
make ベースのフォルダ名:default

とかするとだいたいOKなはず。
もし手元に Arduino 互換ボードがあれば、USBケーブルつないで書き込みもやってみます。6

make ベースのフォルダ名:default:avrdude

ちゃんとmakeが通ったら、そのフォルダをコピって自分のソースフォルダを用意します。

cp -a base-dir handwired/asceensionとかしてパクりました7

あとは、ひたすら ソース変更 → make → テスト を繰り返していきます。

下記は主な変更/作成ファイルです。

ファイル 内容
keymaps/default/keymap.c 自分的なキーマップ変更
rules.mk 自分的なmakeの設定。デバッグ出力の有効/無効などもここ
readme.md 自分的なREADME
asceension.c 自分的なメインっぽい処理
analogpad.c ジョイパッド処理 …ですが実用的にはちょっと難あり
dipsw.c DIPスイッチ処理
config.h ホストに返す VID, PIDの設定はここ

アナログジョイパッド処理は、promethiumというキーボード(電池電圧読んでる?)とdichotemyというキーボード(シリアル経由でロータリーエンコーダ??)を参考にさせてもらいました。

AVRは10年ぶりくらいだったので、いろいろ忘れてて大変でした。

CADデータとかソースコードは GitHub に置いときます。

振り返りとか

実際作ってみると、いろんな問題があるもんです。

  • アナログジョイパッドはやっぱりちょっと実用性に欠ける
  • 矢印キーをホームポジション以外でVim配列にしても脳が受け付けてくれない
  • 長いキー(Enter など)にはスタビライザーをつけるべきだったかも
  • 回路や基板の誤りもいくつか8
  • DIP品でもはんだ付けはダルい
  • micro USB ソケットがモゲやすいので、次は Type-C にしたい
  • AVR マイコンはもうコスパ的につらいので、そのうち ARM Cortex M4 とかにしたい
  • ソフトは深いところがまだよくわかってない(レポート送信等)

イケてなかったところはこんなところです。

感想など

そういえば昔、HHK のキーマップを変えたくてキーボードコントローラを自作したことがありました。

そのときは Cypress の EZ-USB を使って基板を起こし、USB や HIDクラスなんかを勉強しながら実装していったので、かなり時間かかった記憶があります。

それを思うと、マイコン周りはArduino互換品を買ってくればいいですし、ソフトのフレームワークは QMK Firmware を使えば、ブレッドボードでも確認できるので、かなり楽になったと思います。

そういえば、QMK Firmware 自体は C言語と 一部 C++ で書かれているようです。
組込みで実用的に C++ を試すにはいい材料だと思いました。

さて、いろいろ失敗したので今年中に次の基板を描きたいところですが、その前にまずはまともなケースを作らなければと思っています。

少しだけ概要を書くつもりが、長くなってしまいました。
コーヒーについてはまたそのうち書かせていただけたらと思います。

それでは良いお年を。


  1. データシートをざっと見た感じ、MCP23018 と MCP23017 の違いはI2Cの上限速度だけっぽいですし、今回のI2Cは400kHz程度と問題ないので。 

  2. トッププレートは真鍮板で、筐体は3Dプリントか亜鉛鋼板でやりたかったですが。 

  3. 一晩寝かせると失敗や改善点が見えてくるので。 

  4. 工場の歩留まりがよかったのか、6枚届きました。 

  5. タイポしてます。キーボードだけに -_-; 

  6. 最後に指定するavrdudeなどは、使う基板ごとに異なるので、こことか確認です。あと、書き込み時にブートローダに入れる操作も若干異なります。 

  7. 今回は試作なのでkeyboards/handwiredフォルダの下に作りました。 

  8. ダイオードが逆とか、USBコネクタのピン配列が逆とか、アナログジョイパッドの足が入らなかったとかとか