この記事はキーボードカレンダーの14日目の記事です。 昨日の記事はmarksardさんの60%トレイマウントケースでTS配列です。

キーボード自作では、マイコンとキー本体を配線する必要があるが、 キーの押下をうまく検出するための配線には複数の種類がある、 キーボードを自作するためにはこれを状況によって選択する必要があるので、 ここに整理しておく。

GPIO

まず、分類を並べるまえに、 必要な知識として、 マイコンのGPIOポート(General purpose Input-output port:汎用入出力ポート) について必要な事に絞って整理しておく。

自作キーボードで良く使われているAVRに内蔵されているGPIOは、4つのモードがあるが、 自作キーボードファームウエアでは主に次の2つのモードが使われている。 モード名は、Arduinoの定数名を使って書く。

AVRには同じ回路がGPIOポートの数だけ搭載されている。 例えば、自作キーボードで良く使われているマイコンボードのProMicroでは 18のGPIOポートにつながったピンある。

入力プルアップモードINPUT_PULLUP

このモードでは、AVRの中身は次のような状態になる。

入力モード

入力モードなので、V?と書かれた所の電圧を調べて、 HIGHかLOWかに変換してプログラムから読む事ができる。

ピンと5Vの間が抵抗で繋いである(プルアップしてある)事により、 このピンに何も接続されていない状態ではHIになり、 このピンにGNDが接続されると、LOWになる。 LOWをキー押下とするのが一般的のようだ。

入力モード押下

HIかLOWかは電圧で決まり、2.2-2.7V(ATMega328の場合)や、1.5V-1.6V(ATMega32u4の場合)などに閾値がある。 閾値より高い電圧だとHIGHになり低い電圧だとLOWになる。

OUTPUT-LOW

このモードでは、AVRの中身は以下のようになっている。

出力モード

この状態では、ピンからの状態は読みこめない。 読もうとしても常に0Vになっているからだ。

分類

このGPIOポートについての整理をふまえて、実際の分類を整理したい。

直接接続(DIRECT_PINS)

一番簡単な配線が直接接続だ。

具体的にはGPIOピンに、キーを直接接続する。

直接

配線が簡単なかわりに、 GPIOピンの数より沢山のキーが認識できない。

ピン数がNピンある時にNキーまで接続できる。 18ピンあるPro Microでは18キーまでになる。

18キーまでなら、この方式が一番簡単だ。 これで足りない場合は別の配線方法を検討する必要がある。

マトリクス

マトリクス配線とは、縦線(COL)と横線(ROW)を用意してその間にキーを配置する方法である。

matrix

まず、全てのGPIOをINPUT_PULLUPに設定する。 そして、横線の1つをGNDと接続する。 これは、OUTPUT-LOWに設定したGPIOを使って達成できる。 縦線は全てINPUT_PULLUPのままにしておく。 この状態で縦線を見ていくと、押されたキーにつながっている線だけ0Vになっている。 これを横線の分繰り返すと、全てのキーがチェックできる。

matrix押下

メリットは直接接続より沢山のキーを接続できる事だが、 一方で、複数のキーの同時押しの認識に失敗してしまう事がある。 下の図では3つのキーが押されているが、 4つ目のキーが押されているように認識されてしまう。 この4つ目の押してないキーが押されたように見えてしまう事をゴーストと呼ぶ。

matrix ghost

そこで、これを解決するために次に説明するダイオードを挿入する方式がある。

N個のピンに対して、N^2/4個のキーが配置できる。 18ピンあるProMicroでは、81キーまでサポートできる。

マトリクス+ダイオード(COL2ROW)

マトリクスの問題は信号がまわりこんで、誤検知がおこることだった。 この誤検知を回避するために、 ダイオードという半導体素子を挿入する手法が発明された。 ダイオードは一方向にだけ電気をながし、 反対方向には全く流さないという素子である。

ダイオード

自作キーボードでは、1N4148などが良く使われている。

マトリクス配線では、一般的にはマトリクス内の各キーにダイオードを配置する。

matrix COL2ROW

このダイオードがある事により、複数同時押しを行っても、 誤検知は回避できる。

matrix COL2ROW OK

この図では、上の行で押されているキーが、 ダイオードの働きで押されていないのと同じように電気を通さなくなっている。

マトリクス状なので、N個のピンに対して、N^2/4個のキーが配置できる。 18ピンあるProMicroでは、81キーまでサポートできる。

18個より多いキーをつけたいが81キーを越えない場合はこれを選ぶことが多い。 一番採用例が多いようだ。

マトリクス+ダイオード逆向き(ROW2COL)

前の方式のダイオードを逆にしてみた。

matrix ROW2COL

先程のCOL2ROWでは、行の1つを選んで、それに対して列を見ていたが、 この場合は、列を1つ選んで、それに対する行を読む。

単に全体を90度傾けただけとも言える。

キーの数に関する特性は変わらない。 マトリクスなので、N個のピンに対して、N^2/4個のキーが配置できる。 18ピンあるProMicroでは、81キーまでサポートできる。

倍マトリクス

上にあげたマトリクス配列は、 行から列に電気が流れるか、列から行に電気が流れるか、 そのどちらかで構成されていた。

仮に逆方向に電圧をかけても、 ダイオードがあるため、逆方向には電気が流れない。

そこで、この2つのマトリックスを重ねる事で、 キーの数を倍にできないかを考えてみる。

倍マトリクス

この文章を注意深く読んだ人は、 この方式ではマトリクスの説明の所で説明したゴーストが発生するのではないかと指摘するのではないかと思う。

倍マトリクスは動かない?

しかし、実際に作ってみるとゴーストが発生しない事がわかる。

理想的なダイオードは片方に電気を完全に通し、 逆方向には全く通さない。 しかし、現実のダイオードはいくつか理想的ではないふるまいをする。 例えば、ダイオードを図のように接続すると、完全に0Vではなく電位差がある。 良く使われている1N4148はキーボードに使うと最高0.9V低くなる。

ダイオード Vf

GPIOの説明に書いた通り、GPIOはある閾値電圧より上か下かで判断するが、 この場合、ゴーストの発生が予想される箇所では3つのダイオードを通過している。 そのため、この場所は0.9V*3 = 2.7Vになり、 GPIOがLOWと認識する電圧を越えるため、 キーが押されているとは認識されない。

ダイオード Vf3

ピン数がNピンある時にN^2/2キーまで接続できる。 18ピンあるProMicroでは、162キーまでサポートできる。 単純なマトリクスの倍のキーを使う事ができる。

81キー以上のキーを置きたい場合にこれを選ぶといいだろう。

2乗マトリクス

倍マトリクスでは、マトリクスを倍にする事を提案した。 これを更に推し進めて、すべてのピンの間にキーを配置する事を考える。

Square matrix

このままではわかりにくいので、マトリクス状に並べてみる。

Square matrix fix

通常のマトリクスと違って、COL側にのみGPIOに接続する事に注意。

この方式の注意点も、閾値電圧だ。 倍マトリクスと違い、ゴースト部分の電圧はダイオード2つ分であるので、 慎重に部品の組合せを考える必要がある。 もしくは、ダイオードを1キーに対して2つずつ繋ぐ必要があるかもしれない。

Square matrix ghost

ピン数がNピンある時に(N-1)*Nキーまで接続できる。 18ピンあるProMicroでは、306キーまでサポートできる。

162キーでも足りないという場合、 もしくは、使うGPIOポートを最小化したい場合はこれを考えてもよさそう。

その他の分類

ここまでは、回路の工夫でキー数を増やしてきたが、 ここからは、マイコン以外のICを追加する事でキー数を増やす方法を整理したい。

デコーダ

マトリクス配線を元に考える。 例えばCOL2ROWでは、1つのピンだけLOWで他はHIGHに設定した。

デコーダICを使うと、2進数でピンを選んで設定できる。

デコーダ

シフトレジスタ

シフトレジスタは、Nピン分の信号をシリアルに変換できる、 もしくは、シリアル信号をNピン分に変換できるICだ。

また、シフトレジタは直列に何個でも接続できるので、 (動作速度さえ許せば)いくらでも増やす事ができる。

シフトレジスタ

IOエクステンダ

シフトレジスタは簡単な入力(か出力)しかできないが、 IOエクステンダICは、マイコンにGPIOを追加できる。

IOExtender

マイコン追加

実はIOエクステンダはマイコンより値段が高い事がある。 単にマイコンを複数搭載して数を増やすのも手かもしれない。

split

これは単に分割キーボードで良く行われている。

また、追加したICを使って、マトリクスを構成して更にキーを増やす事もできる。

まとめ

みんなもっとキー増やそうぜ。

明日はsirojakeさんのDMMの3Dプリントでフルカラーキーキャップを自作するです。

※この記事は、自作のATmega328ベースのレップリで書きました。

更新: 12月28日

ProMicroのピン数を19ピンとしてましたが、18でした。計算しなおしました。 指摘いただいたあぷろさん、ありがとうございます。