生活を豊かにできる、電子工作やプログラミングの知識を発信していく

【ESP32で電子工作-7】Full-Nchモータードライバアンプの作成(2)【PS4-esp32】

無線操縦可能なラジコン用モータドライバを自作しました。

この記事は<JLCPCB>様の提供で執筆しています。

また、本記事を読む前に前回の記事「【ESP32で電子工作-6】Full-Nchモータードライバアンプの作成(1)【PS4コントローラ】」を読んでいただければと思います。

 

操縦するロボットの紹介

テオヤンセン機構で駆動する6脚ロボットを自作しました。このロボットを無線操縦するためのモータドライバを作成しました。

実際の動きは動画でどうぞ!!


幾何学的な構造で動物みたいな動きをするテオヤンセンはとてもかわいい!

動画では、Futaba製ラジコン用モータドライバラジコン用プロポで駆動させています。

このロボットの制御対象であるモーターはタミヤ380モータ×2個を搭載しています。


タミヤギヤードモータ AO-8025 380K300

今回、1枚の制御基板で2系統のモーターをそれぞれ制御できるようにしていきます。

前回の記事で回路設計、基板設計、基板の発注までを終わらしました。
【ESP32で電子工作-6】Full-Nchモータードライバアンプの作成(1)【PS4コントローラ】

今回は発注した基板の開封、はんだ付け、プログラムの作成をしていきます!!

発注基板の開封とはんだ付け

今回発注した基板は5枚、価格は25ドル(送料別)、1枚5ドルぐらいでした。
今回は銅箔厚みを2倍の2ozにしているので普段より少し高めですね。
配達業者にDHLを選択することで1週間程度で自宅に配達されました(早い!!!)。

到着した基板の開封

発注した基板が到着したので早速開封していきます!

開封するときれいにパッキングされているので、パッキングをはがしていきます

じゃじゃーんと出てきました!!
これらが今回作成した基板になっています。
シルクもばっちりで想定通りの完成度です。

さっそく部品をはんだ付けしていきたいと思います!!

部品のはんだ付け

ということで、いそいそと部品のはんだ付けをしていきました。

先日の記事にも書きましたがAD変換素子を購入し忘れたので、一部部品のついていないところもありますがご愛嬌()

ここで私が愛用している「はんだごて」を紹介させていただきます。
HAKKOの「ダイヤル式温度制御はんだこて FX600-02

温度調節ができて最大500℃までの温度が扱える!!

4000円弱という値段で、コストパフォーマンスがめちゃくちゃいい!!

こて先の種類が豊富!!

という超絶、有能君です。私は鉛フリーはんだで370℃に設定して使用しています。

ESP32でPS4コントローラ(DualShock4)を使用してロボットを動かすためのプログラム作成

当初の目標である、PS4コントローラでモータドライバ回路を制御して、ロボットを駆動させるプログラムの作成を行います。
PS4コントローラー(DualShock4)と通信するために便利なライブラリ「PS4-esp32」が作られているのでそちらを利用させていただきました。
プログラムのコンパイルなどはArduinoIDEを使用しています。

プログラムの作成

今回、作成したプログラムはこのようになっています。

#include <ps4.h>
#include <PS4Controller.h>
#include <ps4_int.h>
#define SD1 27  //left
#define SD2 14  //right
#define IN11 18
#define IN12 19
#define IN21 25
#define IN22 26

int speedmode = 0;
int speed1 = 255;
int speed2 = 200;
int flag = 0;

void forward(int pwm1, int pwm2) {
  ledcWrite(0, pwm1);
  ledcWrite(1, pwm2);
  digitalWrite(IN11, HIGH);   // LEDをオン
  digitalWrite(IN12, LOW);   // LEDをオン
  digitalWrite(IN21, HIGH);   // LEDをオン
  digitalWrite(IN22, LOW);   // LEDをオン
}
void back(int pwm1, int pwm2) {
  ledcWrite(0, pwm1);
  ledcWrite(1, pwm2);
  digitalWrite(IN11, LOW);   // LEDをオン
  digitalWrite(IN12, HIGH);   // LEDをオン
  digitalWrite(IN21, LOW);   // LEDをオン
  digitalWrite(IN22, HIGH);   // LEDをオン
}
void turn_left(int pwm1, int pwm2) {
  ledcWrite(0, pwm1);
  ledcWrite(1, pwm2);
  digitalWrite(IN11, LOW);   // LEDをオン
  digitalWrite(IN12, HIGH);   // LEDをオン
  digitalWrite(IN21, HIGH);   // LEDをオン
  digitalWrite(IN22, LOW);   // LEDをオン
}
void turn_right(int pwm1, int pwm2) {
  ledcWrite(0, pwm1);
  ledcWrite(1, pwm2);
  digitalWrite(IN11, HIGH);   // LEDをオン
  digitalWrite(IN12, LOW);   // LEDをオン
  digitalWrite(IN21, LOW);   // LEDをオン
  digitalWrite(IN22, HIGH);   // LEDをオン
}
void stop() {
  ledcWrite(0, 0);
  ledcWrite(1, 0);
  digitalWrite(IN11, LOW);   // LEDをオン
  digitalWrite(IN12, LOW);   // LEDをオン
  digitalWrite(IN21, LOW);   // LEDをオン
  digitalWrite(IN22, LOW);   // LEDをオン
}


void setup() {
  Serial.begin(115200);
  PS4.begin("AC:67:B2:5B:AB:96");
  ledcSetup(0, 12800, 8);
  ledcSetup(1, 12800, 8);
  ledcAttachPin(SD1, 0);
  ledcAttachPin(SD2, 1);
  pinMode(IN11, OUTPUT);
  pinMode(IN12, OUTPUT);
  pinMode(IN21, OUTPUT);
  pinMode(IN22, OUTPUT);
  digitalWrite(IN11, HIGH);   // LEDをオン
  digitalWrite(IN12, HIGH);   // LEDをオン
  digitalWrite(IN21, HIGH);   // LEDをオン
  digitalWrite(IN22, HIGH);   // LEDをオン
  while (!PS4.isConnected()) {} // 接続されるまで待機

  delay(1000);
  digitalWrite(IN11, LOW);   // LEDをオン
  digitalWrite(IN12, LOW);   // LEDをオン
  digitalWrite(IN21, LOW);   // LEDをオン
  digitalWrite(IN22, LOW);   // LEDをオン

}

void loop() {
  //  if (PS4.isConnected()) {
  if (PS4.Touchpad() == 1) {
    if (flag == 0) {
      flag = 1;
      if (speedmode == 0) {
        speedmode = 1;
        speed1 = 200;
        speed2 = 170;
      } else {
        speedmode = 0;
        speed1 = 255;
        speed2 = 200;
      }
    }
  }
  if (PS4.Touchpad() == 0) {
    flag = 0;
  }
  if (PS4.Right()) {
    turn_right(speed1, speed1);
  }
  else if (PS4.Down()) {
    back(speed1, speed1);
  }
  else if (PS4.Up()) {
    forward(speed1, speed1);
  }
  else if (PS4.Left()) {
    turn_left(speed1, speed1);
  }
  else if (PS4.UpRight()) {
    forward(speed1, speed2);
  }
  else if (PS4.DownRight()) {
    back(speed1, speed2);
  }
  else if (PS4.UpLeft()) {
    forward(speed2, speed1);
  }
  else if (PS4.DownLeft()) {
    back(speed2, speed1);
  } else {
    stop();
  }

  delay(1);
}

※クリックするとプログラムの全文が見れます

前進、後退、カーブなどに対応した関数を作成しmain()でコントローラの押されたボタンに対応して信号を出力するようにしています。
速度の調整はPWMで行っています。

PS4.begin("AC:67:B2:5B:AB:96");

と書いてある箇所のMACアドレスの取得方法については下に書いています。

各自、異なったMACアドレスとなりますので、そこで得られたMACアドレスに変更してください

プログラム自体は単純なものになっているのですが、PS4コントローラ(DualShock4)をESP32で使用するためのライブラリ「PS4-esp32」を使用するのに苦労したので解説していきます。

PS4-esp32ライブラリの使い方

PS4-esp32ライブラリを使用するためにこちらのgithubリンクよりライブラリをダウンロードします。

ダウンロードしたライブラリをArduinoIDEのライブラリマネージャから読み込むことで使用可能となります。

実際にプログラムで使用するときは「ps4.h」・「PS4Contoroller.h」・「ps4_int.h」をそれぞれincludeしてください。
その状態でコンパイルして、無事にコンパイルが通ったらOKです。

私の環境では「esp_err_t esp_bt_gap_set_scan_mode(esp_bt_scan_mode_t mode); 」というエラーが発生してコンパイルができませんでした。

そのため、このエラーが発生したときの対応をしていきます。

PS4-esp32ライブラリでのエラー対応

先述したesp_err_t esp_bt_gap_set_scan_mode(esp_bt_scan_mode_t mode); に対して私が解決した方法を記します。

何をやったかというとエラー発生部をコメントアウトして発生させなくしたというだけです。

インストールしたライブラリから「ps4_spp.c」というファイルを編集していきます。

※私の場合ArduinoIDEで読み込んだファイルはC:\Users\user-name\Downloads\PS4-esp32-master\PS4-esp32-master\srcに保管されていました。

ファイルの中の86から88行目、90行目をコメントアウトすることコンパイルが通るようになりました。
実際には以下のようにファイルを編集しています。

#if CONFIG_IDF_COMPATIBILITY >= IDF_COMPATIBILITY_MASTER_D9CE0BB
    esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_NON_DISCOVERABLE);
#elif CONFIG_IDF_COMPATIBILITY >= IDF_COMPATIBILITY_MASTER_21AF1D7
    esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE);
#endif

こちらのプログラムを

//#if CONFIG_IDF_COMPATIBILITY >= IDF_COMPATIBILITY_MASTER_D9CE0BB
//    esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_NON_DISCOVERABLE);
//#elif CONFIG_IDF_COMPATIBILITY >= IDF_COMPATIBILITY_MASTER_21AF1D7
    esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE);
//#endif

という感じで変更しています。

ESP32とPS4コントローラ(DualShock4)の接続

PS4コントローラ(DualShock4)はそのままではESP32とペアリングしません。

ペアリングさせるためにコントローラに設定されているターゲットのMACアドレスを変更する必要があります。

本来の接続先はPS4本体に登録されているBluetooth用MACアドレスが登録されているのですが、このアドレスをESP32のBluetooth用MACアドレスを調査し、ソフトを使用してそのアドレスに変更します。

ESP32のMACアドレスを調べる

ESP32のマックアドレスを調べるためのMACアドレスを調査するためのプログラムを作成しました。

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

void loop() {
  
}

このプログラムをESP32に書き込むことで、ESP32のMACアドレスがシリアルコンソールに表示されます。

ちなみに私が使用しているESP32で得られたMACアドレスは「AC:67:B2:5B:AB:96」になりました。

得られたMACアドレスをPS4コントローラに書き込むので、忘れないようにメモをしておいてください。

PS4コントローラ(DualShock4)のターゲットMACアドレスを変更

PS4の認識先のBluetooth用マックアドレスを変更していきます。

変更するために「sixaxispairtool 」というソフトを使用しますのでダウンロード・インストールをしてください。

PS4コントローラをパソコンに接続した状態でソフトを起動してください。

正常にコントローラが認識されていると以下のようになります。

current mastarのところに現在の接続先MACアドレスが表示されます。

※認識に失敗していると「No device found」という表示になってしまいます。その場合はソフトおよびパソコンの再起動、再インストールなどを試してみてください。

正常に認識したらchenge mastarのところに先ほど調べたMACアドレスを入力してupdateを押してください。
私の場合ですと「AC:67:B2:5B:AB:96」を入力しました。

これでMACアドレスの変更ができましたので、ESP32で使用できるはずです。

ちなみにPS4に再接続するときは、PS4とコントローラをUSBケーブルで接続し、コントローラのPSマークを押すこと使用可能となります。
この時コントローラ内部のターゲットアドレスは変更されているので、ESP32とまた接続するときは上記の作業をもう一度行ってください。

これで、プログラムの作成、コントローラの設定が完了したので実際にロボットを動かしていきます。

ロボットを実際に動かしてみる

さっそく作成した基板をロボットに搭載しました。

自分で設計した基板なので、きれいにロボットに収めることができました。

実際に動かしている動画がこちらになります。

きちんとPS4コントローラでロボットが操縦できていますね(ご満悦)

今回の記事のまとめ

このようにモータドライバを自作することで、ほかのロボットやラジコンも動かすことができる汎用的な駆動回路を作成することができるようになりました。

ps4の無線コントローラプログラムを応用することでロボットだけでなくマイコンにプログラムを書くだけでいろんな制御に使えます。

なんでも動かせるようになれば作品の幅が広がりますね

今回の記事は以上となります。
それでは、良き電子工作ライフを!!
See You …

  • B!