Help us understand the problem. What is going on with this article?

ESP32(M5StickC)をPS3コントローラで操作してみたくない?

もともとBLEコントローラでESP32を操作したい!ということでNimBLEを使ってたのですが、

NimBLEでESP32(M5StickC)にBLE HIDデバイスを接続する(追記:複数デバイス対応) - Qiita
https://qiita.com/coppercele/items/4ce0e8858a92410c81e3

BLEコントローラが売ってなくて再現性がないということで心が折れたのでPS3コントローラでESP32を操作してみることにします

こんな感じで操作できます

こちらのサイトを参考にさせていただきました

・ESP32 (M5StickC) で PS3 の コントローラ を使う : (Blog)SKYZOO(ヨッシーの備忘録(プチ情報))
http://gijin77.blog.jp/archives/21966552.html

ハードウェア

M5StickC
image.png

M5StickC - スイッチサイエンス
https://www.switch-science.com/catalog/5517/
Arduino互換なESP32がケースに入っててボタンとディスプレイとバッテリーと赤外線LEDがついててWifiとBluetoothも使える欲張りセット


PS3コントローラー

image.png

純正品のいわゆるDUAL SHOCK3
ハードオフにて1,000円前後で売ってるのでコスパが良い
ただ手垢汚れをきれいにするのがめんどくさい

Bluetoothアドレスの登録

PS3コントローラをペアリングするためにはコントローラにEPS32のBluetoothアドレスを書き込まないといけません

ESP32に以下のスケッチを書き込み実行します

void setup(void) {
  Serial.begin(115200);
  uint8_t btmac[6];
  esp_read_mac(btmac, ESP_MAC_BT);
  Serial.printf("[Bluetooth] Mac Address = %02X:%02X:%02X:%02X:%02X:%02X\r\n", btmac[0], btmac[1], btmac[2], btmac[3], btmac[4], btmac[5]);
}

void loop() {
}

このスケッチを実行するとシリアルモニタにアドレスが表示されるのでメモしておきます

こちらから書き込みソフトをダウンロードします

Download SixaxisPairTool by Dancing Pixel Studios
https://sixaxispairtool.software.informer.com/download/

PS3コントローラをPCに接続し、ソフトをインストールして実行するとこのような画面が表示されますので先ほどメモしたアドレスを入力してUpdateボタンを押すと書き込みが完了します

image.png

ライブラリのインストール

Arduino IDEのライブラリマネージャでPS3を検索すると出てきますのでインストールしましょう

image.png

スケッチ例 > PS3 Controller Host > Ps3Demo
image.png

のBluetoothアドレス部分をESP32の物に変更して実行し、PS3コントローラのPSボタンを押すと接続できます

Ps3.begin("01:02:03:04:05:06"); ←この部分

接続できたらPS3コントローラのボタンを押すと結果がシリアルモニタに表示されます

RoverCを操作してみた

せっかくなのでRoverCを操作してみることにします

こちらでRoverCの制御は確立していたのでこちらを組み合わせます

自分流メカナムホイール(RoverC)制御法 - Qiita
https://qiita.com/coppercele/items/1596b7b9904eb4403191

loop()内で左右スティックの値を取得してRoverCの操作をしています

本当はNotifyで操作したかったんですがなぜかうまくいかなかったので誰か検証してみてください(´・ω・`)

#include <M5StickC.h>
#include <Ps3Controller.h>

int8_t speed_sendbuff[4] = { 0 };

int8_t FORWARD[4] = { 50, 50, 50, 50 };
int8_t LEFT[4] = { -50, 50, 50, -50 };
int8_t BACKWARD[4] = { -50, -50, -50, -50 };
int8_t RIGHT[4] = { 50, -50, -50, 50 };
int8_t ROTATE_R[4] = { 30, -30, 30, -30 };
int8_t ROTATE_L[4] = { -30, 30, -30, 30 };

float f, b, l, r, rr, rl = 0.0;

void onConnect() {
    Serial.println("Connected!.");
    digitalWrite(GPIO_NUM_10, LOW);
}
void onDisconnect() {
    Serial.println("Disconnected!.");
    digitalWrite(GPIO_NUM_10, HIGH);
}

void SetChargingCurrent(uint8_t CurrentLevel) {
    Wire1.beginTransmission(0x34);
    Wire1.write(0x33);
    Wire1.write(0xC0 | (CurrentLevel & 0x0f));
    Wire1.endTransmission();
}

int8_t I2CWrite1Byte(uint8_t Addr, uint8_t Data) {
    Wire.beginTransmission(0x38);
    Wire.write(Addr);
    Wire.write(Data);
    return Wire.endTransmission();
}

uint8_t I2CWritebuff(uint8_t Addr, uint8_t *Data, uint16_t Length) {
    Wire.beginTransmission(0x38);
    Wire.write(Addr);
    for (int i = 0; i < Length; i++) {
        Wire.write(Data[i]);
    }
    return Wire.endTransmission();
}

uint8_t setspeed() {  // 前後左右回転それぞれを係数と掛けて足す
    for (int i = 0; i < 4; i++) {
        speed_sendbuff[i] = FORWARD[i] * f;
        speed_sendbuff[i] += BACKWARD[i] * b;
        speed_sendbuff[i] += RIGHT[i] * r;
        speed_sendbuff[i] += LEFT[i] * l;
        speed_sendbuff[i] += ROTATE_L[i] * rl;
        speed_sendbuff[i] += ROTATE_R[i] * rr;
    }
    float limit = 0.0;
    for (int i = 0; i < 4; i++) {
        // speedが100を超えないようにリミッターをかける
        limit = 100.0 / max(abs(speed_sendbuff[3]), max(abs(speed_sendbuff[2]), max(abs(speed_sendbuff[1]), abs(speed_sendbuff[0]))));
    }
    //    printf("limit = %f\n", limit);
    if (limit < 1.0) {
        for (int i = 0; i < 4; i++) {
            speed_sendbuff[i] = speed_sendbuff[i] * limit;
        }
    }

    return I2CWritebuff(0x00, (uint8_t*) speed_sendbuff, 4);
}

void setup() {
    Serial.begin(115200);

    M5.begin();
    M5.update();
    Wire.begin(0, 26, 10000);
    SetChargingCurrent(2);
    M5.Axp.ScreenBreath(7);
    M5.Lcd.fillScreen(BLACK);
    pinMode(GPIO_NUM_10, OUTPUT);
    digitalWrite(GPIO_NUM_10, HIGH);

//    Ps3.attach(notify);
    Ps3.attachOnConnect(onConnect);
    Ps3.attachOnDisconnect(onDisconnect);
    Ps3.begin("D8:A0:1D:52:9C:C2");
    Serial.println("Ready.");
}

void loop() {
    M5.update();
    if (M5.BtnB.wasReleased()) {
        esp_restart();
    }

    if (M5.BtnA.wasReleased()) {
        M5.Axp.PowerOff();
    }

    if (Ps3.isConnected()) {
        if (Ps3.data.analog.stick.ly < -10) {
            Serial.print("Moved the left stick:");
            Serial.printf(" ly=%d\n", Ps3.data.analog.stick.ly);
            f = (abs(Ps3.data.analog.stick.ly) / 128.0);
            b = 0.0;
        }
        else if (10 < Ps3.data.analog.stick.ly) {
            Serial.print("Moved the left stick:");
            Serial.printf(" ly=%d\n", Ps3.data.analog.stick.ly);
            b = (abs(Ps3.data.analog.stick.ly) / 128.0);
            f = 0.0;
        }
        else {
            Serial.printf(" ly=%d", Ps3.data.analog.stick.ly);
            Serial.printf(" left V neutral\n");
            b = 0.0;
            f = 0.0;
        }
        if (Ps3.data.analog.stick.lx < -10) {
            Serial.print("Moved the left stick:");
            Serial.printf(" lx=%d", Ps3.data.analog.stick.lx);
            l = (abs(Ps3.data.analog.stick.lx) / 128.0);
            r = 0.0;
        }
        else if (10 < Ps3.data.analog.stick.lx) {
            Serial.print("Moved the left stick:");
            Serial.printf(" lx=%d", Ps3.data.analog.stick.lx);
            r = (abs(Ps3.data.analog.stick.lx) / 128.0);
            l = 0.0;
        }
        else {
            Serial.printf("lx=%d", Ps3.data.analog.stick.lx);
            Serial.printf(" left H neutral\n");
            r = 0.0;
            l = 0.0;
        }
        if (Ps3.data.analog.stick.rx < -10) {
            Serial.print("Moved the right stick:");
            Serial.printf(" rx=%d", Ps3.data.analog.stick.rx);
            rl = (abs(Ps3.data.analog.stick.rx) / 128.0);
            rr = 0.0;
        }
        else if (10 < Ps3.data.analog.stick.rx) {
            Serial.print("Moved the right stick:");
            Serial.printf(" rx=%d", Ps3.data.analog.stick.rx);
            rr = (abs(Ps3.data.analog.stick.rx) / 128.0);
            rl = 0.0;
        }
        else {
            Serial.printf("rx=%d", Ps3.data.analog.stick.rx);
            Serial.printf(" right H neutral\n");
            rr = 0.0;
            rl = 0.0;
        }
        setspeed();
    }
    delay(1);
}

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした