プログラマブルテンキーを作る

# はじめに

[BUFFALOのテンキーボードBSTK100](https://www.buffalo.jp/product/detail/bstk100wh.html)に[ATmega32U4マイコンボード](https://www.diymore.cc/products/diymore-beetle-badusb-micro-atmega32u4-au-development-expansion-module-board-for-arduino-leonardo-r3-5v-i2c)を組み込み、プログラマブルテンキーボードに改造する。

[<img alt="" width="300" src="https://images-na.ssl-images-amazon.com/images/I/51HHdoIJ%2BzL._AC_SY450_.jpg">](https://www.amazon.co.jp/dp/B01L8VIHAY/) [<img alt="" width="180" src="https://www.amazon.co.jp/images/I/610SxrdhPAL._AC_SL1000_.jpg">](https://www.amazon.co.jp/dp/B07MMB4HPF/)



# テンキーボードBSTK100を分解する

BSTK100は安価で、分解が容易、かつ、くさび型のため内部にマイコンを格納するスペースに余裕がある。
![IMG_7634.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/5803b7d3-863a-e2c9-813a-bce118c0e45c.png)

本体裏側から2本のネジを外すだけで簡単に分解できる。内部のプリント基板もネジ1本で留まっているだけ。
![IMG_7609.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/61febdf7-a18c-df4a-b382-db3ec67af26f.png)
キートップは本体表面に留まっている。キーマトリクスフィルムは11ピンのフレキシブルケーブルでプリント基板のソケットに接続されている。
![IMG_7615基板.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/f4e4a0ae-143a-9869-4629-a06801bd9912.png)
基板にはCol/Row番号をシルク印刷した[ランド](https://unicraft-jp.com/pcb/dictionary/R100.shtml)が用意されており、このランドに[ポリウレタン銅線](https://www.amazon.co.jp/dp/B011IJQVOA/)を簡単にハンダ付けできる。
NumLockキーは基板右側のタクトスイッチ(K1)となっている。その右側にLED(D2)<font color=green>青色</font>がある。このテンキーをWindowsPCで普通に使用すると、NumLockのオン/オフに連動して<font color=green>LED</font>が点灯/消灯する。


# キーマトリクスを調べる

11ピンコネクタ(J2)の左から順に以下のCol/Rowとなっている。

| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| Col0 | Col1 | Col2 | Col3 | Row0 | Row1 | Row2 | Row3 | Row4 | Row5 | Col4 |

また、キーマトリクスは以下の通り。

| 行\列    | Col0 | Col1 | Col2 | Col3 | Col4 |
|:-:|:-:|:-:|:-:|:-:|:-:|
| Row0 | NumLock  |   |   |   |   |
| Row1 |    | -  | *  | /  |   |
| Row2 | 7  | 8  | 9  | BackSpase  |   |
| Row3 | 4  | 5  | 6  | +  |   |
| Row4 | 1  | 2  | 3  | Enter  | Tab |
| Row5 | 0  | 00 |    | .  |   |

Row0が`NumLock`キーだけの割り当てのため、Row0をRow1に短絡させることで、1行減らすことができる。

| 行\列    | Col0 | Col1 | Col2 | Col3 | Col4 |
|:-:|:-:|:-:|:-:|:-:|:-:|
| Row0/1 | <font color=red>NumLock</font>   | - | * | / |   |
| Row2 | 7  | 8  | 9  | BackSpase  |   |
| Row3 | 4  | 5  | 6  | + |   |
| Row4 | 1  | 2  | 3  | Enter  | Tab |
| Row5 | 0  | 00 |    | . |   |

Col4も`Tab`キーだけの割り当てのため、1列減らしたいところであるが、Row4のためそれができない（Row5なら減らせた）。結局、デジタルピンが10本必要となる。




# <font color=green>LED</font>の配線引き出し

プリント基板上の<font color=green>LED</font>の配線を追っていくと、一方（赤線）は、1KΩのチップ抵抗を経由して`5V`とシルク印刷されたランドに繋がっている。他方（青線）は、黒い樹脂で固められたマイコンに向かっていることがわかる。5V側がアノード、マイコン側がカソードだ。カソード側にはランドがないので、適当な場所の[レジスト](https://unicraft-jp.com/article/resist.shtml)を削ってはんだ付けする必要があるが、抵抗も含めてそのまま使える。
![IMG_7615_基板l.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/240715c7-a19a-d42c-e3b1-8de0d41c5e59.png)



# ATmega32U4ボードのデジタルピンに対応させる

今回は以下のように割り当てることにする。

| Col0 | Col1 | Col2 | Col3 | Col4 | Row0/1 | Row2 | Row3 | Row4 | Row5 | <font color=green>LED</font> |
|:---:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:--:|:--:|:---:|
| RX | TX | D11  | D10 | D9 | A0 | A1 | A2 | MO | MI | SCK |
| 0  | 1  | 11   | 10  | 9  | 18 | 19 | 20 | 16 | 14 | 15  | 


テンキーの<font color=green>LED</font>はプログラムからON/OFFできるようにするため、アノード側はSCK(D15)へ、カソード側はGNDへ接続する。



# USBケーブルの配線

基板左側にハンダ付けされているUSBケーブルを取り外し、ATmega32U4ボードのUSB端子に下図の通り結線する。
<img alt="usb_4.png" width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/0b493fd0-d870-1984-4bcc-62cca6a0c884.png">

**ポリウレタン銅線で結線した様子。**
![IMG_7637.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/30e55a9a-7beb-3764-0f9f-1499be06b62a.png)


# 導通確認

[Keypadライブラリ](https://github.com/Chris--A/Keypad)を使用してテストプログラムを作成する。テンキーボードのキーを押したときにキートップ文字がシリアルモニターに出力されれば結線は正常。同時にテンキー上の<font color=green>LED</font>が点滅する。
`Serial.print`の代わりに`Keyboard.print`とかに変更すれば、一旦、元のテンキーの機能が復活する。

```cpp:導通確認プログラム
#include <Keypad.h>

//digital pins
#define PIN_SCK (15)
#define PIN_MI  (14)
#define PIN_MO  (16)
#define PIN_A2  (20)
#define PIN_A1  (19)
#define PIN_A0  (18)
#define PIN_D9   (9)
#define PIN_D10 (10)
#define PIN_D11 (11)
#define PIN_TX   (1)
#define PIN_RX   (0)

#define LED_BLUE PIN_SCK

const byte ROWS = 5; // 5 rows
const byte COLS = 5; // 5 columns

// Define the Keymap
char keys[ROWS][COLS] = {
  {'n', '-', '*', '/', '\0'},  // n:numlock
  {'7', '8', '9', 'b', '\0'},  // b:backspace
  {'4', '5', '6', '+', '\0'},
  {'1', '2', '3', 'e', 't'},   // e:enter,  t:tab
  {'0', 'z', '\0', '.', '\0'}, // z:00
};

byte rowPins[ROWS] = { PIN_A0, PIN_A1, PIN_A2, PIN_MO, PIN_MI };
byte colPins[COLS] = { PIN_RX, PIN_TX, PIN_D11, PIN_D10, PIN_D9 }; 

// Create the Keypad
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

void setup() {
  pinMode(LED_BUILTIN, OUTPUT); //onboard RED led
  pinMode(LED_BLUE, OUTPUT); // tenkey BLUE led
  Serial.begin(115200);
}

void loop() {
  char key = keypad.getKey();
  if (key) {
    Serial.print(millis());
    Serial.print("\t");
    Serial.println(key);
    ledSign();
  }
  delay(10);
}

void ledSign() {
  digitalWrite(LED_BUILTIN, HIGH);
  digitalWrite(LED_BLUE, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  digitalWrite(LED_BLUE, LOW);
}
```


ここまで来たら、各々のキーにお好みのキーコードやキーコードシーケンスを割り当てることで、自分専用のカスタマイズキーボードは完成だ。



# 128x32ドットOLED液晶ディスプレイモジュールを組み込む

このテンキーボードは内部スペースに余裕があるので、さらに128x32ドットOLED液晶ディスプレイモジュールも組み込んでみる。
[<img alt="" width="300" src="https://images-na.ssl-images-amazon.com/images/I/61UlZuoyQtL._SX522_.jpg">](https://www.amazon.co.jp/dp/B01M8JV310/)
**I2C**接続のため、ATmega32U4ボードのSCL/SDAに接続するだけ。ただし、ピンヘッダーが最初からハンダ付けされているので、これを取り外してポリウレタン銅線で結線する。
テンキーの上部にH12mm x W32mmの四角い穴を開けて裏から留める。BUFFALOの文字が一部欠けてしまうが仕方ない。
<img alt="IMG_7631.png" width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/25615b86-a2e0-122b-07b1-95baf02e0b50.png"> ![BSTK100WH_front.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/d69dc30a-6ad2-46f6-5722-bd5b6f069ce5.jpeg)

綺麗に加工するのは難しい。歪になってしまった。
<img alt="IMG_7639.png" width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/97787d43-0087-8932-29ce-9efd5fb93797.png">


このディスプレイに種々情報を表示することで、プログラマブルの幅が広がる。例えば、NumLockキーをモード切り替えのキーとして、N面のモードをサポートし、モードごとにキーとキーコードの対応をさせることで、19キー×N面＝数十〜数百通りのキーコードを割り当て可能となる。これは一例なので、様々工夫することで、さらに使いやすいプログラマブルキーボードになるはずだ。

<img alt="mv.gif" width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/54e8d26c-ff43-29ad-0097-bc4f81ccefa0.gif">
表示ライブラリは[U8g2](https://github.com/olikraus/u8g2)を使用した。

**例として、**

- 10キーモード：キートップ文字通りのキーコードを送出
- マウスモード：マウスを1ドッド単位で上下左右に移動。マウス右/左ボタンのロック。
- カーソルモード：矢印キーコードを送出。Shift/Control/Altキーのロック。
- Preset1：Windowsで便利なキーコードを送出
- Preset2：Macで便利なキーコードを送出
- Preset3：仕事で便利なキーコードを送出

電卓モードがあってもいいかも。電卓のように四則演算した結果をPCへ送出することも可能だ。実際、電卓モードを備えたテンキーも[販売されている](https://www.amazon.co.jp/s?k=電卓付きテンキー)。


# おわりに

ディスプレイを付けたことで、プログラマブルの幅を広げることができた。実際に何をどう割り当てるかは、今後ゆっくり考えることにする。

<br>
<hr>


**＜2021.9.28追記＞**
その後、マウス移動やカーソル移動系の機能は、こちらの[回転型デバイス](https://qiita.com/nak435/items/44897e080ab51208ca3c)に役割を移したため、当記事のプログラマブルテンキーはディスプレイが必要なほど多機能である必要がなくなった。そのため、ディスプレイ無しのシンプルなものに作り直した。

モードは3つだけ。

1. オリジナルテンキーのNumLockオン時のキーコード送出（<font color=green>LED</font>点灯）
1. オリジナルテンキーのNumLockオフ時のキーコード送出（<font color=green>LED</font>消灯）
1. PC普段使いで便利なキーコードを送出（<font color=green>LED</font>点滅）

**プログラマブルテンキー**としては、**3.**のモードだけとなり、使えるキー数はMax19と減ったが、普段使いとしてはこれだけあれば十分である。実際、半数ほどのキーが未割当のままだ。



**以上**

https://qiita.com/nak435/items/9ec70ec5c3b42e3738b5

https://qiita.com/nak435/items/bbe04300c67c37febb7e

https://qiita.com/nak435/items/44897e080ab51208ca3c