12
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

M5ATOMをNintendo Switchコントローラー化して操作を自動化してみる

Posted at

はじめに

きっかけは以下のツイートの内容まんまですが、Nintendo Switchのコントローラー制御を自動化したくなりました。
自動化にあたり行った調査、自動化で使用したライブラリとその使い方を紹介していきます。

調査

「Switch 自動化」でググる

Arduinoが基本のよう。
けどArduinoが手元にない…
M5StackデバイスはいっぱいあるのでESP32でいける方法がほしい…

生成AIに聞いてみる

ChatGPT 3.5、Claude3 Haiku、Bingに、
「ESP32というマイコンを使ってNintendo Switchのコントローラーを作りたいです。どのようなライブラリを駆使すれば実現できますか。」
と聞いてみた。

結果、プロンプトが適当すぎるからでしょうがChatGPTとClaude3はESP32のBLEライブラリを提示してきて結構な低レイヤーから実装させようとしてきました。

ただBingはESP32向けのSwitchコントローラーライブラリを提示してくれて、そこで教えてくれたsorasen2020/SwitchControllerESP32がサンプルコード見た感じ一番シンプルだったのでこれを使ってみました。

実装

サンプルコードをそのままAtomS3に書き込んでみたらSwitchに認識されなくて、コード冒頭の#ifndefまわりを消したらいけました。

当初目的としてはA連打だけしたかったのでこれで実装完了。
簡単すぎる…
BingとSwitchControllerESP32の作者さんありがとう…

サンプルコードの#ifndefまわりを削除しただけのコードがこちら。

/*
Copyright (c) 2023 sorasen2020
released under the MIT license
https://opensource.org/licenses/mit-license.php
*/

#include "SwitchControllerESP32.h"
#include "Arduino.h"

void setup() {
  switchcontrolleresp32_init();
  USB.begin();
  switchcontrolleresp32_reset();
}

void loop() {
  pushButton(Button::A, 100, 1);
}

簡単にコントローラー操作メソッドを紹介

pushButton

void pushButton(Button button, int delay_after_pushing_msec, int loop_num)

ボタンを押すメソッドです。
buttonに後述するButton型を指定します。
ここでは方向ボタンは含まれません。

単にボタンを押すだけのケースでこのメソッドを使います。

delay_after_pushing_msecは押したあとの待ち時間のミリ秒、loop_numは繰り返し回数を指定します。

Button型の定義は下表です。
値を足し合わせることで同時押しになります。

ボタン 記述
Y Button::Y 0x0001
B Button::B 0x0002
A Button::A 0x0004
X Button::X 0x0008
L Button::L 0x0010
R Button::R 0x0020
ZL Button::ZL 0x0040
ZR Button::ZR 0x0080
- Button::MINUS 0x0100
+ Button::PLUS 0x0200
左スティック押し込み Button::LCLICK 0x0400
右スティック押し込み Button::RCLICK 0x0800
HOME Button::HOME 0x1000
キャプチャー Button::CAPTURE 0x2000

pushButton2

void pushButton2(Button button, int pushing_time_msec, int delay_after_pushing_msec, int loop_num)

pushButtonの引数に加え、ボタンを押し込んでいる時間のミリ秒となるpushing_time_msecが追加されたメソッドです。
ちなみにpushButtonでのデフォルトのボタン押し込み時間は40msecです。

pushHatButton

void pushHatButton(Hat button, int delay_after_pushing_msec, int loop_num)

pushButtonと同じようなメソッドですが、こちらは方向ボタンを操作するメソッドです。

Hat型の定義は下表です。

ボタン 記述
Hat::UP 0x00
上右同時 Hat::UP_RIGHT 0x01
Hat::RIGHT 0x02
右下同時 Hat::RIGHT_DOWN 0x03
Hat::DOWN 0x04
下左同時 Hat::DOWN_LEFT 0x05
Hat::LEFT 0x06
左上同時 Hat::LEFT_UP 0x07
ニュートラル Hat::CENTER 0x08

pushHatButtonContinuous

void pushHatButtonContinuous(Hat button, int pushing_time_msec)

方向ボタンを押し込んでいる時間のミリ秒をpushing_time_msecで指定します。
pushButton2とは異なりdelay_after_pushing_msecloop_numの引数は指定できません。

tiltJoystick

void tiltJoystick(int lx_per, int ly_per, int rx_per, int ry_per, int tilt_time_msec, int delay_after_tilt_msec)

lx_perly_perrx_perry_perは左右スティックそれぞれのX/Y軸値を-100~100の範囲で指定します。
tilt_time_msecはスティックを倒している時間のミリ秒、delay_after_tilt_msecはメソッド実行後の待ち時間のミリ秒です。

細かなスティック操作を行いたい場合にこのメソッドを使用します。

UseLStick / UseRStick

void UseLStick(LS Lstick, int tilt_time_msec, int delay_after_tilt_msec)
void UseRStick(RS Rstick, int tilt_time_msec, int delay_after_tilt_msec)

左スティック / 右スティックを特定の方向に完全に倒すメソッドです。
Lstick / Rstickは下表のLS / RS型を指定します(割当られている値がHat型と異なります)。
tilt_time_msecはスティックを倒している時間のミリ秒、delay_after_tilt_msecはメソッド実行後の待ち時間のミリ秒です。

スティック位置 記述
中央(ニュートラル) LS::LS_CENTER / RS::RS_CENTER 0x0000
LS::LS_UP / RS::RS_UP 0x0001
右上 LS::LS_UP_RIGHT / RS::RS_UP_RIGHT 0x0002
LS::LS_RIGHT / RS::RS_RIGHT 0x0003
右下 LS::LS_DOWN_RIGHT / RS::RS_DOWN_RIGHT 0x0004
LS::LS_DOWN / RS::RS_DOWN 0x0005
左下 LS::LS_DOWN_LEFT / RS::RS_DOWN_LEFT 0x0006
LS::LS_LEFT / RS::RS_LEFT 0x0007
左上 LS::LS_UP_LEFT / RS::RS_UP_LEFT 0x0008

TiltLeftStick

void TiltLeftStick(int direction_deg, double power, int holdtime, int delaytime)

左スティックをdirection_degで指定した角度へ倒します。
powerで傾き具合を0.0~1.0の間で指定できます。
holdtimeはスティックを倒している時間のミリ秒、delaytimeはメソッド実行後の待ち時間のミリ秒です。

なお右スティックバージョンのメソッド(TiltRightStickのようなメソッド)はありません。

おわりに

先達の方々による技術の積み重ねのおかげでめちゃくちゃあっさり自動化が実現できました。

なお今回やりたかったA連打のような操作はデバイスに書き込んですぐに実用できますが、複数操作のディレイタイム調整やスティック操作が絡んでくると微妙な試行錯誤が必要になってきます。
コードを書き換えるたびにデバイス書き込みもして…と繰り返すのはかなり億劫なので、opnizを使ってデバイス書き込み不要で処理をホットスワップする方法についても記事にしたいと思います。

12
6
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
12
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?