15
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

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

Last updated at Posted at 2021-09-30

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

20210930_164514-01.jpeg
これを作りました。

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

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

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

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

コンセプト

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

試したい要素と技術

無線(Bluetooth)

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

電池

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

フルカラーLED

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

回路図設計

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

基板図設計

名刺サイズにしました。名刺ケースとしても使えるようにしたかった(未実装)。
image (5).png
このあと、ゾーンを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);
  }
}
```

# 組み立て
ソケットにしたので、キースイッチの交換が出来ます。
![20210930_161913-02.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500333/bc5e2be3-cd4f-7e08-b09b-1f32ff34dc5b.jpeg)
フルカラーLEDも期待通りに動作しました。
![20210930_162106-01.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500333/7da10cf9-1606-20e9-dc94-582e18c75d7d.jpeg)
充電して、Bluetooth接続も出来ました。

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

## 要改善箇所
### 厚さ
約40mm。ほかの自作キーボード(mint60など)と比べると10mm程度厚い。電源を内蔵しているので、仕方ないところもありますが、もう少しスリムにしたいですね。
![20210930_162320-01.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500333/1eba667a-7d29-0878-4e89-b203c8229df7.jpeg)

### Bluetooth接続
AndroidとWin10には接続出来たのですが、[Macには接続出来ません](https://qiita.com/optimisuke/items/b258b1c7a0d2388bde64)でした。ライブラリをそのまま使っているので、接続部分を自分で書く必要がありそうです。

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

### 見た目
基板表面が見えたほうが洒落ていると考え、トッププレートを透明にしたのですが、汚いはんだが見えてしまうのは盲点でした。
色の濃い背景の上に透明アクリルを配置すると、薄く反射するのできれいなのですが、無難にいくなら透過しないプレートがベターですね。
![20210930_162447-01.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500333/d94f285a-eb54-b0c6-4027-016c50b9889c.jpeg)
↑ ここ、好きところとダメなところが同時に同時に楽しめる角度。

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

↓ 只今の進捗。
![スクリーンショット 2021-09-17 141305.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500333/fa101a83-1efc-36ce-3f4c-33833c69b0c8.png)
乞うご期待!!!
(ここに第2回のリンク貼る)
15
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?