⌨️

自作キーボードroBaに入門しました

に公開

先日自作キーボードデビューを果たし、roBaを使い始めました。
組み立てからキーマップ設定までの試行錯誤を書いていきます。

組み立て準備

ロープロ対応ケース

BOOTHで購入したキットに付属しているケースはロープロ非対応なので、ロープロにするなら別途ケースを印刷する必要があります。JLC3DPというサービスが破格の安さなのでこちらを使いました。左右のトップケースをPA12-HP Nylonで、リセットスティックをPA11-HP Nylonで印刷し、本来印刷代$20.77、送料$8.52のところ初回限定クーポンや期間限定クーポンで半額以下の$13.77になりました。だいたい二千円強です。
PA12-HP Nylonは表面に細かな凹凸がありますがサラサラとした触感で、ケース素材にはピッタリです。対してPA11-HP Nylonの表面は紙ヤスリのようにザラザラしており指が滑りません。ケース本体には合いませんが、リセットスティックだけならむしろ良いアクセントになります。

トラックボール

ELECOMのDEFTについてきた34mm黒玉を嵌めてみたところroBaのセンサとの相性が最悪でした。ELECOM製でも赤玉は問題なく使えたのですが、色の好みの問題でPerixxの黒玉を買いました。最初は支持球との摩擦が強く、つっかかる感覚がありましたが、1〜2日で滑らかに動くようになり、今は問題なく使えています。センサとの相性も良好です。

工具

電子工作は初めてなので全てを一から揃える必要がありました。遊舎工房の工具セットは割高なので内容物を参考に自分で買い揃えました。

  • はんだごて・こて台 - ¥4,807
    温度調節機能つきです。
  • フラックス - ¥654
    フラックスの良し悪しはわからないので単価x最小購入数が安いものを選びました。結局使いませんでした。
  • はんだ(Φ0.6mm) - ¥340
    細かい作業がしやすそうな細めのものを選びました。賢明な判断でした。鉛フリーと迷いましたが、融点が低い(すなわち初心者に優しい)ことを優先しました。長さはもっと短くても足ります。
  • はんだ吸収線 - ¥210
  • ピンセット - ¥300

組み立て

大体のことは組み立てガイドに書いてあります。
実はChocソケットには向きがあります。自分は実装途中で知ったのでいくつかのキーはソケットの向きが逆になってしまいました。今のところ不都合なく使えているので、ちょっと気持ちが凹む程度で済みました。
https://www.eisbahn.jp/yoichiro/2021/01/kailh_choc_v1_socket.html

キーキャップはTai Hao Thinsを採用しました。無刻印だと分かりにくいのですが、このキーキャップにも向きがあります。裏面の軸の周りの模様をよく見ると=ö=のように2本線が2方向に長く1方向に短く伸びているのですが、短く伸びている方が手前側、何もない方が奥側です。この向きの通りに取り付けると側面の加工痕が奥側に来るため使用中に目立ちません。
とは言っても、しょせん見栄えの問題なので実用上は180°逆でも何ら問題ありませんし、加工痕も意識して見ないと気づかない程度に小さいです。

ケースを机に直置きすると簡単に滑るので滑り止めが必須です。キットにクッションゴムが入っていますが4個しかないので、2つずつ内側につけて滑り止めとテンティングを兼ねることにしました。

キーマップ

お待たせしました、本題です。ZMK Studioやkeymap-editorは使わず、VSCodeでゴリゴリコードを書いて設定しました。毎度commit/pushしてGitHub Actionsが回るのを待つのは面倒だったので、kot149さんの記事を参考にローカルでビルドできるようにしました。おかげで10〜15秒でビルドが終わるので快適です。自分はdevcontainerにkeymap-drawerをインストールし、キーマップの描画もローカルでできるようにしました。ローカルでの描画は1秒もかからないので、ファームウェアをビルドする前にコンボキーの位置設定がずれていないか描画して確認するという使い方もできます。
https://zenn.dev/kot149/articles/zmk-workspace

第0層(デフォルト)


せっかく自由にレイアウトを決められるのだからと、QWERTYのしがらみから逃れてColemak配列に入門しました。正確にはColemak-DHという亜種らしいです。
カッコ類は開閉ペア入力とカッコの内側へのカーソル移動をまとめて行うマクロを作成し右手に散りばめました。位置は後述の記号レイヤと揃えています。以下は[]を入力してカーソルを間に動かすマクロの設定例です。

roBa.keymap
/ {
    combos {
        brackets {
            bindings = <&brackets>;
            layers = <0 1>;
            key-positions = <7 8>;
        };
    }
    macros {
        brackets: brackets {
            compatible = "zmk,behavior-macro";
            #binding-cells = <0>;
            bindings = <&kp LEFT_BRACKET &kp RIGHT_BRACKET &kp LEFT_ARROW>;
        };
    }
}

左手親指は左から「英数」「スペース」「かな」とMacBook風の配列にしました。OSがキーボードをJIS配列だと思っている場合はZMKのLANGUAGE_1が「かな」、LANGUAGE_2が「英数」に対応しますが、US配列だと思っている場合は分かりません。ChatGPT曰く非対応なので何も起こらないらしいです。自分の場合、MacBookの内蔵キーボードがJIS配列だからかroBaもJISだと思い込んでくれたようで、特に何も設定せずとも上記のキーコードが使えました。
他にもコンボキーを色々設定しています。カッコ類の左にはクォーテーションマーク類を置きました。左手には_-|\がありますが、これらは記号の形がそのまま配置の形になっています。\は見づらいかもしれませんがFとTの同時押しです。
右下の隅は押しづらいので、後述のように配列切り替えとBluetooth設定レイヤの有効化に割り当てています。

第1層(QWERTY配列)


普段使いは想定しておらず、vimなどQWERTY配列を前提とした作業をするための避難用レイヤです。MacBook内蔵キーボードを使うこともまだあるので、vim側でColemak用のキーマップ変更などはしていません。
右下隅のキーは、単押しでColemakレイヤ、2連打でQWERTYレイヤ、長押しでBluetooth設定レイヤ有効化を割り当てています。この挙動はZMKのTap DanceとHold Tapを組み合わせて実現できます。

roBa.keymap
behaviors {
    tog_on: tog_on {
        compatible = "zmk,behavior-toggle-layer";
        #binding-cells = <1>;
        toggle-mode = "on";
    };

    tog_off: tog_off {
        compatible = "zmk,behavior-toggle-layer";
        #binding-cells = <1>;
        toggle-mode = "off";
    };

    mo_off: mo_off {
        compatible = "zmk,behavior-hold-tap";
        #binding-cells = <2>;
        bindings = <&mo>, <&tog_off>;
        tapping-term-ms = <200>;
    };

    // Hold: momentary layer L7_BT
    // Single Tap: Colemak Layout
    // Double Tap: QWERTY Layout
    sp1: sp1 {
        compatible = "zmk,behavior-tap-dance";
        bindings = <&mo_off 7 1>, <&tog_on 1>;
        #binding-cells = <0>;
    };
}

第2層(数字・Fnキー)


フルサイズJISキーボードならR0/R1の行にあるキーのレイヤです。
Fnキーよりも数字の方が使用頻度が高いので、数字を中段に、Fnキーを下段にしています。

第3層(記号)


まずカッコ類をデフォルトレイヤと同じ位置に配置し、あとは頭文字などがColemakレイヤのキーと対応するように並べました。

記号 押すキー 覚え方 記号 押すキー 覚え方
@ A at sign + P plus
^ C caret = Q equal
$ D dollar & R reference
` G grave * S star
# H hash ~ T tilde
% M modulo ! X exclamation

これだと右人差指のホームポジションという特等席が空いてしまうので、使用頻度が高い割に隅に追いやられている=をコピペしています。

第4層(操作系)


使用頻度的には実質矢印レイヤです。右手に矢印、左手に修飾キーを並べています。音量や画面輝度もこのレイヤで調整できます。Mission ControlはC_AC_DESKTOP_SHOW_ALL_WINDOWS、LaunchpadはC_AC_DESKTOP_SHOW_ALL_APPLICATIONSです。
左右どちらの手でも有効化できるので、基本的な操作であれば片手で完結します。
https://zmk.dev/docs/keymaps/list-of-keycodes#application-controls

第5層(マウス操作)

オートマウスレイヤ(AML)です。ColemakでNとI、QWERTYでJとLに当たる位置にマウスボタンを配置しています。kot149さんの記事を参考に、ボールを動かしたら800ms間有効化、その間にマウスキーを押したら500ms延長という設定をしています。
https://zenn.dev/kot149/articles/zmk-auto-mouse-layer

roBa_R.overlay
/ {
    trackball_listener {
        status = "okay";
        compatible = "zmk,input-listener";
        device = <&trackball>;

        // ボールを動かしたら800ms間AML有効化
        input-processors = <&zip_temp_layer 5 800>;
    };
}
roBa.keymap
&mkp_input_listener {
    // マウスキーを押したらAMLを500ms延長
    input-processors = <&zip_temp_layer 5 500>;
};

マウス操作の直後に&mkpを割り当てたキー(N/I)を入力しようとするとマウスクリックになってしまいAMLが延長されてしまうことがありますが、その場合は左手親指で「英数」「かな」のいずれかを押すことで強制的にAMLを脱出できます。
また、後述のスクロールレイヤを起動するキーと被らないよう、Eの位置は空けています。

左手親指の真ん中(スペース)を長押しするとカーソル速度が半分になるため細かい操作がしやすくなります。第3層のトリガーと重複していますが問題なく動作します。短い親指でボールを動かしmacOSの画面左上の🔴🟡🟢やChromeのタブを閉じる×ボタンにカーソルを合わせるのは意外と大変なので、重宝しています。

roba_R.overlay
/ {
    trackball_listener {
        status = "okay";
        compatible = "zmk,input-listener";
        device = <&trackball>;

        slow_mouse {
            layers = <3>;
            input-processors = <&zip_xy_scaler 1 2>;
        };
    }
}

第6層(スクロール)

第0/1層で右手中指のキーを長押しするとトラックボールでスクロールできます。デフォルトの位置(右手中指奥)だと手の小さい自分は疲れやすいため、より長押ししやすい手前側にずらしました。スクロールは速度を1/3に落とし、向きを反転しています。これもkot149さんの記事を参考にしています。
https://zenn.dev/kot149/articles/zmk-input-processor-cheat-sheet

roba_R.overlay
/ {
    trackball_listener {
        status = "okay";
        compatible = "zmk,input-listener";
        device = <&trackball>;

        scroller {
            layers = <6>;
            input-processors = <
                &zip_xy_to_scroll_mapper
                &zip_scroll_scaler 1 3
                &zip_scroll_transform (INPUT_TRANSFORM_X_INVERT | INPUT_TRANSFORM_Y_INVERT)
            >;
        };
    };
};

第7層(Bluetooth)


レイヤーのトリガーの位置をずらした以外はデフォルトのままです。

ロータリーエンコーダ

マウススクロールを割り当てています。第6層でトラックボールでもスクロールができるのですが、エンコーダの方が力が要らず疲れにくいです。その代わり結構速いので大雑把なスクロールをしたい時に使います。ZMK_POINTING_DEFAULT_SCRL_VALを80より小さい値にすればもっとゆっくりスクロールができるかと思いきや、なぜか80未満ではそもそもスクロールができませんでした。

roBa.keymap
#define ZMK_POINTING_DEFAULT_SCRL_VAL 80
// ☝️このdefineは
// 👇このincludeよりも先にする
#include <dt-bindings/zmk/pointing.h>

// 中略

/ {
    behaviors {
            encoder_msc_scroll: encoder_msc_scroll {
            compatible = "zmk,behavior-sensor-rotate";
            #sensor-binding-cells = <0>;
            bindings = <&msc SCRL_UP>, <&msc SCRL_DOWN>;
            tap-ms = <20>;
        };
    }
}

この記事はroBaで書きました。

Discussion