はじめに

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

自作したロボットは、テオヤンセン機構で駆動する6脚ロボットです。幾何学的な構造により、まるで生き物のような滑らかな動きをします。

実際の動きは動画でご確認ください。

これをPS4コントローラで無線操縦するために、ESP32を使ってモータドライバ回路を作成しました。


モータードライバの回路設計と構成

モーターに単純に電気を流すだけでは、正転・逆転の制御はできません。
Hブリッジ回路を使って、電流の方向を自在に切り替えられるようにすることで、モーター制御を実現します。

Hブリッジ回路の電流経路

Hブリッジ回路の電流経路

②番や③番のようにスイッチ入力を入れ替えることでモーターに入力する電流方向が変わります。
そんな理屈でモータの正転・逆転が切り替わります。

これらの動作をマイコン制御によって切り替えることができるような基板を設計していきます。

ドライバの構成:Full-Nch構成

モータードライバ基板はいろんな種類に分類することができます。

PN混合モータドライバ

  • Pch-FETとNch-FETを組み合わせて設計するモータドライバ回路
  • Pch-FETはNch-FETと比較して性能が低いため、性能を上げようとすると値段が高くなりがち。
  • けど、回路設計自体は簡単

Full-Nchモータドライバ

  • NchFETのみで構成されたモータドライバ回路
  • 性能の高いNch-FETのみを使用して回路を構成できる
  • FET間の性能を考慮する必要がない
  • けど、ハイサイド側のFETに対して昇圧回路を組み込む必要があり、複雑な回路構成になってしまう

今回はNch-FETのみを使ったFull-Nch構成のドライバを採用しました。
これは昇圧回路が必要で設計はやや複雑になりますが、FET間の特性差を考えずに済み、部品選定の自由度が高くなります。

使用部品(抜粋)

今回使用した部品はこちらのようになっています。すべては紹介しきれないので主な部品を抜粋させていただきます。

型番 備考
ESP32 無線操縦用のマイコン
2SK2232 Nch-FET。入手性が良く高性能
IR2104 HBドライバ。秋月電子で購入

一応電気特性とかは考えつつ、お手軽に入手できるもので部品選定をしていきました。
今回、1枚の制御基板で2系統のモーターをそれぞれ制御できるようにしていきます。
ほかの部品については以下の回路図を見ていただければと思います。

モータードライバ回路図

モータードライバ回路図


プリント基板設計と製造

Kicadを使って回路図を基板化し、JLCPCBに発注しました。
今回はモータ駆動用の基板であるため、より多く電流が流れてもいいように以下のように基板の設計をしています。

  • 銅箔厚みは通常の1ozではなく、2ozに設定
  • モーター駆動用ラインは2mmの太配線に設定

これにより、理論上4Aまでの電流に耐える設計になっています。

モータードライバ基板配線図

モータードライバ基板配線図


基板の到着とはんだ付け

届いた基板を開封!

開封直後の基板

開封直後の基板

開封直後の基板

開封直後の基板

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

そして想定通りのクオリティでシルクも美しいです

部品のはんだ付けを完了すると画像のようになりました。

部品実装済みの基板

部品実装済みの基板


プログラム作成:PS4コントローラで制御

今回の目的はPS4コントローラ(DualShock4)でモータドライバ回路を制御して無線操縦すること
Arduino IDEとPS4-esp32ライブラリを使用し、ESP32とBluetooth接続します。

クリックでコードを表示

▼ プログラムを見る
#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);   
  digitalWrite(IN12, HIGH);   
  digitalWrite(IN21, HIGH);   
  digitalWrite(IN22, HIGH);   
  while (!PS4.isConnected()) {} // 接続されるまで待機

  delay(1000);
  digitalWrite(IN11, LOW);   
  digitalWrite(IN12, LOW);   
  digitalWrite(IN21, LOW);   
  digitalWrite(IN22, LOW);   

}

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リンクよりライブラリをダウンロードします。

PS4-esp32 ライブラリ(GitHub)

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

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

私の環境ではesp_bt_gap_set_scan_mode()でエラーが出ましたが、該当部分をコメントアウトして回避しました。
インストールしたライブラリから「ps4_spp.c」というファイルを編集していきます。
ファイルの中の86から88行目、90行目をコメントアウトすることコンパイルが通るようになりました。
実際には以下のようにファイルを編集しています。

//#if CONFIG_IDF_COMPATIBILITY ...
//esp_bt_gap_set_scan_mode(...);
//#endif

ESP32とペアリングする方法

PS4コントローラ(DualShock4)はそのままではESP32とペアリングしません。
ペアリングさせるためにコントローラに設定されているターゲットのMACアドレスを変更する必要があります。

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

  1. ESP32のBluetooth MACアドレスを調べる
void setup() {
  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コントローラに書き込むので、忘れないようにメモをしておいてください。

  1. sixaxispairtoolでPS4コントローラの接続先をESP32に変更

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

sixaxispairtool ダウンロードページ

PS4コントローラをパソコンに接続した状態でソフトを起動してください。
正常にコントローラが認識されていると以下のようになります。

sixaxis画面

sixaxis画面

current masterのところに現在の接続先MACアドレスが表示されます。   ※認識に失敗していると「No device found」という表示になってしまいます。その場合はソフトおよびパソコンの再起動、再インストールなどを試してみてください。

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

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

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

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


動作確認

作成した基板をロボットに搭載してみました。 ピッタリサイズでとてもカッコイイですね!

モータードライバ搭載ロボット

モータードライバ搭載ロボット

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

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

きちんとPS4コントローラからロボットを無線操縦できました!(ご満悦)

まとめ

今回のように自作モータドライバとPS4コントローラを組み合わせることで、
多様なロボットやラジコンの操縦ができるようになりました。

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

ESP32の無線機能とArduino環境の柔軟性を活かせば、制御の幅は無限大!

それでは、良き電子工作ライフを!!
See You!!