RaspberryPiWのBLEを使用してPC1のキーボード入力をPC2に渡す

# はじめに
<!-- 発端や概要を記載 -->
この記事は以下に該当する読者を想定しています。
- Windows11
- Arduino IDE 2.3.2
- Arduino IDEでArduino系を使い慣れている
- Rasberry Pi Pico W を購入したが、Pythonプログラム用にRasberry Pi系を購入してセットアップするのが面倒で、Arduino IDEにRasberry Pi Pico ボードを追加してLチカまではできるようになり、次はBLEにでも挑戦してみよう、ぐらいの段階

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [発端](#1発端)
1. [発想](#2発想)
1. [成果物](#3成果物)
1. [シリアル通信部分抜粋](#4シリアル通信部分抜粋)
1. [BLE部分抜粋](#5ble部分抜粋)
1. [考察・感想・その他](#6考察感想その他)

<!-- 各チャプター -->
# 1.発端
発端は以下の通りです。
- ノートPCを持っていた。
- Windows11 Home搭載・ハンドヘルドタイプのゲーム用PCを購入し、ごく稀にキーボードが欲しくなりそうだと思った。
- 購入して眠らせているRaspberry Pi Pico W があった。
- びっくりするほど暇だった。


# 2.発想
1. 元々持っていたノートPC(以下、PC1)とRaspberry Pico W(以下、PicoW)間でUSBシリアル通信を行う。
1. PicoWをBLEキーボードのフリをさせ、新しく購入したゲーム用PC(以下、PC2)とペアリングする。
1. PC1からUSBシリアル通信で送られてきたキーボード入力をBLEでPC2に流す。


# 3.成果物
```C:MyBLEKeyboard.ino
#include <KeyboardBLE.h>

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200);
  KeyboardBLE.begin("MyBLEKeyboard");
  delay(5000);
}

void loop() {
  static bool led_state = false;
  static uint32_t last_blink_time = 0;
  const uint32_t blink_cycle = 1000;

  static uint32_t last_serial_check_time = 0;
  const uint32_t serial_check_cycle = 5;

  delay(1);

  uint32_t now = millis();

  if(now - last_blink_time > blink_cycle) {
    last_blink_time = now;
    led_state = !led_state;
    digitalWrite(LED_BUILTIN, led_state);
  }

  if(now - last_serial_check_time > serial_check_cycle) {
    last_serial_check_time = now;
    if(Serial.available()) {
      char key = Serial.read();
      Serial.print("get:");
      Serial.println(key);

      KeyboardBLE.print(key);
    }
  }
}
```
加えて、ツールで以下を選択する必要があります。
- **ボード: "Raspberry Pi Pico W"**
- **IP/Bluetooth Stack: Bluetoothが含まれるいずれか**
:::note info
LEDの点滅部分は、動いている感を出したかっただけなので読み飛ばしてください。
:::


# 4.シリアル通信部分抜粋
```C:Serial.ino
void setup() {
  Serial.begin(115200);
}

void loop() {
  if(Serial.available()) {
    char key = Serial.read();
    Serial.print(key);
  }
}
```
Arduino系と同じ書き方でOKでした。
Arduino系を使い慣れていれば説明は不要かと思います。


# 5.BLE部分抜粋
```C:BLE.ino
#include <KeyboardBLE.h>

void setup() {
  KeyboardBLE.begin("MyBLEKeyboard");
  delay(5000);
}

void loop() {
  delay(1000);
  KeyboardBLE.print('a');
}
```
:::note warn
抜粋としていますが、説明のための最小構成です。
1秒に1回、'a'を送信するコードです。
:::
1. **KeboardBLE.h** をincludeする必要があります。(ボードと一緒にインストールされるので、特に追加作業はありません)
1. **KeyboardBLE.begin("MyBLEKeyboard");** で初期化します。PC2から引数で与えた文字列のキーボードデバイスとして検出できるようになります。(引数なしの場合はデフォルトのPicoW BLE Keyboardとなります。)
1. **KeyboardBLE.print('a');** で、接続済みデバイスへ引数のキーを送信します。
1. 前述の通り、ツールで**IP/Bluetooth Stack: Bluetoothが含まれるいずれか** を選択する必要があります。初期状態では、**IPv4 Only** が選択されており、コンパイルエラーが出ます。
:::note warn
PicoWとPC2のペアリング操作は、PC2に標準で備わっているBluetooth機能で行います。
:::


<a id="#Chapter6"></a>
# 6.考察・感想・その他
- ほぼスケッチ例の**KeyboardBLE->BLESerial** がそのまま使用できた。
- つまづくとすれば、**IP//Bluetooth Stack:** の部分ぐらいか。
- PC1とPicoWのUSBシリアル通信には、マイコンシリアル通信で使い慣れたTera Termを使用したが、Tera Termが処理してくれないキー(半角/全角キーやファンクションキーなど)をどう送るかが課題。案としては、あきらめる、使用頻度が低いキーをその辺に割り当てる、キーボード入力をすべてフックするWindowsアプリを探すか作る等が考えられるが、本題とは別の話なのでここで一旦良しとする。
- 買ってから全く触っていないPicoWがあったのでPicoWを使用したが、基板むき出しのPicoWより、パッケージングされたM5ATOM S3 Liteの方が本件に適していたかもしれない。(PicoWの方がBluetoothのバージョンが上なので全くメリットがないわけではないが)
- 結論 : キーボードを買った方がいい。