Crazyflie Nano Quadcopterが日本で飛ばせないなら

Crazyflie Nano Quadcopterが日本で飛ばせないなら、飛ばせる物を作ればいいじゃないか…。チョット考えてみるから、真面目に考えて作ってみるに昇格させまして予備実験をして可能性を探っていきたいと思います。

SONY DSC

まずは、一番簡単なコントローラを使った無線操作が出来るかを検証してみます。何を使って実験するかですが、使い慣れたArdunioでBTのコントローラーを接続してみます。

■今回の構成はこちら
受信側:ArdunioMega(1280)+USB Host Shield 2.0 for Arduino
送信側:ワイヤレスコントローラ(DUALSHOCK 3)

USB Host Shield 2.0」は「USB Host Library for Arduinoのライブラリをがあるので簡単にできるはず。

▲PS3コントローラーの接続の流れ

1.)Bluetoothドングルのアドレス確認
スケッチ「PS3BT.ino」をアップロードしてドングルをセットした状態でシリアルモニタを表示表示されているBluetoothアドレスを控えておく
2.)コントローラーへのドングルアドレスの登録
スケッチ「PS3USB.ino」を以下のように修正してアップロード
//PS3USB PS3(&Usb); // This will just create the instance ← コメントアウト
PS3USB PS(&Usb,0x00,0x15,0x83,0x3D,0x0A,0x57); ← ここに表示されたBluetoothアドレスを設定
■正常に設定されるとこのような表示
PS3_Setup-Address
3.)ソフト側アドレス設定(ドングルアドレス登録)
Bluetoothアドレスをスケッチに設定
//PS3BT PS3(&Btd); // This will just create the instance ← コメントアウト
PS3BT PS3(&Btd,0x00,0x15,0x83,0x3D,0x0A,0x57); ← ここに表示されたBluetoothアドレスを設定
4.)PSボタンを押すことでコントローラーを接続
■接続終了画面
PS3_Connect

比較的簡単に接続できてしまいました。

あとは、Ardunioで受信されたコントローラー信号をMultiWiiに送信してあげる事で操縦が可能になります。
どのように送信するかですが、Arduino側からMultiWiiをコントロールするには制御信号としてUART/DSM/PPMの3種類の信号があります。(UART/DSMは同じポートを使用するため、実際は2種類の制御信号)UARTは他での利用(自律制御/ロギング)も考えられるので、今回はPPM信号を専用のポートに送信して制御ができるかを確認します。※:今回は接続確認に実機がないので「MultiWiiConf_2_0」を使って確認を行いました。(PPMで入力したのは確認が簡単(ポートが別)だったので)

PPM信号の概要はこのようになっている。
RC_Receiver_Timing_Diagram1

ようするに、バラバラの各チャンネル信号をシリアル形式で並べて1本のケーブルで送信する。サーボ角に関してはパルス長にて表す。 信号形式がわかった所で、PPM信号の発信ですが簡単に出力するならmicros()関数とか使えばいいのですが、色々と同時実行するとタイミングがずれそうなのでタイマー処理してあげたい所です。

しょうがないから自分で作ろうかと思って探してみたら、作っている人がいらっしゃいました。

ArduinoRCLib」をそのまま使うことにします。

検証用の接続イメージを書くと…。
クリップボード

■今回の接続構成はこちら
・MultiWii(今回はArdunioNanoのプログラムを入れ替え)
・ArdunioMega(1280)+USB Host Shield 2.0 for Arduino
・ワイヤレスコントローラ(DUALSHOCK 3)

■接続要件

  • Bluetooth接続にはライブラリ「USB Host Library for Arduino」を使用する。
  • PPM信号の生成にはライブラリ「ArduinoRCLib」を使用する。
  • コントローラーはワイヤレスコントローラ(DUALSHOCK 3) をArduinoへBluetooth接続
  • Ardunio→MultiWiiのへのコントロール信号送信はPPM信号を送信、CH数は最大制御CHの8CH
  • PPM信号受信の確認にはMultiWiiにUARTで接続したUART_Confで信号を確認

今回試したテストコード(ライブラリを使っているので統合部分のみ作成)

#include
#include
#include
#include

// PPM
#define CHANNELS 6
#define LED_PIN 13 // debug

USB Usb;

// PS3
boolean printTemperature = false;
boolean printAngle = false;
boolean changeThrottle = false;

// RC Control Mode(1-4)
// Mode 1 : Japanese Type
// Mode 2 : USA Type
#define RC_MODE 1
#define RC_DEBUG_MODE

// ROLL,PITCH,THROTTLE,YAW,AUX1,AUX2,AUX3,AUX4,8,9,10,11
#if (RC_MODE ==1)
  #define RC_CH1  2 // PITCH(ELEVATOR)
  #define RC_CH2  4 // YAW(RUDDER)
  #define RC_CH3  3 // THROTTLE
  #define RC_CH4  1 // ROLL(AILERON)
#elif (RC_MODE ==2)
  #define RC_CH1  3 // THROTTLE
  #define RC_CH2  4 // YAW(RUDDER)
  #define RC_CH3  2 // PITCH(ELEVATOR)
  #define RC_CH4  1 // ROLL(AILERON)
#elif (RC_MODE ==3)
  #define RC_CH1  2 // PITCH(ELEVATOR)
  #define RC_CH2  1 // ROLL(AILERON)
  #define RC_CH3  3 // THROTTLE
  #define RC_CH4  4 // YAW(RUDDER)
#elif (RC_MODE ==4)
  #define RC_CH1  3 // THROTTLE
  #define RC_CH2  1 // ROLL(AILERON)
  #define RC_CH3  2 // PITCH(ELEVATOR)
  #define RC_CH4  4 // YAW(RUDDER)
#endif

#define AUX1 5
#define AUX2 6
#define AUX3 7
#define AUX4 8

/* You can create the instance of the class in two ways */
//PS3USB PS3(&Usb); // This will just create the instance
//PS3USB PS3(&Usb,0x00,0x1B,0xDC,0x05,0xF8,0x71); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch

BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
/* You can create the instance of the class in two ways */
PS3BT PS3(&Btd,0x00,0x1B,0xDC,0x05,0xF8,0x71); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch

uint16_t g_input[CHANNELS];                   // Input buffer in microseconds
uint8_t  g_work[PPMOUT_WORK_SIZE(CHANNELS+1)*2];  // we need to have a work buffer for the PPMOut class
// PPMOut requires two buffers:
//     Input buffer containing input samples in microseconds
//     Work buffer of ((channels + 1) * 2) elements for internal calculations and frame buffering
// This setup removes any limit on the number of channels you want, and makes sure the library doesn't use more
// memory than it really needs, since the client code supplies the buffers.
rc::PPMOut g_PPMOut(CHANNELS, g_input, g_work, CHANNELS);

// initialize
void setup() {

  // initialize serial:
  Serial.begin(115200);

  // initialize PIN_MODE
  #if defined(LED_PIN)
    pinMode(LED_PIN, OUTPUT);
  #endif

  // USB initialize
  if (Usb.Init() == -1) {
    Serial.print(F("\r\nOSC did not start"));
    while(1); //halt
  }
  Serial.print(F("\r\nUSB_Host Bluetooth Library Started"));

  // Initialize timer1, this is required for all features that use Timer1
  // (PPMIn/PPMOut/ServoIn/ServoOut)
  rc::Timer1::init();

  // initialize PPMOut with some settings
  g_PPMOut.setPulseLength(448);   // pulse length in microseconds
  g_PPMOut.setPauseLength(10448); // length of pause after last channel in microseconds
  // note: this is also called the end of frame, or start of frame, and is usually around 10ms

  // start PPMOut, use pin 9 (pins 9 and 10 are preferred)
  g_PPMOut.start(12);
}
// main loop
void loop() {

  Usb.Task();

  if(PS3.PS3Connected) {
    // Nomalmode Control(4CH)
    if (!changeThrottle){
      g_input[RC_CH1-1] = map(PS3.getAnalogHat(LeftHatX), 0, 255, 1000, 2000);
      #if defined(RC_DEBUG_MODE)
        Serial.print(F("\r\nLeftHatX: "));
        Serial.print(g_input[RC_CH1-1]);
      #endif
      g_input[RC_CH3-1] = map(PS3.getAnalogHat(RightHatX), 0, 255, 1000, 2000);
      #if defined(RC_DEBUG_MODE)
        Serial.print(F("\tRightHatX: "));
        Serial.print(g_input[RC_CH3-1]);
      #endif
    }
    g_input[RC_CH2-1] = map(PS3.getAnalogHat(LeftHatY), 0, 255, 1000, 2000);
    #if defined(RC_DEBUG_MODE)
      Serial.print(F("\tLeftHatY: "));
      Serial.print(g_input[RC_CH2-1]);
    #endif
    g_input[RC_CH4-1] = map(PS3.getAnalogHat(RightHatY), 0, 255, 1000, 2000);
    #if defined(RC_DEBUG_MODE)
      Serial.print(F("\tRightHatY: "));
      Serial.print(g_input[RC_CH4-1]);
    #endif
  }
//  // update the input buffer
//  for (uint8_t i = 0;  i < CHANNELS; ++i){
//    // fill input buffer, convert raw values to microseconds
//    g_input[i] = random(1000,2000);
//  }
//
  // tell PPMOut there are new values available in the input buffer
  g_PPMOut.update();

  if ((millis() % 1000) == 0){
    digitalWrite(LED_PIN,!digitalRead(LED_PIN));
  }
}

これが出来れば、普通に手動で飛行させるだけなら可能です。その場合にはArdunioMegaとかどう考えてもオーバースペックですけれど…。 PCからの制御信号で自立飛行とか、単体での自立飛行とかしない限り宝の持ち腐れ。最近流行りのオープンソースにして大人数で可能性を探ったほうがいいような気がします。

Megaはオーバスペックだと思うので、ここは最近ようやくブートローダーが出来上がって来ました1284Pあたりを使いましてコントロールしてみたいと思います。 次回は、ライブラリ対応していないようなので変更が必要&シールドからではうまく信号を拾えなかったのでテスト回路から作って検証してみます。

■参考情報
How to hack the PPM signal from any receiver (Futaba) with Arduino – DIY Drones

■「USB Host Shield 2.0 for Arduinoのドングル対応状況」

  • ■対応
    iBUFFALO Bluetooth USBアダプター 3.0+EDR対応 class2 ブラック BSHSBD04BK
    PLANEX Bluetooth Ver3.0+EDR Microサイズ USBアダプタ (Class2/10m) BT-Micro3E2XZ
    PLANEX Bluetooth Ver.4.0+EDR/LE対応 USBアダプタ (省エネ設計) BT-MICRO4
  • ■未対応
    PLANEX Bluetooth ver2.1+EDR Microサイズ USBアダプタ (Class2/10m) BTMICROEDR2XZ
  1. コメントはまだありません。

  1. トラックバックはまだありません。

 
%d人のブロガーが「いいね」をつけました。