質問やフィードバックがありましたら、フォームからお願いします
本文は台湾華語で、ChatGPT で翻訳している記事なので、不確かな部分や間違いがあるかもしれません。ご了承ください
押されたキーの検出
前回述べたように、キーボードは実際には複数のスイッチで構成された回路です。マイクロコントローラのGPIOピンを使用して、スイッチが押されているかどうかを検出することができます。具体的な方法は、スイッチの一端を電源に接続し、もう一端を接地します。キーを押すと回路が導通し、マイクロコントローラはこの変化を感知して、対応する信号を送信します。実際にどのような信号が送られるかについては、後の章で触れます。
しかし、これには欠点があります。各キーには1つのピンが必要であり、104個のキーを持つキーボードの場合、マイクロコントローラには104個のピンが必要です。通常、マイクロコントローラにはそれほど多くのピンは使用できず、または一部のピンは他の用途に使用する必要があります。
スキャンとキーボードマトリックス
実務では、マトリックス接続方式を使用してキーボードの回路を接続します。各マトリックスはマイクロコントローラのピンに接続され、たとえば60個のキーを持つ場合、6x10のマトリックスでは16個のピンで済みます。
R1、R2、R3をそれぞれ高電位に設定し、C1、C2、C3の電位を読み取ることで、どのキーが押されたかを知ることができます。たとえば、下の図のキーが押された場合、C1は現在の電位が高電位であることを読み取ることができ、どのキーが押されたかを検出できます。
ここでの順序は以下の通りです:
- R1を高電位に設定
- C1を読み取る
- C2を読み取る
- C3を読み取る
- R2を高電位に設定
- C1を読み取る
- C2を読み取る
- C3を読み取る
- R3を高電位に設定
- C1を読み取る
- C2を読み取る
- C3を読み取る
理想的にはマトリックスの行と列の数が同じであるべきですが、実際にはそうではない場合があります。一つは、マイクロコントローラのピンが通常十分であるため、もう一つは、無理に二つの数を揃えるとレイアウトが非常に難しくなることがあります。たとえば、キーボードは横列が多く、直列が少ないことが一般的です。
ここで疑問が生じるのは、R1とR2のキーが同時に押された場合に検出できないのではないかということです。実際には同時に検出するのではなく、順番に検出します。この点は心配する必要はありません。一般的なマイクロコントローラは少なくとも16MHz以上の速度を持っており、検出速度は人体の限界をはるかに超えています。マイクロコントローラは最初に押された状態を記憶し、再度読み取ったときに以前の状態と異なることを検出すると、放されたという信号を再度送信します。
ゴースティング
先ほどの回路には問題があります。もしR3にもスイッチが押されていると、一部の電流がここを通って誤判定を引き起こす可能性があります。これを解決する方法は、ダイオードを追加することです。ダイオードは一方向導通の機能を持ち、電流は一方向にしか流れないため、ゴースティングを防ぐことができます。
HID(Human Interface Device)
次に、信号をコンピュータに送信するロジックに移ります。初期のキーボードはPS/2コネクタを使用していましたが、現在最も一般的なのはUSBとBluetoothです。
HIDは、キーボード、マウス、コントローラなど、さまざまな一般的な入力デバイスのプロトコルを規定することで、以前は追加のドライバを書く必要があったコストを、HID規格に従うだけで、どんなデバイスでもドライバなしで実行できるように簡素化しています。
HIDには入力レポート、ディスクリプタ、出力レポートが含まれます。通常、ディスクリプタはこのデバイスが何であるかを説明するために使用され、用途、名前、メーカー、IDなどを含みます。コンピュータはこれらのレポートを読み取ることで、どのように処理すべきかを理解します。
USB
一般的に、マイクロコントローラ内にはUSB機能があり、USB形式でデータを送信することができます。
HIDも同様で、一般的にはUSBまたはBluetoothを介してデータを送信します。しかし、ここではエンジニアが特に気にする技術的な詳細について言及します。USBはホストとデバイスに分かれます。
マウスやキーボードなどの入力デバイスは、CPUと比べて通常は非常に遅いため、CPUがこれらのデバイスの入力を待つと、非常に効率が悪くなります。実際の方法は、コンピュータのUSBコントローラ(ホスト)がデバイス側からデータを継続的にプルし、バッファにデータがあるときにCPUの割り込みを呼び出すことです。そのため、キーボード側ではデータを常に送り続け、残りはホスト側で処理されます。
通常、HIDのフォーマットを書く方法は、実際の操作の中でライブラリが処理してくれるため、対応するキーを対応するキーにマッピングすることに集中すれば大丈夫です。
ここにRaspberry Pi picoの例を示します:
static void send_hid_report(uint8_t report_id, uint32_t btn)
{
// hidがまだ準備できていない場合はスキップ
if ( !tud_hid_ready() ) return;
switch(report_id)
{
case REPORT_ID_KEYBOARD:
{
// キーボードの複数の連続ゼロレポートを送信しないための使用
static bool has_keyboard_key = false;
if ( btn )
{
uint8_t keycode[6] = { 0 };
keycode[0] = HID_KEY_A;
tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode);
has_keyboard_key = true;
}
...
}
この例では、1つのボタンだけで、常にAキーです。しかし、コードから大体の書き方がわかります。コードはまず配列 keycode
を宣言します。長さ6は同時に6つのキーを送信できることを示し、ここでは keycode[0]
のみを使用し、tud_hid_keyboard_report
を呼び出してHIDレポートを送信します。
回路基板の設計と配線
私自身は回路基板設計に詳しくありませんが、基本的な知識さえあれば誰でも回路基板を作ることができることを説明したいと思います。回路基板設計において非常に有名なオープンソースソフトウェアはKicadで、完全に無料です。
このソフトウェアを使用すると、自分の設計したい回路を自分で設計でき、PCBレイアウトの配線もサポートしています。設計した回路を基板に配置し、配線を引くことができます。
すべてが整ったら、回路図(専用のファイル形式があります)を出力してPCB印刷会社のウェブサイトにアップロードすれば、数週間後には製品を受け取ることができます。一般的な安価な業者にはJLCPCBやPCBWayがあります。
QMK
カスタマイズキーボードのコミュニティには、LEDの点灯方法や配列の変更、キーボードにノブを追加したり、LCD画面を設置したりすることに対して非常にこだわるプレイヤーがいます。みんな独自の基準を持っているため、ハードウェアの面でもさまざまな工芸品が展開されるだけでなく、ファームウェアでも高度なカスタマイズが求められます。
(画像はZoom75公式サイトから引用)
理論的には、マイクロコントローラと回路があればキーボードファームウェアを書くことができますが、毎回キーボードの配置を変更するたびにコードを修正しなければならず、マイクロコントローラを交換すると再度書き直す必要があるのは非常に面倒です。そのため、一部のプレイヤーは高度にカスタマイズ可能なファームウェアを自作し、キーボードに関連する設定を定義するだけで、自動的に対応するファームウェアを生成できるようにしています。
現在、キーボードコミュニティで最も有名なのはQMKで、これはtmkから派生したオープンソースファームウェアです。キーボードコミュニティで非常に一般的で、KeychronなどもQMK設定をサポートしています。
先ほど触れた機能は、QMKにはほぼすべてあります。キーの定義、マクロ、LCD、LED制御、Bluetooth、ジョイスティック、さらにはMIDIなど、思いつく機能はQMKにはほぼ揃っています。また、サポートされるカスタマイズキーボードも多数あり、私が現在使用しているZoom65の定義ファイルはこちらで見つけることができます。
さらに驚いたことに、現在はWeb USBもサポートされており、直接インターネット上でキー配置を変更し、変更後にファームウェアの設定を調整することができます。
詳細な原理についてはまだ研究していませんが、おそらく対応するコード実装があり、Web USBを介して直接データがキーボードのファームウェアに送信されるのだと思います。興味のある方はVIAを参考にしてください。
結論
現在、多くの回路基板や外装にはオープンソースのモデルや回路設計が参考にできるものがあります。「ゼロから」自分でキーボードを作るのは依然として難しいですが、昔に比べればかなり容易になっています。しかし、その背後のプロセスを理解するだけでも、キーボードを作るのはそれほど簡単ではないと感じるでしょう。
この記事が役に立ったと思ったら、下のリンクからコーヒーを奢ってくれると嬉しいです ☕ 私の普通の一日が輝かしいものになります ✨
☕Buy me a coffee