見出し画像

Raspberry Pi Picoで動くキーボード「PiPi Gherkin」を作ってみた

PiPi Gherkinとは?

40%Clubが作った30キーのキーボードGherkinをRaspberry Pi Picoで動くようにしたキーボードです。基板のデータはCC BY-SA 4.0で公開されていて、TALP KEYBOARDさんで基板のみ販売されているので、こちらを購入しました。

組み立て

基板以外に用意する部品

基板以外は自分で用意します。
・Raspberry Pi Pico x 1
・ダイオード(1N4148) x 30
・MX用キースイットソケット x 30
・MX用キースイッチ x 30
・MX用キーキャップ x 30
・ピンヘッダー20ピン x 2(今回はPro Microのあまりを利用しました)

ダイオードをつける

久々にスルーホールタイプのダイオードをつけていきます。自家製ダイオードベンダーでキレイに曲げていきます。

画像1

こんな感じで30本つけていきます。

画像2

一部ダイオードの向きが違うところがあるので注意。
今回はダイオード側からハンダ付けしてみました。

画像3

ハンダ付けが終わったら、反対側に生えている足をニッパーで切ります。

画像4

キースイッチソケットの取り付け

こちらは他の自作キーボードキットと同じようにつけていきます。

画像5

Raspberry Pi Picoの取り付け

いつものPro Microと違うところです。
手持ちのピンヘッダでは高さが足りなかったので、余っていたPro Micro付属のピンヘッダを使っていきます。

画像6

まずはピンヘッダをPCBにハンダ付けします

画像7

お次にPicoをハンダ付けします。足が長いので適当に切ってからハンダ付けします。(付ける前に、一応ファームの確認をした方が良かったかも)

画像8
画像9

キースイッチの取り付け

ソケットにスイッチをつけます。

画像10

ケースやキーキャップは必要ですが、ひとまず組み立てはここまでにしておいて、ファームウェアを確認していきます。

ファームウェア

ファームウェアはRaspberry Pi Pico上で動く「KMK Firmware」を使っていきます。

Circuit Pythonの導入

KMK Firmwareは「Circuit Python」というファームウェアの上で動くので、まずはこれを書き込みます。
↓からUF2ファイルをダウンロードします。

Pi Pico上のボタンを押しながら、PCとUSB接続します。
ドライブとして認識されるので、そこにUF2ファイルをドラッグ&ドロップします。しばらくすると、「CIRCUITPY」というドライブになります。

KMKの導入

KMKのリポジトリ↓をcloneするか、緑色のCodeボタンから「Download ZIP」でソースコードを落とします。

kmkディレクトリとboot.pyを先程のドライブのルートにコピーします。

PiPi Gherkin用の設定ファイルの導入

40%clubで用意してくれているファイルを利用します。

こちらのcode.pyを先ほど同様にドライブのルートにコピーします。
KMKの更新に追いついていないのかわからないですが、下記のように4行追記をしないとエラーになります。

#PiPi-GHERKIN - Raspberry Pi PICO
import board
from kmk.keys import KC
from kmk.kmk_keyboard import KMKKeyboard
from kmk.matrix import DiodeOrientation
from kmk.hid import HIDModes
from kmk.modules.layers import Layers # ←追加
from kmk.modules.modtap import ModTap # ←追加

gherkin = KMKKeyboard()
gherkin.modules.append(Layers()) # ←追加
gherkin.modules.append(ModTap()) # ←追加

gherkin.col_pins = (board.GP2, board.GP3, board.GP4, board.GP5, board.GP6, board.GP7)
gherkin.row_pins = (board.GP8, board.GP9, board.GP10, board.GP11, board.GP12)

#Rotate gherkin so USB on Right Side. Not needed if USB on Left Side.
gherkin.col_pins = tuple(reversed(gherkin.col_pins))
gherkin.row_pins = tuple(reversed(gherkin.row_pins))

gherkin.diode_orientation = DiodeOrientation.COLUMNS

gherkin.debug_enabled = False

gherkin.keymap = [
   [
       KC.Q,    KC.W,    KC.E,    KC.R,    KC.T,    KC.Y,    KC.U,    KC.I,    KC.O,    KC.P,
       KC.A,    KC.S,    KC.D,    KC.F,    KC.G,    KC.H,    KC.J,    KC.K,    KC.L,    KC.ESC,
       KC.MT(KC.Z, KC.LCTRL), KC.MT(KC.X, KC.LALT), KC.LT(3, KC.C), KC.LT(4, KC.V), KC.LT(2, KC.BSPC),
       KC.LT(1, KC.SPC),  KC.LT(5, KC.B), KC.MT(KC.N, KC.RALT), KC.MT(KC.M, KC.RCTRL), KC.MT(KC.ENT, KC.RSFT),
   ],
   [
       KC.N1,   KC.N2,   KC.N3,   KC.N4,   KC.N5,   KC.N6,   KC.N7,   KC.N8,   KC.N9,   KC.N0,
       KC.F1,   KC.F2,   KC.F3,   KC.F4,   KC.F5,   KC.F6,   KC.F7,   KC.F8,   KC.F9,   KC.F10,
       KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.DEL,  KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS,
   ],
   [
       KC.EXLM, KC.AT,   KC.HASH, KC.DLR,  KC.PERC, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN,
       KC.F11,  KC.F12,  KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.GRV,
       KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS,
   ],
   [
       KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.MINS, KC.EQL,  KC.LBRC, KC.RBRC, KC.BSLS,
       KC.TAB,  KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.COMM, KC.DOT,  KC.SLSH, KC.SCLN, KC.QUOT,
       KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.LEFT, KC.DOWN, KC.UP,   KC.RGHT,
   ],
   [
       KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.UNDS, KC.PLUS, KC.LCBR, KC.RCBR, KC.PIPE,
       KC.TAB,  KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.LABK, KC.RABK, KC.QUES, KC.COLN, KC.DQUO,
       KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.HOME, KC.PGDN, KC.PGUP, KC.END,
   ],
   [
       KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS,
       KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS,
       KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS,
   ],
]

if __name__ == '__main__':
   gherkin.go(hid_type=HIDModes.USB) #Wired USB enable

kmkの変更に伴い修正が必要になる可能性があるので、詳細はドキュメントやコードを参考にしてください。

デバッグ

Pi Picoはシリアルコンソールでエラー出力などを見ることができます。
Macでの接続方法

ls -1 /dev/tty.usbmodem*
# 出てきたやつにscreenなどで接続することができます。
screen /dev/tty.usbmodem1413201

接続すると、↓な感じで出力が続いていきます。
ドライブ上のファイルを修正→保存したら自動で再実行されるようで便利でした。

オートリロードがオンです。ファイルをUSB経由で保存するだけで実行できます。REPLに入ると無効化します。

code.py 出力:
トレースバック(最新の呼び出しが末尾):
 ファイル "code.py", 行 27, in <module>
 ファイル "kmk/keys.py", 行 377, in __getattr__
ValueError: Invalid key

Code done running.

Press any key to enter the REPL. Use CTRL-D to reload.
ソフトリブート

キーマップ

30%は未知の領域なので、kmkの勉強しながらぼちぼちセットアップしていこうと思います。QMKはCなのであんまり追えてないですが、Pythonなら読めるはず・・・なので、コードも見ていきたいです。

ケース

ファームウェアが動くようになったので、ケースも作ってみます。
PiPi Gherkinを販売しているTALP KEYBOARDさんがケースデータを無料で公開してくれているので、こちらを利用させてもらいます。

イラレのデータになっているので、svgで書き出してfusion360に取り込み、厚さをつけて3Dデータにして、3Dプリントします。

画像11

ひとまずトップ、ボトムプレートと12mmスペーサーで組み上げました。ちょっと高さが出てしまうので、Pi Picoをくり抜いた形でサイドも埋めてモデリングしたいですね。

画像12


さすがに親指ないと辛いなあという気はしますが、ぼちぼちいじっていきます。

参考

追記:RP2040対応のQMK(非公式)を動かす

せきごんさんが非公式にQMKを動かせるように対応してくれて、PiPi Gherkrin用のファームを作ってくれていたので、試してみました。ファイルを入れるだけで簡単に使え、Remap用のjsonも用意してくれています。

せきごんさんによるQMK対応。公式が対応してくれるまでの暫定対応のようです。


追記:Ruby製PRK Firmwareで動かしてみた

Ruby KaigiでPRKの発表があったようで、興味があってこちらも入れてみました。

KMK同様にUF2ファイルとkeymap用のファイルがあれば動きます。
こちらからUF2ファイルをダウンロードして同様にD&Dで反映させます。

しばらくすると、↓のようにマウントされるので、

画像13

↓のkeymap.rbをD&Dしたら使えるようになります。


自作キーボードのオンラインショップをやっています

よかったら覗いてみてください!


この記事が気に入ったらサポートをしてみませんか?