えいあーるれいの技術日記

ROS2やM5 Stack、Ubuntuについて書いています

ATOMS3でゲームパッドを作る (M5ATOM)

ATOMS3が昨年末に発売されました。

私は、スイッチサイエンスでの販売開始直後に購入しました。

ATOMS3 — スイッチサイエンス


ATOM S3は、M5Stack atomシリーズの派生で、MCUにESP32-S3を使用しています。

また、ATOM-Matrixと異なりATOM-S3には120x120ディスプレイやUSBデバイス機能なども搭載されています。

M5Stackにも似た機能はありますが、バッテリーがなく小型なのは(管理的に)助かります。

Announcing ESP32-S3 for AIoT Applications | Espressif Systems


USBを差すと、Wi-FiスキャンやBluetooth、IMUなどのテストを試せます。素晴らしい。


ゲームパッドを作ろう🎮

3ヶ月後にこの記事が上がるということは、はい、そういうことです。

私はこれまでこのATOMS3を早期で購入しておきながら積みマイコンしていました…


とりあえず何か1つでも作っておきたいと思ったので、IMUで動かせる有線のゲームパッドを作ることにしました。

ロール軸が左ジョイスティックのx軸、ピッチ軸がy軸に対応して、ボタンは将来的にモード切り替えなどに使えればいいかなと

これまでUSBデバイスは作ったことはなかったので、とりあえず体験として動かしてみることにしました。


環境

環境は、旧Arduino IDEを使用しました。

いつもはVSCode上のPlatformIOをよく使っていますが、今回はM5Stackのチュートリアルに従ってインストールを進めました。

docs.m5stack.com

Arduinoにはシリアルプロッタがあるので助かります。

IMU

ATOMS3には6軸IMUのMPU6886が搭載されているので、これを用いて roll,pitchを取得します。

以下はRollPitchを求めるプログラムです。(最終的にシリアル通信は消してしまうので、通信部分はなんとなくで書いています🙏)

#include "M5AtomS3.h"
#include <math.h>

float ax, ay, az, gx, gy, gz, t;


void calculateRollPitch(float& roll, float& pitch) {
    M5.IMU.getAccel(&ax, &ay, &az);
    M5.IMU.getGyro(&gx, &gy, &gz);

    roll = atan2(ay, az) * 180.0 / M_PI;
    pitch = atan2(-ax, sqrt(ay * ay + az * az)) * 180.0 / M_PI;

    float dt = 0.01;
    static float roll_prev = 0, pitch_prev = 0;
    roll += (gx / 131.0) * dt;
    pitch += (gy / 131.0) * dt;

    roll = roll * 0.98 + roll_prev * 0.02;
    pitch = pitch * 0.98 + pitch_prev * 0.02;
    roll_prev = roll;
    pitch_prev = pitch;
}


void setup() {
    M5.begin(true, true, true, false);
    USBSerial.begin(115200);
    M5.IMU.begin();
    M5.Lcd.printf("TEST");
}


void loop() {
    float roll, pitch;
    calculateRollPitch(roll, pitch);
    USBSerial.println("%f, %f", roll, pitch);

    M5.Lcd.fillScreen(BLACK);
    draw_ball(64 + roll, 64 - pitch, 10, RED);
    delay(10);
}


ちゃんと角度算出できていました。


ゲームパッド

次のプログラムを参考にプログラムを作成しました。このライブラリは、AtomS3の依存関係に含まれていたので、追加でパッケージを追加することなく使えました。

arduino-esp32/Gamepad.ino at master · espressif/arduino-esp32 · GitHub


最終的に次のようなプログラムになりました。

gist.github.com

ボタン機能も追加したかったのですが、今回は動かず…

他の使い方を模索したいと思います。

(あと、ATOMS3のボタンはディスプレイを直接押下するので、壊しそうで怖いですね)


書き込むと、ジョイパッドとして認識されます。

Ubuntu/Ubuntuでジョイスティックを使用する方法 - Linuxと過ごす を読んで動作確認しました。

sudo apt install -y joystick  jstest-gtk

jstest-gtk

jstest-gtkで認識していました。

https://user-images.githubusercontent.com/67567093/222894514-f5d6b3ea-ce22-48e1-b97a-69e6a064aaf3.png


Turtlesimで動かしてみる。

ジョイスティックとして振る舞っているので、これまでのROSパッケージのジョイスティックを置き換えることもできます。

PlayStationのデータをTwistに変換するプログラム(HarvestX/PlayStation-JoyInterface-ROS2)を使用しました。 teleop.launch.py において hw_type:=DualShock4topic_name:=/turtle1/cmd_velの引数が必要です。

github.com


1000円でゲームパッドを買うこともできますが、マイコンを使ってコントローラを作るだけでもいい体験になりそうな気がしますね。

楽しい。