デジタル入力(DI)ピンが足りない場合、キーマトリクスを使う。検索すれば既に情報がいっぱいあるが、めっちゃ丁寧に説明してみる。
Pro MicroなどのArduino系マイコンでは、プルアップ抵抗が内蔵されており(内部プルアップ),それを使えばスイッチをGNDに繋ぐだけでDIができる。
この時点で既にピンとこない人のために、もっとデジタル入出力(DIO)の基礎的な話も別記事に書いておいた。
デジタル入力の基礎的な話 - プルアップとかそんなん - manvaのエンジニアリング魂
では,上記の内部プルアップを用いたアクティブローの回路で,GNDではなく、デジタル出力(DO)に繋いだらどうなるか。DOをスイッチのイメージで描くと,↓のようになる。
DOにLowを出力した時にはGNDに繋いだのと同じだが、DOにHighを出力した時、スイッチがオンでもオフでもHighであり、スイッチの操作が無効になる。スイッチ1つだと、無効とか要らんわ、と思うだろうが、この後のキーマトリクスで使う。
キーマトリクス回路とは,↓のようなものである。
図は,3行3列の例である。とりあえずダイオードは無視して考えると,それぞれのスイッチが、上記のようなアクティブローの回路になっていて、DOで無効化できるようにしていると見なせる。
この例では、3行x3列で9個のスイッチを入力できる。単純にスイッチを1つずつDIに入力したら9ピン必要だが,この回路ならピンの数はDO3本,DI3本の計6本で済む。同様の配線で、行や列を増やすこともでき、行や列の数が多いほどピン数の節約効果は大きくなる。
わかりやすいように電圧がVccになっている線を赤にする↓。
スイッチが全てオフならDOはどれもDIにつながっていないので,DOの状態に関係なくDIは全てHとなる。
また、DOが全てHなら、スイッチが全て「無効」の状態となり,スイッチの状態に関係なくDIは全てHとなる。DOで行ごとに無効化できるため、まず1行目のみを有効にしてDIを読み取り、次に2行目のみを有効にしてDIを読み取り、ということを高速に切替えれば全てのスイッチを読み取れる、という仕組みである。
その時の回路の電圧の状態を詳しく見てみる。DO1のみをLow(有効)にした時、回路の状態は↓のようになる。
一番上の行のスイッチのみが有効となる。
ここで、SW1-1をオンにすると↓
のようになり、DI1がローとなり、SW1-1が押されたことをマイコンで検出できる。
この図を見てみると、このときに、もしSW2-1やSW3-1も同時におされると、ショートすることがわかる(ダイオードが無ければ)。そうならないためにダイオードを入れている。
Arduino IDEで自作キーボードのプログラムをするなら↓こんな感じ。
void loop() { int CurrentKeyState; int i, j; for( i=0; i<NUM_ROW; i++ ){ digitalWrite( rowPin[i], LOW ); for( j=0; j<NUM_COL; j++ ){ CurrentKeyState = digitalRead( colPin[j] ); if( CurrentKeyState==LOW && PreviousKeyState[i][j]==HIGH ){ Keyboard.press( keyMap[i][j] ); }else if( CurrentKeyState==HIGH && PreviousKeyState[i][j]==LOW ){ Keyboard.release( keyMap[i][j] ); } PreviousKeyState[i][j] = CurrentKeyState; } digitalWrite( rowPin[i], HIGH ); } }