0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DJI Mavic3を自律飛行させる方法|外付センサ編2

0
Last updated at Posted at 2026-01-14

IMG_2338.jpeg

前回からの続き。

  • 機体の姿勢を把握するジャイロセンサは6軸だと正確な値は取得できず不十分で磁気も取れる9軸にする必要がある(磁気データで正確な角度に補正できる)
  • 空間の中の位置も把握したいので前後左右上下の距離が図れるセンサも導入する必要がある

ということで、改めてセンサーの選定からやり直し

距離センサ:シングルポイントLiDAR TSD10

Screenshot 2026-01-14 at 23.23.52.png
https://akizukidenshi.com/catalog/g/g131303/
LiDARセンサーというとレーザーポインタがぐるぐる回っていて360度周囲の距離が図れるものしか知らなかったけど、360度ではなく1点、センサが向いてる方向の距離を測るシングルポイントLiDARというものを秋月で見つける。

■主な仕様

  • 電源電圧min.:4.5V
  • 電源電圧max.:5.5V
  • 測定距離min.:0.05m
  • 測定距離max.:10m
  • 測定方式:赤外線ToF
  • 測定項目:距離
  • インターフェイス:UART
  • 動作温度min.:-20℃
  • 動作温度max.:60℃

20m、50m図れるモデルもあるが、展示をするBUGのギャラリースペースは高さが7.5m、幅が7m、インスタレーションとして使う空間の奥行きは11mほどなので、このTSD10というモデルを機体3方向(例えば下、後ろ、右)に向くように取り付ければ、空間の中でどの辺にいるか大体の位置が測定できそうなのでこれを採用。(仕様見ると分かる通りLiDARもToF = Time of Flight方式の一種だと知る。)

ジャイロ:BNO055使用 9軸センサーフュージョンモジュールキット

Screenshot 2026-01-14 at 23.39.20.png
https://akizukidenshi.com/catalog/g/g113010/
秋月にはもう一種類9軸ジャイロセンサーあったけど、販売終了していてもう一方のものを選択。

■主な仕様
・電源電圧min.:3.3V
・電源電圧max.:5V
・加速度チャンネル:3
・測定加速度min.:±2g
・測定加速度max.:±16g
・測定角速度min.:±125dps
・測定角速度max.:±2000dps
・測定磁束密度max.:±2500μT
・測定項目:加速度・ジャイロ・磁気
・インターフェイス:I2C

マイコン:Seeed Studio XIAO ESP32S3

Screenshot 2026-01-14 at 23.49.03.png
https://akizukidenshi.com/catalog/g/g118078/
それまで使ってた手持ちのXIAO ESP32C3だとパフォーマンス的に怪しいのと、UARTインターフェイスが使える数の問題があり、S3はハイパフォーマンスでデフォルトでUARTインターフェイスが3つ使えてシングルポイントLiDAR TSD10 ×3つの扱いが楽そうだったのでこちらも購入。

リチウムポリマー 3.7V → モバイルバッテリ 5V

XIAOやその他、小型のマイコンをスタンドアロンで使う際、軽量小型の3.7Vのリチウムポリマー電池使うのが定番でそうしてたけど

  • ↓ TSD10の動作電圧が4.5〜5.5Vで電圧足らない
  • ↓ 昇圧基板の導入検討
  • ↓ 秋月が年末年始でクローズ
  • ↓ 制作を進めたいのでAmazonで適当な5V昇圧基板を購入
  • ↓ 届いて試してみるも、全くうまくいかず5V取得できず
  • ↓ しばらく格闘するも原因分からずネットにリファレンスも見つからず

てことで、ここに2日以上費やしたのち諦めてストロベリー・リナックスで良さそうな昇圧基板注文しつつ、やはり先に進めたいので普通のモバイルバッテリに移行。
意外と小容量でコンパクトなものがなくてMavic3の上面になんとかフィットしそうな以下をチョイス。

https://amzn.asia/d/dpf9EBC

LiDAR TSD10 のボーレートは [460800]

Screenshot 2026-01-15 at 0.18.05.png
一番最初のポストREADMEにも書いたけど、このボーレートの正しい設定のところでどハマリした。
ChatGPT、Gemini、Claudeの3者は必ず最初は「これ系のセンサのボーレートは115200」と言い張り、テストコード生成させて試してみても、プログラム書き込みはできるけど一向に正しい値が出力されず。LLM側もボーレートが不正確なことを疑っていて、センサの仕様書のPDFを共有したのに正解にはたどり着かず、結局自分でマニュアルに書いてある「baurate: 460800」を発見。2日消費して無事動作テスト成功。LLMは一次情報を信じず、正誤判断できず、多く流布している情報のほうを盲信してしまう(とLLM自身も自覚している)。まるでネトウヨのようである

このセンサを3方向むけて機体に固定するためのハウジングをモデリング

Screenshot 2026-01-15 at 0.26.38.png

  • 機体下の床からすこし浮いたスペースに収まるサイズで設計
  • センサがズレて動かないようにピッタリはまる形状をデザイン
  • コードを取り回す溝と結束バンドを通す穴を付ける

これをプリントして
IMG_2345.jpeg

機体に固定
IMG_2405.jpeg

9軸センサを追加して最終動作確認

LLMにセンサの仕様を渡して、ここまでのTSD10 ×3個のプログラムに統合する形で9軸ジャイロセンサの値を取得してWi-Fi経由で計6つの値をUDPでPCに送るプログラムを生成してもらう

XIAOs3_MavicSensors_wifi.ino
#include <WiFi.h>
#include <WiFiUdp.h>
#include <OSCMessage.h>
#include <HardwareSerial.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>

// Wi-Fi / OSC設定
const char* ssid = "Buffalo-G-8188";
const char* password = "pc4pakte375mr";
const char* udpAddress = "192.168.11.5";
const int udpPort = 8888;
WiFiUDP Udp;

// --- LiDAR 設定 (元のピンアサインを完全に維持) ---
HardwareSerial LidarSerial1(1);
HardwareSerial LidarSerial2(2);
HardwareSerial LidarSerial3(0);

// LiDAR 1のピン (D7, D6)
#define LIDAR1_RX_PIN 44
#define LIDAR1_TX_PIN 43
// LiDAR 2のピン (D9, D8)
#define LIDAR2_RX_PIN 8
#define LIDAR2_TX_PIN 7
// LiDAR 3のピン (D1, D0)
#define LIDAR3_RX_PIN 2
#define LIDAR3_TX_PIN 1

uint8_t rxBuffer1[4], rxBuffer2[4], rxBuffer3[4];
int bufferIndex1 = 0, bufferIndex2 = 0, bufferIndex3 = 0;
uint16_t distance1 = 0, distance2 = 0, distance3 = 0;

// --- BNO055 設定 ---
// アドレス0x28, Wireを使用
Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x28, &Wire);

unsigned long lastSendTime = 0;
const unsigned long sendInterval = 33;  // 約30Hz

void setup() {
  Serial.begin(115200);
  delay(2000);
  Serial.println("=== TSD10 x3 + BNO055 System ===");

  // LiDAR 1-3 初期化 (ご自身で解決された460800bpsに設定)
  LidarSerial1.begin(460800, SERIAL_8N1, LIDAR1_RX_PIN, LIDAR1_TX_PIN);
  delay(100);
  LidarSerial2.begin(460800, SERIAL_8N1, LIDAR2_RX_PIN, LIDAR2_TX_PIN);
  delay(100);
  LidarSerial3.begin(460800, SERIAL_8N1, LIDAR3_RX_PIN, LIDAR3_TX_PIN);
  delay(100);

  // I2C初期化 (XIAO D4=SDA/GPIO5, D5=SCL/GPIO6)
  Wire.begin(5, 6);

  // BNO055の開始
  if (!bno.begin()) {
    Serial.println("BNO055 not detected. Check wiring or I2C ADDR.");
  } else {
    Serial.println("BNO055 Initialized!");
    // 外部クリスタルを使用(安定性向上のため)
    bno.setExtCrystalUse(true);
  }

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi!");
}

void loop() {
  // LiDAR 1 データ読み取り
  while (LidarSerial1.available()) {
    uint8_t byte = LidarSerial1.read();
    if (bufferIndex1 == 0 && byte != 0x5C) continue;
    rxBuffer1[bufferIndex1++] = byte;
    if (bufferIndex1 >= 4) {
      distance1 = rxBuffer1[1] + (rxBuffer1[2] << 8);
      bufferIndex1 = 0;
    }
  }

  // LiDAR 2 データ読み取り
  while (LidarSerial2.available()) {
    uint8_t byte = LidarSerial2.read();
    if (bufferIndex2 == 0 && byte != 0x5C) continue;
    rxBuffer2[bufferIndex2++] = byte;
    if (bufferIndex2 >= 4) {
      distance2 = rxBuffer2[1] + (rxBuffer2[2] << 8);
      bufferIndex2 = 0;
    }
  }

  // LiDAR 3 データ読み取り
  while (LidarSerial3.available()) {
    uint8_t byte = LidarSerial3.read();
    if (bufferIndex3 == 0 && byte != 0x5C) continue;
    rxBuffer3[bufferIndex3++] = byte;
    if (bufferIndex3 >= 4) {
      distance3 = rxBuffer3[1] + (rxBuffer3[2] << 8);
      bufferIndex3 = 0;
    }
  }

  // 一定間隔でOSC送信
  unsigned long currentTime = millis();
  if (currentTime - lastSendTime >= sendInterval) {
    // BNO055からオイラー角(角度)を取得
    sensors_event_t event;
    bno.getEvent(&event);

    OSCMessage msg("/xiao/sensor");
    // LiDARの距離
    msg.add((int32_t)distance1);
    msg.add((int32_t)distance2);
    msg.add((int32_t)distance3);
    // BNO055の角度 (Heading, Roll, Pitch)
    msg.add((float)event.orientation.x);  // 方位角
    msg.add((float)event.orientation.y);  // ピッチ
    msg.add((float)event.orientation.z);  // ロール

    Udp.beginPacket(udpAddress, udpPort);
    msg.send(Udp);
    Udp.endPacket();
    msg.empty();

    // デバッグ表示
    Serial.printf("D: %d, %d, %d | Ang: %.1f, %.1f, %.1f\n",
                  distance1, distance2, distance3,
                  event.orientation.x, event.orientation.y, event.orientation.z);

    lastSendTime = currentTime;
  }
}

2、3回修正入れてすんなり問題なく動くプログラム生成してもらえた。
MaxのUDPrecieveオブジェクトでセンサからの6つの値を無事表示成功。
基板とバッテリ、センサを結束バンドで、機体のセンサに干渉しないように固定。

IMG_2407.jpeg

しかし、これを実際飛ばしてみるとかなり致命的なレベルで値がシームレスに流れてこず頻繁にフリーズしてしまう。
ドローンの映像伝送プロトコルがO3+(OcuSync 3+)というかなり信号強度がある規格のようで、それにうちのへぼいWi-Fiが負けてる?てかそもそもグローバルなインターネットについないでいたので、それも原因か。あとXIAOにアンテナも付いてない。
ので

  • 使ってない適当なWi-Fiルーター使ってローカルネットワークを構築
  • XIAOにアンテナ付ける

をやってみたところ問題ない速度でのWi-Fi通信成功。

次の課題

  • 実際の展示空間ぐらい天高ある広めの場所でも同じ構成で問題なく通信できるかテスト
  • センサの入力値をもとにプロポを自律的に操作するプログラムをつくりこむ
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?