Digisparkの良さを味わう（ESP32とI2C通信してWiiリモコンを無線マウス化する）

# はじめに
タイトルは長いですが、要するに以下のようにWiiリモコンをマウスにしちゃったというお話です。

![作ったもの.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155449/cec5bf06-8848-a8aa-6ddc-6fd72d17ce9d.png)

PCのBluetoothアプリを使用してWiiリモコンでマウス操作するものはあるようですが、ちょっと好きにはなれません。
・理由１：PCでアプリを走らせるための仕組みが面倒（起動スクリプトや手動起動）
・理由２：別のPCで使う場合、Bluetoothのペアリングが必要で面倒

そこで、以下のDigispark的三段論法？に至ったというわけです。

DigisparkはUSBマウスのように接続してすぐに使える
　↓
ESP32はWiiリモコンとBluetoothで通信できる
　↓
DigisparkとESP32がタッグ（I2C）を組めば強い
　　
Digispark(とESP32)、すばらしい:clap_tone1:


# 使用したもの
* [ESPr® Developer 32](https://www.switch-science.com/catalog/3210/)　 ※本記事で「ESP32」と呼称  
* ESP-IDF (xtensa-esp32-elf at the 1.22.0-80)　→ Ubuntu18.04上に環境を構築
* [Digispark](https://www.amazon.co.jp/HiLetgo-Digispark-Kickstarter-ATTINY85-%E8%B6%85%E5%B0%8F%E5%9E%8BArduino%E4%BA%92%E6%8F%9B/dp/B07BJ2F2WZ)
* Arduino IDE (バージョン1.8.5) 
* [USBコネクタ(マイクロB)](https://www.switch-science.com/catalog/1599/)
* Wiiリモコン

# 結線

以下の通りに繋げました。
　

|USBコネクタ  |ESP32  |Digispark  |備考  |
|---|---|---|---|
|+5V  |VIN  |5V  ||
|GND  |GND  |GND  ||
|D+  | NC |D+  ||
|D-  | NC |D-  ||
|NC |IO25  |P0(SDA)  |ESP32のソフトウェアでプルアップ|
|NC |IO26  |P2(SCL)  |ESP32のソフトウェアでプルアップ|
※NC：未接続

# 作成手順１：Digisparkのソフトウェアを書き込む

１. Arduino IDEに以下のライブラリを追加する  

 - [TinyWireS](https://github.com/rambo/TinyWire)

※: zipファイルを解凍して、その中の「TinyWireS」をArduinoIDEで「スケッチ-> Include Library -> Add ZIP Library...を選択」と選択する

２. Arduinoのスケッチ[(githubに置きました)](https://github.com/bigw00d/wiimote-mouse-demo/blob/master/digispark-i2c2mouse/digispark-i2c2mouse.ino)を取得する


３. ArduinoIDEでDigisparkにスケッチを書き込む

# 作成手順２：WiiリモコンのMACアドレスを取得する

[「BTさがしてアドレス表示 + ペアリング for Bluetooth」](https://play.google.com/store/apps/details?id=com.jojoagogogo.bti)というAndroidアプリを使ってMACアドレスを取得します。

WiiリモコンのAボタンとBボタンを同時に押し、アプリで検索するだけで取得できます。

[jp-96さんの記事](https://qiita.com/jp-96/items/86dc3a95b2732aa78c77#mac%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E3%81%AE%E7%A2%BA%E8%AA%8D)を参考にさせていただきました。

# 作成手順３：ESP32にソフトウェアを書き込む

１. [btstack](https://github.com/bluekitchen/btstack)をクローンする  

```
$ git clone https://github.com/bluekitchen/btstack.git
```

２.btstackのexampleフォルダにコード[(githubに置きました)](https://github.com/bigw00d/wiimote-mouse-demo/blob/master/wiimote_i2c_converter.c)をwiimote_i2c_converter.cとして配置します。

※wiimote_addr_string = "AA-AA-AA-AA-AA-AA" の値は、１つ前の手順で取得したWiiリモコンのMACアドレスに変更してください。

３．ESP32にソフトウェアを書き込む

```
$ cd port/esp32
$ ./integrate_btstack.py
$ cd example/wiimote_i2c_converter
$ make menuconfig
$ make
$ make flash
```

※make menuconfigで設定画面が出るので、「Serial flasher config」->「Default serial port」からUSBのシリアルポートを設定する(ttyUSB0とか）
※シリアルポートは「$ ls -l /dev/serial/by-id/」で確認した

# 使用方法

１. USBケーブルでPCとUSBコネクタ(micro B)を接続する  

２. Wiiリモコンの①ボタンと②ボタンを同時に押す（１．の実行後にすぐに行う）

３. WiiリモコンがESP32と接続するとWiiリモコンの右端のLEDのみの点灯に変わる（下図参照）
![remocon_nontoumei.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155449/7e3173ad-dfd6-c5a7-c6bf-9e9f89ca245f.png)

４. Digisparkが使用可能となると、DigisparkのLEDが消灯→点灯に変わる（恐らく３．の間に点灯していますが・・・）


# 雑感
Bluetoothの後にI2Cを介しているので（データのハンドリング処理で）操作の応答性が心配でしたが、思ったよりも良さそうです。

ただし、斜めのカーソル移動がしづらいので、その辺りを含めてマウス操作の改善の余地はありそうです。（Digisparkのスケッチの改良）

また、WiiリモコンのLEDや振動機能を使うことができるので、その辺りのアレンジをしてみると面白そうです。（詳細は後述する「おまけ」をご覧ください）


それでは、見ていただいてありがとうございました。
тнайк чoμ_〆(・ω・｡)			
			
# おまけ

### WiiリモコンのLED操作について

WiiリモコンとESP32のBluetooth接続時に4番目のLEDを光らせています。実はここの動作には「[Feedback Features](http://wiibrew.org/wiki/Wiimote#Feedback_Features)」というWiiリモコン動作の仕組み（仕様？）を利用しています。
そして、「Feedback Features」には以下のようなものがあるので、例えば「Bluetooth接続時に振動させる」といったことが容易に行えます。(以下のRummbleを使用する）
・Player LEDs
・Rumble（振動機能）
・Speaker

今回、Bluetooth接続時に実際にLEDを光らせているコードは以下の部分です。接続時に「nitifyConnect 」をtrueにします。そして、起動時のL2CAP_EVENT_CAN_SEND_NOW（キー操作時にも実行する）でLED4を点灯させるデータ(0xA2, 0x11, 0x80)をWiiリモコンに送ります。
参考：[Player_LEDsの説明資料](http://wiibrew.org/wiki/Wiimote#Player_LEDs)

```wiimote_mouse_demo.c（210行目辺り）
case L2CAP_EVENT_CAN_SEND_NOW:
    if(channel == l2cap_wiimote_interrupt_cid){
        if(nitifyConnect) {
            nitifyConnect = false;
            wiimote_data |= WIIMOTE_FEEDBACK_EVENT_LED4; //detect connection
        }
        uint8_t report[] = { 0xA2, 0x11, wiimote_data };
        printf("L2CAP_EVENT_CAN_SEND_NOW: 0x%02x\n", wiimote_data);
        l2cap_send(l2cap_wiimote_interrupt_cid, (uint8_t*) report, sizeof(report));
    }
    break;

```

例えばこのwiimote_dataをFeedback Featuresの仕様に従って変えてやれば、いろいろ面白いことができるというわけです(ΦωΦ)ﾌﾌﾌ…

# 参考記事
 + Digispark(ATTiny85) をI2CのSlaveで使用(TinyWireS)して、RaspberryPi(Master)と通信してみる
  + https://qiita.com/mt08/items/46d73c4e1957c1eb55f5
 + ESP32にWiiリモコンを接続して十字キーでLチカする
  + https://qiita.com/jp-96/items/ff3822ab81f7696172c0
 +  BTstack Manual(ESP32の箇所)
  + http://bluekitchen-gmbh.com/btstack/ports/existing_ports/#sec:esp32Port


# 更新履歴
* 2019-12-12：新規作成