夢の無線キーボードを自作したい。 第1話「マクロキーボード」


導入「自作キーボードにBluetoothをひとつまみ」


これを作りました。

遡って1年前、友人から勧められたMint60が初めて触れた自作キーボードでした。
分割キーボードなので、キーボードの間に書見台を置いて文字起こしをしたり、社用のノートPCを置いたり、お皿を置いたりと、デスクワークの利便性が飛躍的に向上しました。ありがとう、Mint60。

そして、ふと思ったわけです。
「これ、無線にしたら最強じゃね?」
と。

しかし、テストもせず、いきなり難度の高いものを作り始めるなんて愚の二乗。
まずは小さく手軽なもの、マクロキーボードを試作してみました。

この記事は、キーボード制作の流れをざっくりと紹介するものになります。個々の説明などはいずれ。

コンセプト

  • 回路の動作検証のため、発注・制作コストを抑える。
  • 後に使いたい技術要素を試験的に盛り込む。

試したい要素と技術

無線(Bluetooth)

Bluetoothを搭載しているArduinoマイコンといえば、ESP32
技術資料も多いので、少なくとも色々試すには良いと思います。
そして何より安い。(国内で1500円、海外の通販で500円)
3.3V系なので、後述する3.7Vの電池との相性がいいのもポイント高いです。

電池

充電したい。乾電池は重い。なら、リチウムイオンポリマー電池を使っちゃいましょう。
今回の試作で特に試験したいのは、ここの充電回路がうまく動くかどうかですね。

フルカラーLED

ゲーミング需要。
開発中の動作確認にも便利です。
キーボードでよく使われているフルカラーチップLEDが5V系ばかりだったので、原始的な4本足のフルカラーLEDを採用しました。

回路図設計

8キーしかないので、キースイッチのダイオードは必要ないから省略。

基板図設計

名刺サイズにしました。名刺ケースとしても使えるようにしたかった(未実装)。

このあと、ゾーンをGNDで塗りつぶします。

発注

PCB(基板)とキーボードアクリルプレートをElecrowさんに発注。
10セットで、

PCB: $19.90
プレート: $5.80 x2
送料: $9.30

合計: $40.80

1万円くらいは覚悟していたので想定より安くて驚きました。

制御

ArduinoIDEにESP32のライブラリを適用して開発しました。
Bluetoothの接続部分は、ESP32 BLE Keyboard libraryを使用させてもらいました。
フルカラーLEDのテストに、RGBにそれぞれスイッチを対応させ、スイッチを押すと色が変化していくようプログラムしました。

#include <BleKeyboard.h>

#define BUILTIN_LED 2
#define LED_R 17
#define LED_G 21
#define LED_B 19
#define KEYSW_1 33
#define KEYSW_2 25
...
#define SETTINGSW 32
#define LEDC_BASE_FREQ 12800
#define LEDC_RESOLUTION 8
#define LEDC_CHANNEL_R 0
#define LEDC_CHANNEL_G 1
#define LEDC_CHANNEL_B 2

BleKeyboard bleKeyboard("BleMacroKeyboard", "BleMacroKeyboardd_manufacturer", 100);

void PwmLed(int channel) {
  static uint8_t brightness[3] = {0, 0, 0};
  static int diff[3] = {1, 1, 1};
  ledcWrite(channel, brightness[channel]);
  if (brightness[channel] == 0) {
    diff[channel] = 1;
  } else if (brightness[channel] == 255) {
    diff[channel] = -1;
  }
  brightness[channel] += diff[channel];
}

int read_all_sw() {
  unsigned int pushed = 0;
  if(digitalRead(SETTINGSW) == LOW) {
    pushed |= (1<<0);
  }
  if(digitalRead(KEYSW_1) == LOW) {
    pushed |= (1<<1);
  }
  if(digitalRead(KEYSW_2) == LOW) {
    pushed |= (1<<2);
  }
  ...
  return pushed;
}

void setup() {
  pinMode(KEYSW_1, INPUT_PULLUP);
  pinMode(KEYSW_2, INPUT_PULLUP);
  ...
  pinMode(SETTINGSW, INPUT_PULLUP);
  pinMode(BUILTIN_LED, OUTPUT);
  digitalWrite(BUILTIN_LED, LOW);
  ledcSetup(LEDC_CHANNEL_R, LEDC_BASE_FREQ, LEDC_RESOLUTION);
  ledcAttachPin(LED_R, LEDC_CHANNEL_R);
  ledcSetup(LEDC_CHANNEL_G, LEDC_BASE_FREQ, LEDC_RESOLUTION);
  ledcAttachPin(LED_G, LEDC_CHANNEL_G);
  ledcSetup(LEDC_CHANNEL_B, LEDC_BASE_FREQ, LEDC_RESOLUTION);
  ledcAttachPin(LED_B, LEDC_CHANNEL_B);
  ledcWrite(LEDC_CHANNEL_R, 0);
  ledcWrite(LEDC_CHANNEL_G, 0);
  ledcWrite(LEDC_CHANNEL_B, 0);
  bleKeyboard.begin();
}

void loop() {
  // static variable defind.
  static unsigned int sw_pushed_saved = 0;
  // measures for chattering.
  if(sw_pushed_saved != read_all_sw()) {
    digitalWrite(BUILTIN_LED, HIGH);
    delay(5);
    // for LED
    unsigned int sw_pushed = read_all_sw();
    unsigned int sw_pushed_xor = sw_pushed ^ sw_pushed_saved;
    if(sw_pushed & (1<<1)) {
      PwmLed(LEDC_CHANNEL_R);
    }
    if(sw_pushed & (1<<2)) {
      PwmLed(LEDC_CHANNEL_G);
    }
    if(sw_pushed & (1<<3)) {
      PwmLed(LEDC_CHANNEL_B);
    }
    // setting sw
    if(sw_pushed_xor & (1<<0)) {
      //
    }
    // ble
    if(bleKeyboard.isConnected()) {
      if(sw_pushed_xor & (1<<4)) {
        if(sw_pushed & (1<<4)) {
          bleKeyboard.press('a');
        } else {
          bleKeyboard.release('a');
        }
      }
      if(sw_pushed_xor & (1<<5)) {
        if(sw_pushed & (1<<5)) {
          bleKeyboard.press(KEY_ESC);
        } else {
          bleKeyboard.release(KEY_ESC);
        }
      }
      ...
    }
    sw_pushed_saved = sw_pushed;
    digitalWrite(BUILTIN_LED, LOW);
  }
}

組み立て

ソケットにしたので、キースイッチの交換が出来ます。

フルカラーLEDも期待通りに動作しました。

充電して、Bluetooth接続も出来ました。

レビュー

得られたもの

やりたかったこと(技術的に)はだいたい出来ました。試作機としては十分。何回か失敗することを想定していたのですが、1回でパスしてしまい拍子抜けです…

要改善箇所

厚さ

約40mm。ほかの自作キーボード(mint60など)と比べると10mm程度厚い。電源を内蔵しているので、仕方ないところもありますが、もう少しスリムにしたいですね。

Bluetooth接続

AndroidとWin10には接続出来たのですが、Macには接続出来ませんでした。ライブラリをそのまま使っているので、接続部分を自分で書く必要がありそうです。

電池もち

300mAhのバッテリーでは、2,3時間で充電が切れてしまうようです。
今回採用した電池は、Li-Poの中では容量の少ない方ですので、もっとバッテリー容量の大きいものを採用する必要がありそうです。
また、消費電力量を抑える工夫なども特にしていないので、そのあたりもやっていきたいですね。

見た目

基板表面が見えたほうが洒落ていると考え、トッププレートを透明にしたのですが、汚いはんだが見えてしまうのは盲点でした。
色の濃い背景の上に透明アクリルを配置すると、薄く反射するのできれいなのですが、無難にいくなら透過しないプレートがベターですね。

↑ ここ、好きところとダメなところが同時に同時に楽しめる角度。

次回

本丸である分割キーボードの制作をします。

↓ 只今の進捗。

乞うご期待!!!
(ここに第2回のリンク貼る)