はじめに
WaveshareのRP2040-LCD-0.96を使ってLCDディスプレイ付きの分割キーボードを作ったのですが作成中に色々やらかしたので、後世のためにもここにハマりポイントを記しておきます。
対象読者としては、自作初めて or 2回目くらいのビギナー向けです。
環境
- 言語:MicroPython
- キーボード向けライブラリ:KMK Firmware
LCD用のGPIOピンが割り振られている
第一やらかしはLCD用のGPIOピンが事前に割り振られているにも関わらず、それらのピンにキーボード用のピンを割り当ててPCBを作成してしまったことです。

(Wikiからピンアサインを拝借)
御覧の通り、GP8, 9, 10, 11, 12, 25は"LCD used pins"と記載されております。
これを完全に見落としており、GP8と9にキーボードの行をアサインし、PCBを発注してしまいました。
全てはんだ付け後に、LCDの画面が点けようと苦戦していたところ、このとんだ凡ミスに気付かされました...。
応急対応(というか恒久になりそう)としては、まずキーボード用のピンをアサインし直します。
そしてRP2040-LCDにピンヘッダーを刺して、ピンヘッダー経由でPCBへはんだ付けします。この時、GP8と9のみピンをピンヘッダーから抜くことでGP8とGP9には導通しないようにし、ジャンパ線を使って対象のキーボード行の回路からアサインし直したピンへ直接接続を行うことで事なきを得ました。
とはいえ、衝撃などでジャンパ線が外れる可能性は高く、事なきを得られて無い感はありますが、、、
RP2040-LCD-0.96は マスターで使う(分割の場合)
KMKでは分割キーボード用のライブラリが既に用意されており、こんな感じで簡単に分割の設定ができます。
import board
from kmk.kmk_keyboard import KMKKeyboard
from kmk.modules.split import Split, SplitSide, SplitType
keyboard = KMKKeyboard()
# ...
split = Split(
split_type=SplitType.UART,
split_side=SplitSide.LEFT,
data_pin=board.GP0,
use_pio=True,
)
keyboard.modules.append(split)
# ...
そして、KMKの標準設定では分割されたキーボードの左側がプライマリ、右側がセカンダリという形になります。
そのため、基本的には左側がいわゆる処理の司令塔となるため、右側は「どのボタンを押したか」という情報を左側へ送る役割に特化しています。つまり、全ての情報を知っているのがプライマリということになります。
例えば、
- 現在のレイヤ
- PCに送っている最終的なキーデータ
- 修飾キーの押し状態
などを把握しています。
これらを勘案すると左側にLCDを持ってくることで、右側から受けた操作も考慮することができるため全てのキー操作に関してLCDを利用することが可能となります。
LCDの表示を切り替えるのに手こずる
とりあえず、LCDの利用方法の第一歩としてレイヤーを切り替えたときにどのレイヤーかを表示する機能を実装しようとしたのですが、これにかなり手こずりました。
単に画面を表示するだけであれば容易です。ただ、キーボードが打ち込まれたことをスキャンするメイン処理と、画面描画を切り替える操作を共存させようとすると、なかなか上手くいきませんでした。結局、Layerモジュールに対して描画命令を割り込ませる継承を行うことで、レイヤー切り替えの表示ができるようになりました。
# ...
import displayio
from adafruit_display_text import label
from adafruit_st7789 import ST7789
from kmk.kmk_keyboard import KMKKeyboard
from kmk.modules.split import Split, SplitSide, SplitType
from kmk.modules.layers import Layers
keyboard = KMKKeyboard()
# ...
displayio.release_displays()
display = None
layer_label = None
spi = busio.SPI(clock=board.GP10, MOSI=board.GP11)
display_bus = fourwire.FourWire(
spi, command=board.GP8, chip_select=board.GP9, reset=board.GP12
)
# 0.96インチ特有のオフセット設定
display = ST7789(
display_bus, width=160, height=80, rowstart=0, colstart=24, rotation=270
)
splash = displayio.Group()
display.root_group = splash
# レイヤー表示用ラベル
layer_label = label.Label(
terminalio.FONT, text="WELCOME", color=0x00FF00, x=40, y=15, scale=3
)
splash.append(layer_label)
print("Display OK")
display.refresh()
# --- 2. カスタムレイヤーモジュールの定義 ---
class CustomLayers(Layers):
def __init__(self):
super().__init__()
self.last_reported_layer = -1
def after_matrix_scan(self, keyboard):
# 親クラス(Layers)の本来の処理をまず実行
super().after_matrix_scan(keyboard)
# 現在のレイヤー状態を取得
try:
current = keyboard.active_layers[0] if keyboard.active_layers else 0
except:
current = 0
# レイヤーに変化があった時だけ実行(ここがトリガー)
if current != self.last_reported_layer:
self.last_reported_layer = current
# 実際の表示更新
if current == 0:
layer_label.text = "LAYER\nBASE"
layer_label.color = 0x00FF00
elif current == 1:
layer_label.text = "LAYER\nFUMK"
layer_label.color = 0xFF0000
# 画面の物理リフレッシュ
display.refresh()
# --- 3. Split(左右通信)の設定 ---
split = Split(
split_type=SplitType.UART,
split_side=SplitSide.LEFT,
data_pin=board.GP0,
use_pio=True,
)
keyboard.modules.append(split)
keyboard.modules.append(CustomLayers())
おわりに
とりあえず、今回記載した内容は自作キーボードにおいてギリギリ致命傷にはならないので、もしやらかしたとしても割と何とかなります。自分は全部はんだ付け終わった後に、やらかし1つ目と2つ目に気づいたときは絶望しましたが、はんだ吸収材で根気よく剥がして何とかなりました。ぜひ失敗も楽しみながら、自作キーボードをやってみてください!
