工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

Arduino 64キー プロトタイピング キーボードマトリックス: シフトレジスタで自作キーボード

部品と材料

部品数量
Arduino UNO1
1N4148 高速スイッチングダイオード64
タクトスイッチ 6×6×5mm (トップアクチュエート)64
ピンヘッダー (1×8)2
74HC595 シフトレジスタ1

必要な工具

アプリとオンラインサービス

プロジェクト概要

更新: コードを改良しました (文末の「Update」参照)。

統合キーボードを必要とするプロジェクトで、開発ボード上にキーボードをどう実装するかという課題に直面しました。USBキーボードや既存のArduinoベースキーボードは使えません。実際のプロジェクトではキーボードがメインマイコンに直接接続されるためです。そこで、この PCBベースの64キー プロトタイピング用キーボードマトリックス を設計しました。

このPCBにはICを一切搭載していません。キーマトリックスの行と列が直接ピンヘッダーに接続されているため、Arduinoや任意のマイコンに接続可能。統合キーボードを搭載するプロジェクトのプロトタイピングに最適です。

詳細なコメント付きコードを同梱。I/Oピン11本 (行8 + 列3 for シフトレジスタ制御? 実際は列8本直接入力 + シフトレジスタ制御3ピン = 11ピン) で動作するあらゆるArduino互換ボードで使用可能。64キーにはシフト、キャップス、Ctrl、Alt、Fn、「スペシャル」キーの修飾キーに加え、用途自由な6キーを含む。全キーの機能を修飾キーとの組み合わせ含めて個別に定義可能 で、既存のキーボードコードより 大幅に柔軟 です。

提供コードはシリアル出力しますが、表示先をOLED等に変更するのは容易 (Arduino IDEの「すべて置換」で Serial.print を display.print 等に一括変換)。

プログラムサイズについて

ライブラリを一切使わずスクラッチで書いたためコードは大きめです。Arduino UNOではプログラム領域 9100 バイト (28%)、グローバル変数 394 バイト (19%) を使用。より効率的な書き方やライブラリは存在しますが、全キー×全修飾キーの完全なカスタマイズと、実用的なキーボード挙動 (例: CapsLock有効時のShiftで小文字になる等) を両立させるにはこのアプローチが必要でした。

ステップ1: キーボードマトリックスの仕組み

なぜマトリックスが必要か? 64キーを直接接続すると64本のI/Oピンが必要。マトリックス化すれば ピン数 = キー数の平方根 (切り上げ) で済みます。行ごとにスイッチを共通接続、列ごとにも共通接続し、行を順次アクティブ (LOW) にして列をスキャンします。

スキャン方法: マイコンの内蔵 プルアップ抵抗 を列ピンに使用。通常時は全行 HIGH。スキャン対象の行のみ LOW にし、押下されたキーの列が LOW になるのを検知。ATmega328Pにはプルダウンがないためプルアップを使用。この処理を高速に繰り返し (コードでは200回/秒に制限)、全キーをスキャンします。

ダイオード、ゴースト現象、Nキーロールオーバー: ダイオードは特定キー同時押し時に意図しないキーが検知される「ゴースト」を防ぎます。ダイオードは一方向のみ導通するため、隣接スイッチ経由の迂回電流を遮断し、Nキーロールオーバー (任意のキー組み合わせ同時押し対応) を実現します。

シフトレジスタでピン節約: 理論上8行×8列=16ピン必要ですが、74HC595シフトレジスタ で行側 (出力) を制御し、Arduino側は3ピン (Data, Latch, Clock) で済みます。入力側 (列) にもシフトレジスタ (並列入力シリアル出力型) を使えばさらに節約可能ですが、ノイズ/チャタリング対策が複雑になるため今回は見送りました。

ステップ2: PCB設計

KiCADで設計 (Eagle派の方ごめんなさい)。回路図: スイッチ+ダイオードシンボルを64個配置、1×8ピンヘッダー2つ (行用・列用) を追加。フットプリント割り当て時、KiCADのダイオードシンボルとフットプリントでピン番号が合わない問題に遭遇 (初版基板は廃棄)。修正版ではカスタムフットプリントでピン番号を入れ替え対処。基板外形はFusion 360で設計しDXFでインポート。配線は2層基板でビアも使用。ガーバーファイル一式をZIPで提供 (Google Driveリンク)。JLCPCB等に直接アップロード可能。

ステップ3: PCB実装

最も単調だが簡単な工程。スルーホール部品のみ。ダイオードの向き (マーク合わせ) に注意。サードハンドで基板固定 → ダイオード全挿入 → 裏返してはんだ付け → リードカット → タクトスイッチ全挿入・はんだ付け → ピンヘッダーはんだ付け。ピンヘッダーはオス/メスどちらでも可。オスを基板裏に付ければブレッドボード直挿し可能。

ステップ4: Arduinoとの接続

列ピン (8本) → Arduino直結:

74HC595 配線 (ブレッドボード中央溝にまたがって配置、ピン1は刻印側):

Arduino D0, D1 (シリアル用) は未使用。

ステップ5: Arduinoコード書き込み

提供コードを通常通りアップロード。詳細コメント付き。メインループはタイマー関数で、5msごとにキーボードスキャン関数を呼出し。スキャン関数は行ごとにシフトレジスタ更新 → 8列チェック。押下キーをシリアル出力。

キー機能の変更: 各キー・修飾キー条件に対応する Serial.print("_"); を書き換えるだけ。例: Fn+N 押下時の出力等、全組み合わせカスタマイズ可能。バックスペース等はシリアルモニターでは効かないが、独自実装で対応可能。

自作プロジェクトへの組み込み: Serial.print を対象デバイスの出力関数に置換するだけで統合可能。

2021/1/30 更新版コード (大幅リライト)

オリジナルコードは「最後に押されたキー」を追跡する方式で、複数キー同時押しや連打 (「bummer」の 'mm' 等) で文字化けや入力漏れが発生していました。新版は キーボード全体の状態を前回ループと比較 する方式に変更。これにより:

トレードオフ: ダイナミックメモリ使用量増 (605バイト, 29%) だが、プログラム領域は大幅削減 (3532バイト, 10%)。

コード (更新版 ProtoKeyboardV1-Bits.ino)

/* Sketch for Prototyping Keyboard V1.2
 * by Cameron Coward 1/30/21
 * Tested on Arduino Uno. Requires custom PCB and 74HC595.
 */
const int rowData = 2, rowLatch = 3, rowClock = 4;
const int colA = A0, colB = A1, colC = A2, colD = A3;
const int colE = A4, colF = A5, colG = 5, colH = 6;

const byte shiftRow[] = {B01111111, B10111111, B11011111, B11101111,
                         B11110111, B11111011, B11111101, B11111110};
byte rowState[8] = {0}, prevRowState[8] = {0};

// キーコード配列 (ASCII): 無修飾, Shift+Caps, Shift, Ctrl, Spcl, Alt, Fn, Caps
const char key[] = { ... 64要素 ... };
const char capsShiftKey[] = { ... };
const char shiftKey[] = { ... };
const char ctrlKey[] = { ... };
const char spclKey[] = { ... };
const char altKey[] = { ... };
const char fnKey[] = { ... };
const char capsKey[] = { ... };

long previousKeyboardMicros = 0;
long keyboardInterval = 500; // μs
int rowToCheck = 0;
bool caps=false, shift=false, capsShift=false, ctrl=false, spcl=false, alt=false, fn=false;

void setup() {
  Serial.begin(9600);
  pinMode(colA, INPUT_PULLUP); ... pinMode(colH, INPUT_PULLUP);
  pinMode(rowLatch, OUTPUT); pinMode(rowClock, OUTPUT); pinMode(rowData, OUTPUT);
  updateShiftRegister(B11111111);
}

void loop() { mainTimer(); }

void mainTimer() {
  unsigned long currentMicros = micros();
  if(currentMicros - previousKeyboardMicros > keyboardInterval) {
    previousKeyboardMicros = currentMicros;
    checkKeyboard();
  }
}

void updateShiftRegister(byte row) {
  digitalWrite(rowLatch, LOW);
  shiftOut(rowData, rowClock, MSBFIRST, row);
  digitalWrite(rowLatch, HIGH);
}

void checkKeyboard() {
  updateShiftRegister(shiftRow[rowToCheck]);
  // 8列チェック → rowState[rowToCheck] の各ビット設定
  updateShiftRegister(B11111111); // リーク防止
  rowToCheck = (rowToCheck + 1) % 8;
  if (rowToCheck == 0) checkPressedKeys(); // 8行完了でキー処理
}

void checkPressedKeys() {
  // 修飾キー状態取得 (行/列ビット位置で判定)
  shift = bitRead(rowState[5],1) | bitRead(rowState[6],4);
  ctrl  = bitRead(rowState[6],5) | bitRead(rowState[7],3);
  spcl  = bitRead(rowState[6],6) | bitRead(rowState[7],2);
  alt   = bitRead(rowState[6],7) | bitRead(rowState[7],1);
  fn    = bitRead(rowState[7],4);
  capsShift = (shift && caps);

  for(int i=7;i>=0;i--) for(int j=7;j>=0;j--) {
    bool newBit = bitRead(rowState[i],j);
    bool prevBit = bitRead(prevRowState[i],j);
    if(newBit && !prevBit) { // 立ち上がりエッジのみ処理
      int thisChar = i*8 + j;
      if(capsShift) processKey(capsShiftKey[thisChar]);
      else if(shift) processKey(shiftKey[thisChar]);
      else if(ctrl) processKey(ctrlKey[thisChar]);
      else if(alt) processKey(altKey[thisChar]);
      else if(spcl) processKey(spclKey[thisChar]);
      else if(fn) processKey(fnKey[thisChar]);
      else if(caps) processKey(capsKey[thisChar]);
      else processKey(key[thisChar]);
    }
    if(newBit) bitSet(prevRowState[i],j); else bitClear(prevRowState[i],j);
  }
}

void processKey(char receivedKey) {
  if(receivedKey == 7) caps = !caps; // CapsLockトグル (ASCII 7 = BEL)
  else Serial.print(receivedKey);
}

カスタムパーツとエンクロージャ

PCB製造用ガーバーファイル一式 (keyplots_4xipOSLHzg.zip) を製造サービスにアップロード。

回路図

回路図PDF (schematic.pdf) を参照。

製造プロセス

  1. Arduino Nano 33 IoT製 フライトシミュレーター2020用コックピットパネル - LCD&CDI表示
  2. Microsoft Flight Simulator 2020用Arduinoスイッチ&LEDパネル
  3. MIDIキーボードをArduino・LED・MuseScoreでスマートピアノチューターに変身
  4. Arduino Unoで8×8 LEDマトリックスを制御:ステップバイステップガイド
  5. 学校向けスマート体温監視システム: 正確、リアルタイム、安全
  6. Arduino用8ビットI/Oポートライブラリ:デジタル制御を拡張
  7. Arduino Nano用 高性能2.8インチTFTシールド - 320×240 SPIディスプレイ
  8. Arduino用絶縁アナログ入力回路の設計:LM331 V-F変換+フォトカプラでノイズ耐性を確保
  9. Arduinoで作る電卓 - 16x2 LCDと4x4キーパッドで四則演算
  10. DCモーター制御の極意:PID制御とPWM出力による速度・方向制御のエキスパートガイド
  11. Arduino向けスマート屋内ナビゲーションロボットキット