自作キーボード設計入門2を読みながらいろいろ試してみました

最初に組み立てたErgoDash、2つ目に組み立てたClaw44、これらに共通して言えることは、「個人の誰かが設計し、キット化して売り出しているキーボード」であるということです。つまり、キーボードは自分で設計し、部品を集めさえすれば、自分でいかようにも作り出せるということです。

キーボードはメーカーが作って売って、それを買って使う。ちょっと前まではこれしか知りませんでしたが、組み立てキットを購入してハンダ付けして完成させ使う、コレだけではすぐに物足りなくなってきてしまいました。

「自分だけのキーボードをいつか作ってみたい」

そう思うようになってしまったのです。

そのために必要となる勉強は、かなりの量になるんじゃないかと思っています。別に何も焦る理由はないので、今までソフトウェアを作ることしかしてこなかった自分ですが、ハードウェアという新しい世界にちょっと足を踏み入れてみたくなり(世間ではこれを「沼に浸かる」と表現するんだそうです)、ゆっくりと勉強を始めることにしました。

とは言え、なかなか勉強するにも、何から手を付けていいかわかりませんでした。組み立てキットの中には、基板などの設計を公開しているものもあって、それを見ればどう作るのか「ある程度の前提知識を持っていれば」わかるかと思います。でも、僕はそういった前提知識がほとんどありません。「え、抵抗?電圧低下させるものでしょ?でも、それの何が美味しいの?」というレベルです。

幸いなことに、Corne Cherryなどを設計した @foostan さんが、自作キーボードの設計方法についての書籍を出されています。これを読んで勉強を始めることにしました。

1と2があるのですが、両方とも購入して眺めてみたところ、2から始めたほうが良さそうだ、と気が付きました。2であれば、必要な部品さえ購入して準備できれば、手軽に試していけそうだったからです。

自作キーボード設計入門(電子版) - Pastry Keyboard - BOOTH

自作キーボード設計入門2(電子版) - Pastry Keyboard - BOOTH

このエントリでは、自作キーボード設計入門2を実際に試していった際のログとなります。

購入したもの

設計入門2では、数多くの部品を使います。まずはそれら部品の購入をしました。具体的には、以下となります。

結構な数の部品となりましたし、金額も総額としては結構行きます。まあ、授業料ということで、良いかな、と。

抵抗やダイオードなどは、100個入りとか買ってますが、その方が単価としては安いので選択してます。もちろん、試す際にはそんなに使わず、使っても一桁です。いつか自分のキーボードの設計を行う際に使えるかな、と先行投資として、大事に取っておこうと思ってます。

どれも通販で購入可能です。遅くても2,3日待てば家に届くでしょう。

無印でケースを買ってきて、部品を全部収めてみました。

キーボードを動作させるためのソフトウェアであるQMK Firmwareに関しては、すでにErgoDashやClaw44にて経験をしていたので、ProMicroにファームウェアを書き込む手順などはすでに知っている状態でした。なので、PC側の準備は整っています。ちなみに、普段からKubuntu 20.04にて開発をしているので、その環境でソフトウェア側の環境を作ってあります。このエントリでは、ファームウェアの書き込み方法などは説明しません。

1キーのキーボード作成

最初に取り掛かったのは、キーが一つしかないキーボードを、ブレッド上で再現することです。これは、かなりシンプルに作れました。

たったこれだけです。スイッチが2つあるのは、一つはキーコードを送り込むためのキー、そしてもう一つは、リセットスイッチです。リセットスイッチを設置しておくことで、ファームウェアを書き込む際にピンセットでショートさせるなどのことをしなくても良くなります。

1キーの場合は、キースイッチをProMicroのあるピンとGNDのピンの間に入れるだけです。簡単ですね。

ファームウェアについては、QMK Firmwareで新規にキーボードを作成します。この際、設計入門2の中では、 ./util/new_project.sh を利用していましたが、現在のQMK Firmwareではそのコマンドは存在していなくて、代わりに ./util/new_keyboard.sh を使えばよいです。その後は、本に書いてあるとおりにコードを修正していけば、1キーのキーボードが完成します。

たった一つしかキーがありませんが、自分で作った回路から文字がPCに打ち込めた瞬間は、かなりのトキメキがあります。ぜひ皆さんにも体験していただきたいです。

12キーのキーボード作成

次は、12個のキーを持つキーボードの再現です。

これも特に難しいことはなく、ProMicroのピンとGND間にキーをおいていけば出来上がります。

ただし、本に掲載されていた図では、右側のGNDが接続されていませんでした。回路図上でもProMicroの裏面の右側にある2つのGNDは未接続になっていました。そのため、ブレッドボードの実装図のまま部品を配置しただけでは、右側においたキーたちは押しても反応しません。

正しくは、ブレッドボード上の右側の3行目もしくは4行目とブレッドボードの右側の+記号の列とを接続して、(+の列に接続はしてはいますが意味的には)キースイッチが全てGNDに接続されるようにすれば、ちゃんとキーが反応するようになります。

コードは以下においてあります。

Add a new keyboard for tutorial. · yoichiro/qmk_firmware@f6d820b

Underglow LEDを搭載したキーボードの作成

次に行ったのは、Underglow LEDの取り付けです。Underglow LEDとは、キーボードの底面にLEDを取り付けて光らせようというものです。実際には、以下のような感じになります。きれいですよね。

先ほどは12個のキーでしたが、それを3つに減らします。そして、LEDテープをProMicroに接続します。

ブレッドボードの下にLEDテープを置けば、名実ともにUnderglow LEDになったのですが、そこまで機転が利かなったのが残念なところです。

ファームウェアとしては、以下の修正を行いました。

Underglow LED. · yoichiro/qmk_firmware@ae9b0f5

Underglow LEDの取り付けは、実はそう難しくないということがこれでわかりました。

OLEDを搭載したキーボードの作成

先ほどは七色に光るLEDの取り付けでしたが、次に行ったのは、OLED、つまり文字表示などが可能な液晶画面の取り付けです。実際のキーボードでは、ProMicroの上に配置していることが多いかと思います。

このOLEDをブレッドボードに追加します。

キーについては、先ほどと同じです。変わったところは、LEDテープを取り外して、その代わりにOLEDを取り付けているところですね。OLEDに、VCCとGND、そして信号を流すために2本の接続をProMicroからOLEDに対して行っています。

ここで、I2CでProMicroとOLEDは通信していることがわかりました。

OLEDに対応したファームウェアの修正ですが、本に掲載されているコードの修正では、Helixにて提供されたコードを利用して実現していますが、現在ではQMK Firmware側で対応がされていますので、 rules.mk ファイルにて OLED_DRIVER_ENABLE = yes してあげればOLEDを利用可能になります。

修正したコードは、以下のような感じです。

Use OLED feature. · yoichiro/qmk_firmware@f34a817

ただし、実際には以下の追記は必要ありません。

#include "lufa.h"
#include "ssd1306.h"

なくてもちゃんとOLEDを表示できるはずです。つまり、以下のコードの記載だけで、OLEDは表示できるようになります。

// rules.mk
OLED_DRIVER_ENABLE = yes

// keymap.c
#ifdef OLED_DRIVER_ENABLE
void oled_task_user(void) {
    oled_write_P(PSTR("Hi, Yoichiro!"), false);
}
#endif

簡単になってます。手軽ですね。

キーマトリクスの作成

最初の方に12キーのキーボードを作成しましたが、そのときは各キーはGNDに接続しました。これだと、ProMicroのピンの数がキー数の上限になるので、実用的ではありません。多くのキーを接続できるようにするために、キーマトリクスというテクニックがあります。次は、キーマトリクスを試しました。

実際に組んでみるまで、キーマトリクスは直感的に入ってこなくてわからなかったのですが、組んでみるとはっきりと仕組みがわかります。特に回路図で見ると、列と行の配線が交差している箇所があり、それが接続されてしまっているのか、その配線は接続されていないのか、不明でした。正解は、接続されていない、でした。

変更したファームウェアの差分は、以下となります。

Implement key matrix. · yoichiro/qmk_firmware@e8e6c39

そして、ダイオードがなぜ必要なのかも、はっきりとわかりました。実際に、一つダイオードを外してみました。

こうしてしまうと、例えば以下のように、左上のキー以外の3つのキーを同時に押した際に、

押していない左上のキーも、押されてしまうことが実際にわかります。これは、ダイオードがないために、本来流れないはずの経路で電流が流れてしまうために発生する事象です。下の図の緑の部分は、ダイオードさえちゃんと実装されていれば、本来流れなかった電流です。それが流れてしまったことで、ぐるっと回って別の行に対するピンにまで電流が流れてしまい、ProMicroが「あ、左上が押されているな」と判断するに至ってしまいました。

本の中でも同じようなことが説明されていますし、全く同じ図が登場しているのですが、実際の回路で現象を再現できると、はっきりとダイオードの役割を理解することができました。

Backlight LED付きのキーボードの作成

ErgoDashを組み立てた際に、各キースイッチに砲弾型のLEDを付けていって、暗い場所でもキーがわかるようにLEDで光らせる「Backlight LED」に対応しました。全てのキーにLEDを付けていくことになり、しかも抵抗もキーの数だけ実装する必要があるため、結構大変だった記憶があります。しかも、取り付けたトランジスタが小さく、表面実装だったこともあり、熱で破壊してしまって苦労したという苦い思い出もあります。

キーマトリクスができた後は、そんなBacklight LEDを試しました。

トランジスタによってBacklight LEDのONとOFFを制御します。そして、LEDの後に抵抗を入れることで、LEDを保護します(LEDの許容電圧内にする)。

ファームウェアについては、以下が変更差分となります。 BACKLIGHT_ENABLE = yesrules.mk ファイルに記載して、 config.h ファイルに Backlight LEDのか色を接続したピンがどれかなどを設定します。

Support Backlight LED. · yoichiro/qmk_firmware@eda4b93

Backlight LEDの仕組みはその部品数の多さから、他よりも難しいのかな、と勝手に思い込んでいましたが、わかってしまえばそう難しいことではなかったです。無事Breathingも機能しました。書籍上はLEDを4つ取り付けていましたが、今回は2つにしましたが、もしキーの数だけBacklight LEDを装着したいってなったとしても、分岐してLEDを増やしていけば良いだけです。

シリアル通信での分割型キーボードの作成

今まではブレッドボードをひとつだけ使って回路を組んでいきました。つまり、これは「一体型のキーボード」を作ってきたことになります。しかし、タッチタイピングができてきた僕にとって、欲しいキーボード、作りたいキーボードは、やはり分割型です。

Backlight LEDの次のテーマとして、分割型のキーボードを試してみます。最初は、データが流れる線が一本だけの、シリアル通信からです。

キーマトリクスを組んだ回路を、2枚のブレッドボードにそれぞれ組んでいきます。キーマトリクスまでは、2枚とも全く同じ回路で構いません。

そして、左右のどちらがマスターになるのかを決めるために、D2のピンを使うようにしています。シリアル通信の通信路は、D0同士を結線します。実際には、この通信路はProMicroからTRSSジャックに向けて結線し、TRRSケーブルが通信路となります。

ファームウェアの変更差分は、以下です。

Split Keyboard with Serial communication. · yoichiro/qmk_firmware@1c06609

ポイントは、以下となります。

  • rules.mk ファイルにて、 SPLIT_KEYBOARD = yes を記載します。
  • config.h ファイルにて、 #define USE_SERIAL を追記し、更に #define SOFT_SERIAL_PIN D0 にてシリアル通信に使用するピンを、 #define SPLIT_HAND_PIN D2 にてどちらのキーボードがマスターになるかを指定するためのピンを、それぞれ指定します。

分割キーボードにするために、基本的にはProMicroのあるピン同士を繋いでしまって、あとはファームウェアを適切に設定すれば終わり、というとてもシンプルな手順をこなせば良いだけです。個人的には、このシンプルさは結構衝撃でした。そして、実際に通信先のブレッドボードの回路からキーを打つことができたのは、感動的でした。

ここまでは、実は一つ作り終えたら、全部部品を外して、ゼロから再度部品を配置していく、という苦行を行っていました。その方が、回路がどのような構成なのか、学習結果が脳に定着するかな、と思って、あえて毎回ゼロスタートしてました。が、もうだいたいわかってきた気がするので、ここから先は全部部品を外すようなことはせず、変更箇所のみを変えていくように切り替えました。

I2Cによる分割型キーボードの作成

シリアル通信の後は、I2C方式によって左右のキーボードを通信する方式に変更することを試しました。

マスターがどちらなのかの判定は先ほどのままとして、シリアル通信では1本だった通信路を2本に増やしています。さらに、マスター側にプルアップ抵抗を2つ実装しています。

ファームウェアの変更は、先ほど config.h ファイルに #define USE_SERIAL と書いていた箇所を #define USE_I2C に変更するのみです。

I2C communication. · yoichiro/qmk_firmware@1faa089

部品数が増えて、通信路も増えている割に、実は実現されることはシリアル通信と変化はありません。I2C方式のほうが速度アップに貢献されるはずなのですが、どうやら体感できるさまではいかないようなので、特に理由がなければシリアル通信で良いのかな、と思ってます。

ここまでで、基本が終わりです。

I2C、キーマトリクス、Underglow LED、スピーカーの合わせ技

ここからは、応用編になります。書籍では、Fourier という昔販売されていてすでに販売終了となったキーボードのブレッドボード上での再現が説明されています。これは、I2Cによる分割、Underglow LEDの対応、そして特徴的なこととして、スピーカーの実装がされています。

ErgoDashにはスピーカーを取り付けることができるように端子が提供されていたのですが、結局今までそれを試してはいませんでした。そのため、スピーカーをキーボードに付けた後どんな音が奏でられるのか、興味津々でした。

最初に部品をいろいろ購入した際に、圧電スピーカーを買っておいたのは、このFourierでのスピーカー実装を実際に試すことができそうだったからです。念願が叶う瞬間です。

書籍では、スピーカーを取り付けるProMicroのピンがC6のみであると読み解ける書き方がされていましたが、QMK Firmwareのドキュメントを見る限り、現状では他のピンも利用可能っぽいです。ただ、今回の試作では、C6を使いました。

Audio

I2CによるProMicro間の接続とUnderglow LEDの取り付けは、前に行ったときと全く同様です。スピーカーのみをC6とGND間に取り付けたのみとなります。

ブレッドボード上での回路ができあがり、さあファームウェアの修正だ!と思ってQMK Firmwareのコードを見てみると、なんと、 keyboards/fourier ディレクトリがありませんでした。「試せないじゃん!」と一瞬思いましたが、きっとFourier特有のコードがあると言うよりは、単にハードウェアの構成に沿った設定がされているだけだろう、しかも結構古めのコードかもしれない、と想像できるので、自分でファームウェアは準備することにしました。

先ほどI2Cでの分割キーボードを試した時のファームウェアのコードから、今回の構成に対応するために修正した差分が、以下となります。

Audio and LED. · yoichiro/qmk_firmware@1641cc7

Underglow LEDについては、 RGBLIGHT_ENABLE = yes にて有効にします。そして、スピーカーについては、 AUDIO_ENABLE = yes によってサウンド機能を有効にして、 #define C6_AUDIO を追記してピンの場所を教えます。

ただし、このままの状態でビルドを行ったところ、ビルド結果がProMicroの容量に収まらないくらい大きくなってしまってビルドが失敗してしまいました。そこで、容量削減のため、Underglow LEDのアニメーションを #define RGBLIGHT_ANIMATIONS によって全部含めていたのですが、それをやめて、 #define RGBLIGHT_EFFECT_RAINBOW_MOOD のみにしました。これにより、ProMicroに収まる大きさでビルドできるようになりました。

ファームウェアを書き込んだ後、さっそくスピーカーから音が出てきました。そして、以下の追記を行っておいたので、キーを押す度に「ピッ」と音を出すことができました。

bool process_record_user(uint16_t keycode, keyrecord_t *record) {
#ifdef AUDIO_ENABLE
    if (record->event.pressed) {
      float my_song[][2] = SONG(QWERTY_SOUND);
      PLAY_SONG(my_song);
    }
#endif
…
}

実際に音を出してみて、キーを押す度に鳴っていてはウザいことに確実になるな、と思いましたが、USBケーブルを繋いだ時に音が鳴ったりするのはとても良いなと思いました。

I2C、キーマトリクス、Underglow LED、スピーカー、OLEDの合わせ技

ここまでで、おそらく一通りのことをやってきたかなと思います。例えば自分でキーボードを設計する際に、個々の構成要素の実装で回路の概要がわからないってことはなくなったかな、と思います。

先ほどのI2C、キーマトリクス、Underglow LED、スピーカーの組み合わせは、実はそれで全部入りとは言えません。これらに対して、更に「OLED」をつけることができてこそ、全部入りかなと思います(Backlight LEDはこの際置いておきましょう)。

設計入門2では、Fourierの次はHelixとなっています。Helixでは、シリアル通信、キーマトリクス、Underglow LED、そしてOLEDの組み合わせとなっていました。僕は、それらに対して、スピーカーを加えた構成で組んでみて、今回の設計入門2を卒業しようと考えました。

実際にやってみた時の映像が、以下となります。

I2Cからシリアル通信に変更しているので、通信路となる配線は1本に減っています。そして、書籍に掲載されていたHelixの回路図を見て気がついたのですが、左右でマスターがどっちになるかを決定させるための配線が、行われていませんでした。ファームウェアのコードを見ても、 #define SPLIT_HAND_PIN D2 が定義されていませんでした。それでもちゃんと通信はできていたので、もしかしたらシリアル通信においてマスターが左右どちらなのかを決定させるための配線は、さっきも省略できたかもしれません。

OLEDはI2Cにて通信が行われるため、さきほどI2CにてProMicro間の通信を実現していた配線をやめて、シリアル通信ではD2を使うようにしました。その分空いたD0とD1には、OLEDを配線します。その他は、先ほどと同じです。

ファームウェアの変更は、以下のようにしました。

Add OLED. · yoichiro/qmk_firmware@37a2657

この差分適用後のビルドでは、あとたった220bytesしか残ってないよ!、という渓谷が出てしまいましたが、なんとか制限範囲内には収まってくれました。

動画を見ていただいてわかるとおり、全てを諦めずに、全部入りのキーボードが、ブレッドボード上とはいえ、実現させることができました!

まとめ

このエントリでは、僕が「自作キーボード設計入門2」を読みながら実際にブレッドボード上で設計を実証していった過程について、簡単に紹介してみました。

全く前提知識がない状態でいきなり基板から入ることは難しすぎて、もしそれを求められていたら、とっくに挫折して諦めていたと思います。しかし、@foostanさんによるこの本があって、僕は自作キーボードの設計のスタートラインに立つために、寝坊せずに寝床から起きあがることはできたかな、と思っています。

やはり、実際に作ってみて動かすことは、何よりも大事なことです。普段からソフトウェア開発をしている僕にとって日々大事にしていることであり、それはハードウェアにおいても一緒なんだな、とこの本を通じて知ることができたと思っています。なにか困った時には、ブレッドボードに戻って実証実験をする、そういった基礎的なノウハウを身につけることができたので、今後何かあったときにも安心感を持って前に進んでいけそうです。

もし自作キーボードの設計に興味を持った方は、ぜひ「自作キーボード設計入門2」を手にしてみてください。そして、読み進めていく中で、このエントリが少しでもお役に立てば、幸いです。

このエントリーをはてなブックマークに追加

関連記事

2023年のRemap

Remapにファームウェアビルド機能を追加しました

Google I/O 2023でのウェブ関連のトピック

2022年を振り返って

現在のRemapと今後のRemapについて