今回は、以前の記事「小さなAruduino互換ボードにゲームコントローラーをワイヤレスで接続!ミニUSBホストシールド2.0+SparkFun Pro Micro+Buletoothアダプタを使うやり方」の続きの記事となりますが、その記事で作成した小型のBuletoothボードを使って、RCタンクを製作してみたいと思います。

もともとミニUSBホストシールド2.0SparkFun Pro Microを応用する方法について色々調べた理由としては、小型のラジコン用回路として利用できるところに魅力を感じたからであり、最終的にはプラモデルのラジコン化に使ってみたいと考えたからでした。そこで、今回の記事ではその検証をさらに進め、実際に2個のモーターを制御する基礎回路と制御コードを作成するため、試作のRCタンクを製作してみたというわけです。

今回、ベース車両として選んだのは、タミヤ製「楽しい工作シリーズ No.211 アームクローラー工作セット」です。左右に履帯がついたアームがあり、多少の障害物ならどんどん乗り越えて走るので、ラジコン化したらかなり楽しそうです。また、上面が平らで回路やバッテリーなどの搭載がしやすいため、さらに応用・発展させることができるというメリットもあります。

では、早速製作していきましょう!

スポンサーリンク




目次

  1. 製作に必要なもの
  2. ミニUSBホストシールド2.0の加工
  3. アームクローラーの車体の組み立て
  4. 回路の組み立て
  5. 制御用スケッチのコーディング
  6. まとめ

1. 製作に必要なもの

まずは製作に必要なものをリストアップしてみたいと思います。主なパーツのほとんどはamazonで入手可能です。

SparkFun Pro Micro 3.3V/8MHz (32U4搭載)

SparkFun Pro Micro 3.3V/8MHz DEV-12587

Pro Microには5v版と3.3v版の2種類がありますが、ミニUSBホストシールド2.0で使用できるのは3.3v版のみですので注意してください。amazonで入手できる安価な製品の多くは5v版ですが、SparkFunの純正品には3.3v版のものがあります。

ミニUSBホストシールド2.0

GAOHOU ミニUSBホストシールド2.0ADK SLR開発ツール互換SPIインターフェイス

秋月電子通商 ロングピンソケット 1×42(42P)

必要な分だけポキポキ切り取って使用できるため、持っていると結構便利なのです。

Bluetooth USBアダプター

プリンストン Bluetooth USB アダプター Ver4.0+EDR/LE(省電力) PTM-UBT7X

Bluetooth USBアダプターは他のものでも代用できると思いますが、当方で動作を確認したのは上記の製品です。

Bluetooth ゲームコントローラー

FONLAM Switch対応 コントローラー 無線 ゲームパッド プロコン 背面ボタン Switch/Android/IOS/PC全対応 ゲームコントローラー 6轴ジャイロセンサー 連射 振動 高耐久ボタン 重力感応 キャプチャー機能 スイッチ対応 ワイヤレス/Bluetooth接続 pro controller タブレット適用 無線有線二モデル 反応速い マクロ対応 日本語説明書 (ブラック)

このゲームコントローラー以外にも、PS3、PS4のゲームコントローラー、あるいはその互換コントローラーを使うことができます。当方で動作を確認したのは上記の製品です。

ベース車両

タミヤ 楽しい工作シリーズ No.211 アームクローラー工作セット 70211

タミヤ 楽しい工作シリーズ No.97 ツインモーターギヤーボックス (70097)

その他

電子工作で最もよく使われるモータードライバーといえば「TA7291P」ではないでしょうか。4.5V〜20Vの電圧で最大2.0Aの出力を出せる性能があり、工作用のマブチモーターから少し大きめのモーターまで扱える性能があります。秋月電子通商で入手できなくなったので、今後は入手が難しくなるのかと思っていましたが、amazonではまだまだ入手可能なのようですね。

オーディオファン モータードライバ 東芝製チップ TA7291P
モーターを制御可能 正回転 逆回転 停止 制御解放 フルブリッジドライバ

KKHMF 5個 SY-170 ミニブレッドボード カラフルブレッドボード はんだ原型 テスト170タイポイント

今回、Arduinoの電源は、かさばるモバイルバッテリーではなく、降圧専用の電源レギュレータキット9v乾電池を利用することにしました。この降圧レギュレータは、秋月電子通商でたったの250円(税込)で入手可能で、Raspberry Pi Zeroにも使えることから、一つ持っているとかなり重宝します。なお、詳しい使い方は、こちらの記事「Raspberry Pi Zeroを乾電池や7.2Vバッテリーで起動させる2つの方法」で詳しく扱っています。

三端子レギュレータキット 5V ターミナル版(TB版)

またこれら以外に必要なものは以下の通りです。箇条書きにしてみました。

※上記のリンクはamazon、または秋月電子通商へのリンクとなっています。

2. ミニUSBホストシールド2.0の加工

まず、ミニUSBホストシールド2.0SparkFun Pro Microで使うには、ボードそのものの改造が必要になります。

下側が、その改造後のミニUSBホストシールド2.0ですが、このように両サイドにピンソケットを装着して、SparkFun Pro Microと抱き合わせて使用します。また、基盤の裏側にも加工が必要になります。

詳しくはこちらの「小さなAruduino互換ボードにゲームコントローラーをワイヤレスで接続!ミニUSBホストシールド2.0+SparkFun Pro Micro+Buletoothアダプタを使うやり方」で、改造方法を解説していますのでご覧ください。ゲームコントローラーをペアリングして使用する方法についても解説しています。

なお、上記の改造方法について扱った記事では装着していなかったのですが、今回は5v電源をmicroUSBソケットからではなく、ピンの「RAW」から取得するため、さらに2つピンソケットを増設している点にも注意してください。

3. アームクローラーの車体の組み立て

USBホストシールド2.0を改造して、ゲームコントローラーとペアリングするところまでの作業が完了したら、今度はアームクローラーの車体の組み立てを行います。

基本的に説明書通りに組み立てますが、ギヤボックスをツインモーターギヤボックスに変更する必要があります。ただし双方タミヤ製のため互換性があり、簡単に換装できるようになっています。詳しくは双方の説明書を参考にしてみてください。

また有線リモコンではなく、Bluetooth接続を利用したラジコンのため、モーターにはノイズキラーコンデンサの取り付けをお勧めします。コンデンサは、0.01μFのセラミックコンデンサ(103と表記されている)を使用しました。この種の工作ではよく使うコンデンサなので、秋月電子通商などで一袋買っておくと便利です。取り付けは上図のようにモーター1個あたり3つずつハンダ付けしました。

3. 回路の組み立て

ベース車体が完成したら、回路を組み立てます。回路はミニブレッドボードをベースにして下図のように組んでみました。

まず、2つのモータードライバー「TA7291P」を差し込んで必要な配線をジャンパーワイヤーで組んでください。当初1A以上出力できるモバイルバッテリーを使用して電源を一つにすることも検討したのですが、モーター側のパワーを確保するために5V以上の電圧を使用したかったので、電源はSparkFun Pro Micro用とモーター用とで分けてみました。

なお、今回の動力は小型の130モーター2個ですが、360モーターや540モーターなど、本格的なラジコン用のより大きなモーターの場合は、通常7.2vバッテリー等を使用することになると思いますが、そのような場合でも、この回路をそのまま使用することが可能です。

回路が組み終わったら、車体と合体させてみてください。ミニブレッドボードは裏面の両面テープを使用し、電池ボックスなどそれ以外のものは、別途用意したクッション両面テープを使用して貼り付けます。

ミニUSBホストシールド2.0SparkFun Pro Microを抱き合わせたBluetoothモジュール、及びSparkFun Pro Micro用降圧電源モジュールは、ミニブレッドボードの端などに貼り付けます。

これで車体が完成しました!

5. 制御用スケッチのコーディング

それでは、いよいよ制御用スケッチのコーディングです。ここでは詳しく扱いませんが、コードを組むには「SparkFun AVR Boards」と「USB_Host_Shield_2.0-master」という2つのライブラリが導入されている必要があります。前述の記事で詳しく解説していますので、ここではそれらの導入が済んでいることを前提に話を進めます。

またここでは、紹介したXbox互換コントローラーの使用を前提にコーディングしていきます。PS3、PS4のコントローラーを使用したい場合は、PS3、PS4用のサンプルコードを開いて、その上に必要な記述を追記してください。

想定する操作方法

今回操作に使用するのは、左右のアナログスティックのみで、その他のボタンは使用しません。両方を前に倒すと前進、後ろに倒すと後進、交互に倒すと超信地旋回するという操作法を採用します。

/*
 Example sketch for the Xbox One S Bluetooth library - developed by Kristian Sloth Lauszus
 For more information visit the Github repository: github.com/felis/USB_Host_Shield_2.0 or
 send me an e-mail:  lauszus@gmail.com
 */

#include <XBOXONESBT.h>
#include <usbhub.h>

// Satisfy the IDE, which needs to see the include statement in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>

USB Usb;
// USBHub Hub1(&Usb); // Some dongles have a hub inside
BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so

/* You can create the instance of the XBOXONESBT class in two ways */
// This will start an inquiry and then pair with the Xbox One S controller - you only have to do this once
// You will need to hold down the Sync and Xbox button at the same time, the Xbox One S controller will then start to blink rapidly indicating that it is in pairing mode
XBOXONESBT Xbox(&Btd, PAIR);

// After that you can simply create the instance like so and then press the Xbox button on the device
// XBOXONESBT Xbox(&Btd);

// デジタル出力設定
const int L_INT1 = 2;
const int L_INT2 = 3;
const int R_INT1 = 4;
const int R_INT2 = 5;

const float INPUT_RESO = 0.01012; // ≒ 255/(32678-7500);
float inputL, inputR;
int pwmL, pwmR;

void setup() {
  Serial.begin(115200);
#if !defined(__MIPSEL__)
  // ↓これをコメントアウトしないと、シリアル通信の接続待ちとなりBluetoothドングルが初期化されない。
  // while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
  if (Usb.Init() == -1) {
    Serial.print(F("\r\nOSC did not start"));
    while (1); //halt
  }
  Serial.print(F("\r\nXbox One S Bluetooth Library Started"));

  // ピンモードを出力に設定
  pinMode(L_INT1, OUTPUT);
  pinMode(L_INT2, OUTPUT);
  pinMode(R_INT1, OUTPUT);
  pinMode(R_INT2, OUTPUT);

  // PWM値の初期値を0に設定
  analogWrite(L_INT1, 0);
  analogWrite(L_INT2, 0);
  analogWrite(R_INT1, 0);
  analogWrite(R_INT2, 0);
}
void loop() {
  Usb.Task();

  if (Xbox.connected()) {
    if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500 || Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500 || Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500 || Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) {
      if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500) {
        Serial.print(F("LeftHatX: "));
        Serial.print(Xbox.getAnalogHat(LeftHatX));
        Serial.print("\t");
      }
      if (Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500) {
        Serial.print(F("RightHatX: "));
        Serial.print(Xbox.getAnalogHat(RightHatX));
        Serial.print("\t");
      }

      // 左側前進
      if (Xbox.getAnalogHat(LeftHatY) < -7500) {
        // Serial.print(Xbox.getAnalogHat(LeftHatY));
        Serial.println("左側前進");
        inputL = (Xbox.getAnalogHat(LeftHatY) * -1 - 7500) * INPUT_RESO;
        pwmL = (int)inputL;
        Serial.print(pwmL);
        analogWrite(L_INT1, pwmL);
        analogWrite(L_INT2, 0);

      // 左側後進
      } else if (Xbox.getAnalogHat(LeftHatY) > 7500) {
        // Serial.print(Xbox.getAnalogHat(LeftHatY));
        Serial.println("左側後進");
        inputL = (Xbox.getAnalogHat(LeftHatY) - 7500) * INPUT_RESO;
        pwmL = (int)inputL;
        Serial.print(pwmL);
        analogWrite(L_INT1, 0);
        analogWrite(L_INT2, pwmL);

      // 左側停止
      } else {
        analogWrite(L_INT1, 0);
        analogWrite(L_INT2, 0);
      }

      // 右側前進
      if (Xbox.getAnalogHat(RightHatY) < -7500) {
        // Serial.print(Xbox.getAnalogHat(RightHatY));
        Serial.println("右側前進");
        inputR = (Xbox.getAnalogHat(RightHatY) * -1 - 7500) * INPUT_RESO;
        pwmR = (int)inputR;
        Serial.print(pwmR);
        analogWrite(R_INT1, pwmR);
        analogWrite(R_INT2, 0);

      // 右側後進
      } else if (Xbox.getAnalogHat(RightHatY) > 7500) {
        // Serial.print(Xbox.getAnalogHat(RightHatY));
        Serial.println("右側後進");
        inputR = (Xbox.getAnalogHat(RightHatY) - 7500) * INPUT_RESO;
        pwmR = (int)inputR;
        Serial.print(pwmR);
        analogWrite(R_INT1, 0);
        analogWrite(R_INT2, pwmR);

      // 右側停止
      } else {
        analogWrite(R_INT1, 0);
        analogWrite(R_INT2, 0);
      }
      
      Serial.println();
      
    } else {
      analogWrite(L_INT1, 0);
      analogWrite(L_INT2, 0);
      analogWrite(R_INT1, 0);
      analogWrite(R_INT2, 0);
    }
  }
}

スケッチの解説

28〜32行目:
まずここで使用するデジタルピンを指定します。

34行目:
サンプルコードでは、他のボタンも全て入力値が「7500」以上の時に受け付けるようになっているので、それに倣って設定しますが、調べたところ、入力値の上限が「32678」であるため、入力値がその範囲内の時に、反応するようにします。モータードライバーに渡すPWM値は、0〜255までであるため、その分解能(1段階あたりの値)をここでセットします。コメントもに示してある通り、255 / (32678 – 7500)の近似値で「0.01012」と定義しました。

そもそも、PWM値は整数で渡す必要があり、小数点以下は後で切り捨てます。つまりこの値はざっくり「0.01」でよいということになります。入力値が「7500」以上の時に受け付けるようになっているというのは、つまりこのような理由だったのかと、後で気がつきました。

42行目:
USBケーブルを接続してコントローラーの値が取得できているかなど、シリアルモニターを使って値の取得をテストするような場合には、ここは“イキ”にしておきますが、本番用の書き込みの際には、必ずコメントアウトしておかないと、ここでシリアルポートの接続を待ち続けてしまい、USBポートが初期化されないため、ここはコメントアウトしておく必要があります

78行目〜、88行目〜、104行目〜、114行目〜
左右それぞれの前進後進の記述となります。それぞれ、入力値に応じて出力ピンに0〜255までの値を渡すようになっています

なお、上記は今回使用しないボタンの記述を一切消去してあります。消去してあるコードの部分はサンプルコードを参照してみてください。

6. まとめ

このミニUSBホストシールド2.0SparkFun Pro Microを使ったこのBluetoothモジュールはデジタルピンにまだまだ余裕があり、さらに多くのサーボモーター、LED、センサー類を搭載できます。コントローラー側にも空きボタンがあるため、様々なアイテムのラジコン化のベースとして使用できるかと思います。また小型であるため、当初の目論み通り、プラモデルへの組み込みも楽々できそうです。現在何を作るか思案中です!