Arduinoでポケモン剣盾自動化してみた ~自動ワット稼ぎ編~

#はじめに
Nintendo Switchから充電ポートがUSB Type-Cになり、専用のプロコントローラーもUSBになったそうで、ArduinoのUSB HID(ヒューマンインターフェースデバイス)機能を持つLeonardoで自動化してみました。

今回は、自動ワット稼ぎで一躍有名になった(なってない)「ポケットモンスター　ソード＆シールド」を例に進めてみます。

#準備するもの

- PC (自分でPCと呼べるもの)
- USBケーブル(Type-A - micro)
- Arduino Leonardo (ATmega32u4チップ搭載)
- 変換ケーブル(Type-A メス - Type-C オス)

きちんと正規品を買いたかったのですが、お財布が許してくれなかったのでこちらを購入しました。安いですがきちんとしていました。
[-Amazon- HiLetgo Leonardo Pro Micro](https://www.amazon.co.jp/HiLetgo%C2%AE-Leonardo-ATmega32U4-%E3%83%96%E3%83%BC%E3%83%88%E3%83%AD%E3%83%BC%E3%83%80-Arduino%E3%81%AB%E5%AF%BE%E5%BF%9C/dp/B01M6WULAO/ref=pd_bap_rp_1/357-2302559-1831202?_encoding=UTF8&pd_rd_i=B01M6WULAO&pd_rd_r=629f9e1e-551b-4a7f-83df-23aa21fdcaf5&pd_rd_w=APas1&pd_rd_wg=5Vvse&pf_rd_p=9faab08c-64cc-4758-abf5-183e1debc0ca&pf_rd_r=BPVHV22EC9638ZGGKGWD&psc=1&refRID=BPVHV22EC9638ZGGKGWD)

#作業工程
##Arduino IDEのインストール
[Arduinoの公式サイト](https://www.arduino.cc/)に行き、上の __SOFTWARE>DOWNLOADS__ を選択し、 __Download the Arduino IDE__ から自分の環境にあったIDEをダウンロードしてインストール。

##Switch操作用ライブラリをダウンロード
今回は、有志の方によって製作されたライブラリを使用します。[GitHubの公開ページ](https://github.com/celclow/SwitchControlLibrary)に行き、__clone or download__(緑色のプルダウン)から__Downkoad ZIP__を選択し、ダウンロードして、解凍してください。

解凍したフォルダを置く場所が重要で、ダウンロードした__SwitchControlLibrary-master__ディレクトリを、Arduinoがインストールされたディレクトリ(Windowsのデフォルトは _C:\Program files(x86)\Arduino_) の中にある__libraries__というディレクトリに移動してください。Arduino IDEはプログラムをコンパイルする際にこのディレクトリを参照してくれます。

##Arduino IDEを使う
Arduino IDEはソースコードをコンパイルして実機に転送してくれます。今回使うライブラリと一緒に説明していきます。
まずは最初に使うライブラリの宣言をします。今回用いるライブラリはプロコントローラーと同じ信号をArduinoから送信します。

```c++
#include <SwitchControlLibrary.h>
```

次に各ボタンの動作です。

```c++
# Aボタンを押す
SwitchControlLibrary().PressButtonA();
# Aボタンを離す
SwitchControlLibrary().ReleaseButtonA();
```

このように、ボタンを押す動作と離す動作が別になっているので、これらをペアで使っていきます。対応しているボタンは、

```c++
void PressButtonY();
void ReleaseButtonY();
void PressButtonB();
void ReleaseButtonB();
void PressButtonA();
void ReleaseButtonA();
void PressButtonX();
void ReleaseButtonX();
void PressButtonL();
void ReleaseButtonL();
void PressButtonR();
void ReleaseButtonR();
void PressButtonZL();
void ReleaseButtonZL();
void PressButtonZR();
void ReleaseButtonZR();
void PressButtonMinus();
void ReleaseButtonMinus();
void PressButtonPlus();
void ReleaseButtonPlus();
void PressButtonLClick();
void ReleaseButtonLClick();
void PressButtonRClick();
void ReleaseButtonRClick();
void PressButtonHome();
void ReleaseButtonHome();
void PressButtonCapture();
void ReleaseButtonCapture();
```

です。詳しくはライブラリ内の`SwitchControlLibrary.h`を読んでください。

次に矢印ですが、スティックではない方向キーは、

```c++
MoveHat();
```

この関数を利用します。上を0として、8分割して、時計回りに数えます。そして中心が8です。例えば、__右左__ と入力したければ、

```c++
MoveHat(2);
MoveHat(6);
MoveHat(8);
```

となります。最後に真ん中に戻してあげるのを忘れないようにしてくださいね。

#自動化
あとはこれらの関数をうまく組み合わせると自動化の出来上がりです。これらの関数をArduinoの`loop()`に入れてあげることで繰り返し実行することができます。

また、Arduinoの動作はSwitchが認識できる速度より数倍速く動作してしまうので適宜`delay()`を用いて時間調整をしてあげることが必要です。

そんなこんなでできたコードがこちら。

```c++
#include <SwitchControlLibrary.h>

void setup(){
}

void loop() {
  // 開始 みんなで挑戦の直前から。
  SwitchControlLibrary().PressButtonA();
  delay(50);
  SwitchControlLibrary().ReleaseButtonA();
  delay(3000);
  // 募集開始
  SwitchControlLibrary().PressButtonHome();
  delay(50);
  SwitchControlLibrary().ReleaseButtonHome();
  delay(1000);
  SwitchControlLibrary().MoveHat(4); // down
  delay(50);
  SwitchControlLibrary().MoveHat(8); // center
  delay(100);
  SwitchControlLibrary().MoveHat(2); // right
  delay(50);
  SwitchControlLibrary().MoveHat(8); // center
  delay(100);
  SwitchControlLibrary().MoveHat(2); // right
  delay(50);
  SwitchControlLibrary().MoveHat(8); // center
  delay(100);
  SwitchControlLibrary().MoveHat(2); // right
  delay(50);
  SwitchControlLibrary().MoveHat(8); // center
  delay(100);
  SwitchControlLibrary().MoveHat(2); // right
  delay(50);
  SwitchControlLibrary().MoveHat(8); // center
  delay(100);
  SwitchControlLibrary().PressButtonA();
  delay(50);
  SwitchControlLibrary().ReleaseButtonA();
  delay(1500);
  // 設定画面
  SwitchControlLibrary().MoveHat(4); // down
  delay(2000);
  SwitchControlLibrary().MoveHat(8); // center
  delay(50);
  SwitchControlLibrary().MoveHat(2); // right
  delay(50);
  SwitchControlLibrary().MoveHat(8); // center
  delay(50);
  SwitchControlLibrary().MoveHat(4); // down
  delay(50);
  SwitchControlLibrary().MoveHat(8); // center
  delay(50);
  SwitchControlLibrary().MoveHat(4); // down
  delay(50);
  SwitchControlLibrary().MoveHat(8); // center
  delay(50);
  SwitchControlLibrary().MoveHat(4); // down
  delay(50);
  SwitchControlLibrary().MoveHat(8); // center
  delay(50);
  SwitchControlLibrary().MoveHat(4); // down
  delay(50);
  SwitchControlLibrary().MoveHat(8); // center
  delay(50);
  SwitchControlLibrary().PressButtonA();
  delay(50);
  SwitchControlLibrary().ReleaseButtonA();
  delay(500);
  // 時間設定
  SwitchControlLibrary().MoveHat(4); // down
  delay(50);
  SwitchControlLibrary().MoveHat(8); // center
  delay(50);
  SwitchControlLibrary().MoveHat(4); // down
  delay(50);
  SwitchControlLibrary().MoveHat(8); // center
  delay(50);
  SwitchControlLibrary().PressButtonA();
  delay(50);
  SwitchControlLibrary().ReleaseButtonA();
  delay(500);
  // 時間の変更
  SwitchControlLibrary().MoveHat(2); // right
  delay(50);
  SwitchControlLibrary().MoveHat(8); // center
  delay(50);
  SwitchControlLibrary().MoveHat(2); // right
  delay(50);
  SwitchControlLibrary().MoveHat(8); // center
  delay(50);
  SwitchControlLibrary().MoveHat(0); // up
  delay(50);
  SwitchControlLibrary().MoveHat(8); // center
  delay(200);
  SwitchControlLibrary().PressButtonA();
  delay(50);
  SwitchControlLibrary().ReleaseButtonA();
  delay(50);
  SwitchControlLibrary().PressButtonA();
  delay(50);
  SwitchControlLibrary().ReleaseButtonA();
  delay(50);
  SwitchControlLibrary().PressButtonA();
  delay(50);
  SwitchControlLibrary().ReleaseButtonA();
  delay(50);
  SwitchControlLibrary().PressButtonA();
  delay(50);
  SwitchControlLibrary().ReleaseButtonA();
  delay(100);

  SwitchControlLibrary().PressButtonHome();
  delay(50);
  SwitchControlLibrary().ReleaseButtonHome();
  delay(1000);
  SwitchControlLibrary().PressButtonA();
  delay(50);
  SwitchControlLibrary().ReleaseButtonA();
  delay(1000);
  SwitchControlLibrary().MoveHat(4); // down
  delay(50);
  SwitchControlLibrary().MoveHat(8); // center
  delay(500);
  SwitchControlLibrary().PressButtonA();
  delay(50);
  SwitchControlLibrary().ReleaseButtonA();
  delay(1000);
  SwitchControlLibrary().PressButtonA();
  delay(50);
  SwitchControlLibrary().ReleaseButtonA();
  delay(4000);
  SwitchControlLibrary().PressButtonA();
  delay(50);
  SwitchControlLibrary().ReleaseButtonA();
  delay(2000);
  SwitchControlLibrary().PressButtonA();
  delay(50);
  SwitchControlLibrary().ReleaseButtonA();
  delay(1000);
  SwitchControlLibrary().PressButtonA();
  delay(50);
  SwitchControlLibrary().ReleaseButtonA();
  delay(1000);
}
```

個人の環境で若干変化がある可能性があるのでそこは随時変更してください。

できたら、 Arduino IDE の `ツール>ボード` から `Arduino Leonardo` を選択します。

ここからも重要で、SwitchはデバイスのIDが登録外だった場合、信号を受け付けなくなるので、ArduinoのデバイスのIDをSwitchが認識できるものに変えてあげる必要があります。

Arduinoのインストールされたディレクトリから `hardware > arduino > avr` と進み、`boards.txt` の285-286行目を、

```
leonardo.vid.1=0x0f0d
leonardo.pid.1=0x0092
```

と変更してあげます。

完成したら、Arduino IDE に戻って、左上の矢印からマイコンボードに書き込んで完了です。

完成したArduinoを変換コネクタをつかってSwitchに接続すれば勝手に動いてくれます。

#最後に
ライブラリを公開してくださっている方がいたおかげで随分と簡単に実装ができてしまいました。

あとは、画像認識と組み合わせて自動孵化厳選装置も作ってみたいですね。