オリジナルDIYキーボードでQMK firmwareを使ってロータリーエンコーダとNeoPixelを制御する方法
前回の記事でボクのDIYキーボードキット用のQMK firmwareの作成方法について説明したけど、ロータリーエンコーダ(以下、エンコーダ)とNeoPixelの制御については、触れていなかったから、QMK firmwareでエンコーダとNeoPixelを制御する方法について説明するよ。
前回の記事とこのページの内容を読むことで、DIYキーボードキットの全機能を使用したQMK firmwareを作成することができるよ。このページでは、以下の機能の設定方法について説明しているよ:
- エンコーダ
- NeoPixel
- レイヤー
- COMBOキー
DIYキーボードキットはBOOTHで発売中なので、まだ持っていない場合はぜひ購入してね!
BOOTHの商品ページ
DIY kit 01 - Keyboard XIAO RP2040
対象読者
- DIYキーボードキットを手っ取り早くマクロパッドにしたいみんな
- RP2040用にQMKを使ったファームウェアの作り方を知りたいみんな
環境
このページで説明してる内容は、前回の記事で説明した環境と同じだよ。
- QMK firmware
環境の構築方法は前回の記事を読んでね。 - DIY kit 01 - Keyboard XIAO RP2040
- Windows/Mac
MacはSonomaでも動作することを確認済みだよ。
エンコーダの設定
まずは、qmk firmwareでエンコーダーの設定をする方法を説明するよ。エンコーダの処理方法には2種類あって、1つ目がキーマップを使う方法。2つ目がコールバックを使う方法。ここではキーマップを使う方法について説明しているよ。
公式の説明はこちらを参照してね。
まずは、作成中のキーボードのディレクトリーに移動してね。例えば、ボクの場合だと:
cd ~/qmk_firmware/keyboards/nanana_diy
エンコーダの設定のために編集するファイルは以下の3つだよ:
- nanana_diy/info.json
- nanana_diy/rules.mk
- nanana_diy/keymap/default/keymap.c
info.json
まずはキーボードの設定を編集するよ。info.jsonを開いて以下の2箇所を追加してね。
- featuresにeccoder: trueを追加
- TOP階層にencoderを追加
encoder: true
featuresというキーにencoder: trueを追加することで、このキーボードでエンコーダ機能を有効にすることができるよ。
"features": {
..
"encoder": true
},
encoder
jsonファイルのTOP階層にencoderというキーを追加して、そこにエンコーダのピン割り当てを定義するよ。割り当て例は以下を参考にしてみてね。この例ではDIYキーボードキットのEnc1とEnc2のピンをそれぞれ割り当てているよ。
pin_a, pin_bはそれぞれエンコーダのA,B端子を指しているよ。resolutionはエンコーダの1クリックあたりに出力されるパルスの数を指定するよ。
"encoder": {
"rotary": [
{ "pin_a": "GP4", "pin_b": "GP3", "resolution": 2 },
{ "pin_a": "GP1", "pin_b": "GP2", "resolution": 2 }
]
},
全体
修正後のinfo.jsonは以下の通りだよ。
{
"manufacturer": "NANANA",
"keyboard_name": "nanana_diy",
"maintainer": "nananauno",
"bootloader": "rp2040",
"diode_direction": "COL2ROW",
"features": {
"bootmagic": true,
"command": false,
"console": false,
"extrakey": true,
"mousekey": true,
"nkro": true,
"encoder": true
},
"matrix_pins": {
"direct": [
["GP26","GP27","GP28","GP29"]
]
},
"encoder": {
"rotary": [
{ "pin_a": "GP4", "pin_b": "GP3", "resolution": 2 },
{ "pin_a": "GP1", "pin_b": "GP2", "resolution": 2 }
]
},
"processor": "RP2040",
"url": "",
"usb": {
"device_version": "1.0.0",
"pid": "0x2326",
"vid": "0xFEED"
},
"layouts": {
"LAYOUT": {
"layout": [
{"label": "GP26", "matrix": [0, 0], "x": 0, "y": 0},
{"label": "GP27", "matrix": [0, 1], "x": 1, "y": 0},
{"label": "GP28", "matrix": [0, 2], "x": 2, "y": 0},
{"label": "GP29", "matrix": [0, 3], "x": 3, "y": 0},
]
}
}
}
rules.mk
キーボードのディレクトリの直下にあるrules.mkに以下の1行を追加して、エンコーダのキーマップを使用することを定義しておくよ。
ENCODER_MAP_ENABLE = yes
keymap.c
次に、キーマップを定義するために、キーマップのディレクトリへ移動してね。
cd keymap/default
keymap.cを編集する前に、前回の記事で作成したkeymap.jsonは今回は使用しないから、ファイル名をkeymap.json.oldなどに変更してqmkから使えないようにしておいてね。 keymap.jsonでエンコーダを割り当てる方法が見つからなくて、今回はkeymap.cで割り当てる方法を説明しているよ。もし、keymap.jsonを使ったやり方を知っていたらぜひ教えてね。
keymap.cを開いて以下のように編集してね。
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(
KC_A, KC_B, KC_C, KC_D
)
};
#if defined(ENCODER_MAP_ENABLE)
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {
[0] = { ENCODER_CCW_CW(KC_PAGE_UP, KC_PAGE_DOWN), ENCODER_CCW_CW(KC_VOLD, KC_VOLU) }
// Encoder 1 Encoder 2
};
#endif
このコードを少し解説しておくと、
const uint16_t PROGMEM keymaps
keymapsは前回の記事で説明したkeymap.jsonを使ったキーの割り当てをC言語のコードで定義し直しているよ。Key1, Key2, Key3, Key4を押したときに、PCへ入力されるキーコードを定義しているよ。例えば、KC_Aはaという文字がPCへ入力されるよ。[0]は0番目のレイヤーのキー割り当てであるということを示しているよ。
const uint16_t PROGMEM encoder_map
encoder_mapがエンコーダのキー割り当てを定義している部分になるよ。ENCODER_CCW_CW(KC_PAGE_UP, KC_PAGE_DOWN)の部分が1つ目のエンコーダEnc1に対するキー割り当てで、ENCODER_CCW_CWの1つ目の値がエンコーダが時計回りに回転した時に入力されるキーコード、2つ目の値がエンコーダが反時計回りに回転した時に入力されるキーコードになっているよ。そして、ENCODER_CCW_CW(KC_VOLD, KC_VOLU)の部分が2つ目のエンコーダEnc2に対するキー割り当てになっているよ。
動作確認
ここまででエンコーダの設定が完了したから、一度ファームウェアを作成してXIAO RP2040に書き込んでみてね。
qmk complile
qmk flash
XIAO RP2040にファームウェアが正常に書き込めたら、PC上でChromeなどのWebブラウザを開いて、キーボードのエンコーダを回転させてみてね。Enc1を回すとブラウザのページがスクロールできるはずだよ。また、Enc2を回すとPCの音量が変わることを確認してね。
NeoPixelの設定
ここでは、DIYキーボードキットに搭載された4つのNeoPixelを点灯させるための設定について説明するよ。最終的には色々なエフェクトを使用するんだけど、ここでは動作確認のためにRAINBOWというエフェクトのみを使用してNeoPixelを点灯させてみるよ。
NeoPixelの設定のために編集するファイルは以下の2つだよ:
- nanana_diy/rules.mk
- nanana_diy/config.h
rules.mk
キーボードのディレクトリの直下にあるrules.mkに以下の2行を追加して、RGB Lightを使用することを定義しておくよ。また、qmkではDIYキーボードキットで使用しているRP2040向けのPIOドライバーも用意されていて、WS2812_DRIVERでvendorを指定することで、PIOドライバーを有効にすることができるよ。
RGBLIGHT_ENABLE = yes
WS2812_DRIVER = vendor
config.h
次に、キーボードのディレクトリの直下にあるconfig.hに以下の定義を追加するよ。DIYキーボードキットで使用しているNeoPixelのモジュールはSK6812MINI-Eだけど、WS2812_xxxxの定義がそのまま使用できるよ。
// For NeoPixel LEDs
#define WS2812_DI_PIN GP0
#define WS2812_TIMING 1250
#define WS2812_T1H 650
#define WS2812_T0H 350
#define WS2812_TRST_US 100
#define RGBLED_NUM 4
#define RGBLIGHT_LIMIT_VAL 200
#define RGBLIGHT_DISABLE_KEYCODES
#define RGBLIGHT_EFFECT_RAINBOW_MOOD
#define RGBLIGHT_DEFAULT_MODE RGBLIGHT_MODE_RAINBOW_MOOD
WS2812_xxxxはNeoPixelのモジュールに関する設定で、SK6812MINI-Eのデータシートを参考に設定するよ。各定義の説明は以下の通りだよ:
WS2812_DI_PIN
NeoPixelのDINが接続されたGPIOピンの番号を指定するよ。DIYキーボードキットのNeoPixelはGP0に接続されているよ。
WS2812_TIMING
SK6812MINI-EのTH+TLの時間を指定するよ。初期値の1250ns=800kHzでオッケー。
WS2812_T1H
SK6812MINI-Eで1を表す波形のHIGH継続時間を指定するよ。データシート上では標準が640nsだけど、下記の注釈の仕様があるから、650nsに設定しているよ。
WS2812_T0H
SK6812MINI-Eで0を表す波形のHIGH継続時間を指定するよ。データシート上では標準が320nsだけど、下記の注釈の仕様があるから、350nsに設定しているよ。
WS2812_TRST_US
SK6812MINI-EでリセットのためのLOW継続時間を指定するよ。データシート上の最小80usより少し長い100usに設定しているよ。
RGBLED_NUM
NeoPixelの数を指定するよ。DIYキーボードキットには4つのNeoPixelが搭載されているから、4を指定しているよ。
RGBLIGHT_LIMIT_VAL
NeoPixelの明るさを制限するための定義だよ。0-255で設定するよ。最大輝度で使用するとNeoPixelの寿命にも影響する可能性があるから、ここでは最大輝度を200に設定しているよ。
RGBLIGHT_DISABLE_KEYCODES
qmkからNeoPixelのエフェクトや色を変更する方法として、config.hで事前に定義する方法と、NeoPixel用に割り当てられたキーコードを使用する方法があるよ。キーコードで変更した場合、変更後の値がRP2040のフラッシュに記憶されて、RP2040の電源を入れ直しても前回のNeoPixelの状態を維持できるようになっているよ。ただ、この値が残っていると、config.hを変更してもその通りにNeoPixelが点灯しない原因になるから、ここでは、キーコードを無効にすることで、config.hで意図した通りにNeoPixelを点灯させるようにしているよ。
RGBLIGHT_EFFECT_RAINBOW_MOOD
RAINBOWのエフェクトを使用するための定義だよ。
RGBLIGHT_DEFAULT_MODE
NeoPixelのエフェクトの初期値としてRAINBOWを指定しているよ。
動作確認
ここまででNeoPixelの設定が完了したから、もう一度ファームウェアを作成してXIAO RP2040に書き込んでみてね。
qmk complile
qmk flash
XIAO RP2040にファームウェアが正常に書き込めたら、DIYキーボードキットに搭載された4つのNeoPixelが色々な色に変化していることを確認してね。
もう少し実用的にしてみよう
エンコーダとNeoPixelが設定通りに動作していることが確認できたかな?エンコーダとNeoPixelを制御するための基本的な設定はこれで完了だけど、実際にキーボードとして便利に使用するには、もう少し工夫した方が良さそうだね。
ここまでの設定だと、NeoPixelはRAINBOWエフェクトしか使えないから、ここからは、DIYキーボードキット上のキー操作で色を変えたり、エフェクトを変えたりできるように設定を変更してみるよ。
レイヤー
qmkはレイヤーという概念があって、レイヤーごとにキーマップが作成できて、レイヤーを切り替えることで、別のキーマップに素早く切り替えることができるよ。qmkでは最大32枚のレイヤーを作成することができるよ。
qmkのキーマップとレイヤーの説明は以下に詳しく書いてあるよ。
作りたいもの
もう少し実用的なキーボードにするために、DIYキーボードキットに搭載された2つのエンコーダと4つのNeoPixelをそれぞれ以下のように制御するよ。ここでは、2枚のレイヤーにそれぞれキーを割り当てて、1枚目のレイヤーではPCへのキー入力に、2枚目のレイヤーではNeoPixelの設定変更をできるようにしてみるよ。
Layer0
- Enc1: 時計回り=PageDown、反時計回り=PageUp
- Enc2: 時計回り=Vol up、反時計回り=Vol down
- Key1: 文字A入力
- Key2: 文字B入力
- Key3: 文字C入力
- Key4: 文字D入力
- A+B: 押している間のみLayer1へ切り替え
Layer1(NeoPixelの設定変更)
- Enc1: 時計回り=Hueの値を増加、反時計回り=Hueの値を減少
- Enc2: 時計回り=Val(Brightness)の値を増加、反時計回り=Valの値を減少
- Key1: 無効
- Key2: 無効
- Key3: 前のLEDエフェクト
- Key4: 次のLEDエフェクト
LEDのエフェクトは、qmkに用意されている以下のエフェクトを使用するよ。
- RGB Static Light
- RGB Breathing
- RGB Rainbow Mood
- RGB Rainbow Swirl
レイヤーの設定
まずは2枚のレイヤーを作成して、それぞれにキーを割り当てる方法を説明するよ。
レイヤーの設定のために編集するファイルは以下の1つだよ:
- nanana_diy/keymap/default/keymap.c
keymap.c
keymap.cを開いて、以下のように修正するよ。
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(
KC_A, KC_B, KC_C, KC_D
),
[1] = LAYOUT(
KC_NO, KC_NO, RGB_MODE_REVERSE, RGB_MODE_FORWARD
)
};
#if defined(ENCODER_MAP_ENABLE)
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {
[0] = { ENCODER_CCW_CW(KC_PAGE_UP, KC_PAGE_DOWN), ENCODER_CCW_CW(KC_VOLD, KC_VOLU) },
[1] = { ENCODER_CCW_CW(RGB_HUD, RGB_HUI), ENCODER_CCW_CW(RGB_VAD, RGB_VAI) }
// Encoder 1 Encoder 2
};
#endif
1枚だけのレイヤーの場合、[0]=LAYOUT(..)のみがあったと思うけど、[1]=LAYOUT(..)を定義することで2枚目のレイヤーを追加することができるよ。ここではkaymapとencoder_mapそれぞれに[1]=LAYOUT(..)を追加して、2枚目のレイヤーにキーを割り当てているよ。
keymapの2枚目のレイヤーでは、Key3を押した時に前のLEDエフェクトへ変更、Key4を押した時に次のLEDエフェクトへ変更するためのキーを割り当てているよ。2枚目のレイヤーに切り替わっている間はKey1とKey2は押しっぱなしになっているから、Key1とKey2は無効にしているよ。
[1] = LAYOUT(
KC_NO, KC_NO, RGB_MODE_REVERSE, RGB_MODE_FORWARD
)
encoder_mapの2枚目のレイヤーでは、Enc1が反時計回りの時にRGBのHueを減少、時計回りの時にRGBのHueを増加、Enc2が反時計回りの時にRGBのVal(Brightness)を減少、時計回りの時にRGBのValを増加させるようにキーを割り当てているよ。
[1] = { ENCODER_CCW_CW(RGB_HUD, RGB_HUI), ENCODER_CCW_CW(RGB_VAD, RGB_VAI) }
ここまででレイヤーの設定は完了だよ。
COMBOキーの設定
次にCOMBOキーの設定をするよ。COMBOキーというのは、2つ以上のキーの組み合わせることで、キーに割り当てられているキーとはまた別のキーを入力するための機能だよ。
先ほどのレイヤーの設定で2枚目のレイヤーを定義したけど、この2枚目のレイヤーに切り替えるためのキーが必要だよね。レイヤー切り替え専用のキーがあればベストだけど、DIYキーボードキットのようなマクロパッドはキーの数が少ないから、特定の2つのキーを押すことで、レイヤーを切り替えられるようにするよ。
COMBOキーの設定のために編集するファイルは以下の1つだよ:
- nanana_diy/rules.mk
- nanana_diy/keymap/default/keymap.c
rules.mk
rules.mkを開いて以下の1行を追加するよ。この1行を追加することで、qmkでCOMBOキーが有効になるよ。
COMBO_ENABLE = yes
keymap.c
keymap.cを開いて、以下のコードを追加するよ。
const uint16_t PROGMEM test_combo1[] = {KC_A, KC_B, COMBO_END};
combo_t key_combos[] = {
COMBO(test_combo1, MO(1))
};
コードを少し説明すると、
const uint16_t PROGMEM test_combo1
test_combo1では、キーの組み合わせを定義しているよ。AとBが押された時にLayer1へ切り替えたいから、KC_A, KC_Bを指定しているよ。COMBO_ENDはシーケンスの終わりを示すために必ず最後に必要だよ。
combo_t key_combos
key_combosでは、COMBOキーのリストにキーの組み合わせを追加しているよ。今回はCOMBOキーはA+Bの1つしかないから、COMBO(test_combo1, MO(1))を1つだけ追加しているよ。MO(1)はCOMBOキーの組み合わせでキーが押されている間だけLayer1へ切り替えるという意味だよ。
MO(x)以外にもたくさん切り替え方法があるから、詳しくはこちらを参考にしてみてね。
NeoPixelのエフェクト追加
最後にNeoPixelにRAINBOW以外のエフェクトを追加するよ。
NeoPixelのエフェクト追加のために編集するファイルは以下の1つだよ:
- nanana_diy/config.h
config.h
config.hを開いて、NeoPixelのエフェクトを定義している部分を以下のように修正してね。今回はキーコードでNeoPixelのエフェクトを切り替えるからRGBLIGHT_DISABLE_KEYCODESはコメントアウトしておいてね。以下のように修正することで、RAINBOWに加えて、BREATHINGとRAINBOW_SWIRLのエフェクトも使えるようになるよ。
//#define RGBLIGHT_DISABLE_KEYCODES
#define RGBLIGHT_EFFECT_BREATHING
#define RGBLIGHT_EFFECT_RAINBOW_MOOD
#define RGBLIGHT_EFFECT_RAINBOW_SWIRL
動作確認
ここまででレイヤーの設定、COMBOキーの設定、NeoPixelのエフェクト追加が完了したよ。最後にファームウェアを作成してXIAO RP2040に書き込んで動作確認をするよ。
qmk complile
qmk flash
XIAO RP2040にファームを書き込めたら、Key1とKey2を同時に押して、レイヤーが切り替わるかどうか確認してみてね。Key1とKey2を押しながら、エンコーダを回したり、Key3やKey4を押してNeoPixelのエフェクトを切り替えたりしてみてね。
NeoPixelのエフェクトはエフェクトによっては複数のアニメーションパターンがあって、今回使用した3つのエフェクトは以下のようになっているから、別のエフェクトに切り替えるためには、キーを何回か押す必要があるよ。
RGBLIGHT_MODE_STATIC_LIGHT
RGBLIGHT_MODE_BREATHING
RGBLIGHT_MODE_BREATHING+1
RGBLIGHT_MODE_BREATHING+2
RGBLIGHT_MODE_BREATHING+3
RGBLIGHT_MODE_RAINBOW_MOOD
RGBLIGHT_MODE_RAINBOW_MOOD+1
RGBLIGHT_MODE_RAINBOW_MOOD+2
RGBLIGHT_MODE_RAINBOW_SWIRL
RGBLIGHT_MODE_RAINBOW_SWIRL+1
RGBLIGHT_MODE_RAINBOW_SWIRL+2
RGBLIGHT_MODE_RAINBOW_SWIRL+3
RGBLIGHT_MODE_RAINBOW_SWIRL+4
RGBLIGHT_MODE_RAINBOW_SWIRL+5
まとめ
QMK firmwareを使用してエンコーダとNeoPixelを制御する方法について説明したよ。また、レイヤーとCOMBOキーを使用することで、DIYキーボードキット上のキー操作でキーマップを切り替えてNeoPixelのエフェクトを変更する方法についても説明したよ。
前回の記事と今回の内容でDIYキーボードキットに搭載された全ての機能を使用したqmkのファームウェアを作成することができるよ。qmkには他にも色々な機能があるから、色んなことを試して、オリジナルのキーボードを作ってみてね。
じゃあ、またね!
Discussion