LoginSignup
13
7

More than 3 years have passed since last update.

自作キーボードを作った話

Last updated at Posted at 2019-12-17

この記事はキーボードカレンダー2019#2の18日目の記事です。

はじまり

周りのエンジニアが全員メカニカルキーボードを使っているような職場環境なので自分もキーボードを組んでみることにしました。とはいえキーボードキットも安くはないので、どんなデザインが良いのか、試作機を自作してみることにしました。デザインファイルやファームウェアのソースコードは全てGitHubに公開しています。

デザイン

ErgoDox系なのでキー数多めです。OpenSCADを使ってデザインしたものを3Dプリントしています。片面の横幅は約15cmです。たいていの家庭用の3Dプリンターだと印刷できる底面積は15cm x 15cm程度なので、今回のデザインがギリギリの横幅となります。

IMG_20191202_095827.jpg

OpenSCADではスクリプトを書いて形状をデザインします。デザインをするといっても、GitHubで公開されているプロジェクトファイルをベースとしたため、キーの場所を替えるだけの簡単なお仕事でした。片面だけをデザインしてからmirror([1,0,0])コマンドで反転させると反対側の面もできます。

Screenshot from 2019-12-09 00-44-29.png

キースイッチはケースにはめ込んで固定します。試作機のためボトムプレートは作っていません。滑り止めのゴム足の代わりにゴムトリムを挟み込んでいます。

IMG_20191215_165519.jpg

配線はゆかりさんのブログを参考にしています。キーボードは片面5行×7列ですが、6行×6列のマトリクスとして空中配線しています。しっかりとはんだ付けしないと入力不良を起こす原因となるため、ピンの足にワイヤを巻きつけたりダイオードの足同士を絡ませたりしてからはんだ付けしています。

IMG_20191214_012530.jpg

ファームウェア

職場ではGoを書いています。そこでファームウェアをTinyGoで書いてみることにしました。

2019年12月現在、TinyGoが動くマイコンは限られます。自作キーボードで一般的に使われているProMicroはTinyGoでは使えません。また、TinyGoはUSB HIDやBLE HIDのドライバーを提供していないという問題もあります。そこで今回はATMega328pRN42を接続する構成を取っています。RN42はUART接続型のBluetoothモジュールでありHIDデバイスとして振る舞うことができます。キーの送信はマイコンからUSB HID Keyboard scan codeを送信するだけです。

// SendKeyboardReport sends a raw keyboard report for scan codes and modifier keys.
// The data byte array should be specified in scan codes or encoded values
// and the length should be 6.
// The modifier byte is a bit mask value that represents modifier key status.
// See 5.3.3 Raw Report Mode in datasheet.
func (d Device) SendKeyboardReport(data []byte, modifier byte) error {
    if len(data) != 6 {
        return errors.New("length of data should be 6")
    }

    header := []byte{0xFD, 0x09, 0x01, modifier, 0x00}
    _, err := d.Write(header)
    if err != nil {
        return err
    }
    _, err = d.Write(data)
    return nil
}

RN42を使うとマイコンボードや開発言語を問わず自作キーボードを作れます。別バージョンとして、GR-CITRUSを使ったMicroPythonバージョンも作っています。ハードウェアだけではなくソフトウェアも自分好みに作り込めるのがRN42を使ったキーボード自作の良いところだと思います。

IMG_20191214_150428.jpg

余談ですが、デバイス周りのコードを書くときはuartなどのデバイス固有のインターフェースをコンストラクタやイニシャライザで外から受け取るようにしておくとあとからテストコードを書きやすくなると思います。

class RN42:
    def __init__(self, uart):
        self.uart = uart

    def write(self, key):
        self.uart.write(key)

    def send_keyboard_report(self, data, modifier):
        if len(data) != 6:
            return

        header = bytearray(b'\xFD\x09\x01\x00\x00')
        header[3] = modifier
        self.uart.write(header)
        self.uart.write(data)

おまけ

100円ショップで売られているおゆまるとUVレジンでキーキャップの複製もやってみました。軸の穴の型をとるときには先が尖ったものではなくマイナスドライバーで押しこんであげると良いです。#1200〜#2000のヤスリで形を整えたあとにコンパウンドで磨いています。ネイルのトップコートでコーティングしてあげても良いようです。

IMG_20191215_172818.jpg

詳しくはこちら。
https://twitter.com/takjn/status/1187036320108929024
https://twitter.com/takjn/status/1187359440883707904

おわりに

キーレイアウトを試すための試作機のつもりで作りましたが、十分実用になっています。見た目とか打鍵感とか打鍵音とかはキットには遠く及びませんが、自分で書いたファームウェアで動くキーボードでそのファームウェアを書くという体験はセルフホスティング的な面白さがあって良いです。

この記事はこの記事で紹介した自作キーボードで書きました。

13
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
7