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?

M5StickC Plus2で作る!DJIドローンのリモートID(Wi-Fi Beacon)レコーダー

Posted at

はじめに

  • M5StickC Plus2を使って、iPhoneでは確認しづらいDJIドローンのWi-Fi BeaconリモートIDを可視化・記録する装置を作った

背景

DJI製ドローンを飛ばしていたら、リモートIDが本当に発信されているのか気になった。
手持ちのiPhoneでは、以下の理由でリモートIDを見ることが出来なかった。

  • リモートIDは、Bluetooth 5.x、又はWi-Fi Aware、又はWi-Fi Beaconのどれかで発信する必要がある
    リモート ID 技術規格書
    抜粋

    2. RID 機器等の性能要件
    (1) リモート ID 信号(以下「RID 信号」という。)は、Bluetooth 5.x Long
    Range(以下「Bluetooth 5.x」という。)、Wi-Fi Neighbor Awareness
    Networking(以下「Wi-Fi Aware」という。)又は Wi-Fi Beacon の無線方
    式による直接放送方式(RID 機器等から発信された RID 信号を受信機能を
    有する端末が直接受信する通信方式)により発信されるものでなければ
    ならない。
    
  • DJIドローンはWi-Fi BeaconでリモートIDを発信しているとされている

    Device BT 4 BT 5 Wi-Fi Beacon Wi-Fi NAN Link Notes
    DJI Mavic 3 https://www.dji.com/cz/mavic-3 Range < 500 meters via smartphone
    DJI Mini 3 Pro https://www.dji.com/cz/mini-3-pro Range < 500 meters via smartphone
  • iPhoneアプリはOS制約の関係で、Wi-Fi Beaconを見ることが出来ないらしい
    OpenDroneID の opendroneid-core-c#ios
    抜粋(google翻訳)

    iOS向けDroneTagアプリケーションは、iOSでBluetooth 4 Legacy Advertising信号を受信できます。
    AppStoreからダウンロードできます。
    ソースコードはhttps://github.com/dronetag/drone-scannerで公開されており、iOSとAndroidの両方でビルドできます。
    
    iOS 用の別の受信機アプリケーションは、こちらでベータテストされています: https://testflight.apple.com/join/HA3EL4zw。
    
    Appleは現在、BT4レガシーアドバタイジング以外のドローンID信号送信方法を受信するための適切なAPIを公開していません。
    つまり、iOSの現在のバージョン(15まで)は、BT5 Long Range + Extended Advertising、Wi-Fi NaN、Wi-Fiビーコンの受信をサポートしていません。
    
  • 従って、iPhoneアプリでは、DJIのリモートIDを見ることが出来ない

そこで、手持ちのM5StickC Plus2を使ってDJIのリモートIDを見ようと思った。
ただし、作った後にOpenDroneIDのESP32実装の存在を知ったので、次回があればそちらを利用したい。

  • OpenDroneIDのESP32実装
    抜粋(google翻訳)
    ESP32送信機のサンプル コードには、ESP32 HW でドローン ID 信号を受信するためのコードも含まれています。
    

開発環境

  • Windows 11
    • バージョン 24H2 (OS ビルド 26100.2605)
  • Arduino IDEバージョン :2.3.6
    • 日付:2025-04-09T11:26:55.498Z
    • CLIバージョン:1.2.0
  • Arduinoライブラリ:
    • M5GFX 0.2.9
    • M5Unified 0.2.7
    • M5StickCPlus2 1.0.1
    • ArduinoJson 7.4.1
  • M5StickCPlus2

構成

アプリケーションは主に以下のコンポーネントから構成される。

  1. メインスケッチ (drone_remote_id.ino):
    • Wi-Fiスニッフィングの初期化とパケット処理コールバック (wifi_sniffer_packet_handler) の設定
    • ボタン入力処理、Wi-Fiチャンネル制御、定期的な画面更新
    • RemoteIDDataManagerM5CanvasTextDisplayController のインスタンス化と制御
    • RTCからの時刻取得とシステム時刻設定
  2. RemoteIDDataManagerクラス:
    • 受信したリモートIDデータをRID(機体識別子、通常はシリアルナンバー)ごとに整理・格納
    • データは時系列のリングバッファ (std::deque) で管理し、古いものから削除
    • ターゲットRIDのデータはより多く保持
    • 各種クエリ機能(最新データ取得、RSSI順ソート、JSON出力など)を提供
    • ArduinoJson ライブラリを利用してJSON文字列を生成
    • 複数タスクからのアクセスを考慮し、セマフォでデータ整合性を保護
  3. M5CanvasTextDisplayControllerクラス:
    • M5GFXの M5Canvas を利用したダブルバッファリングによる、ちらつきのない画面表示を実現
    • 文字単位のグリッドベースでのテキスト配置
    • Arduino Print クラスライクなインターフェースを提供し、print/println で簡単に描画可能
    • 画面回転や文字サイズ変更にも対応

PlantUMLクラス図

使い方

  1. Gitのdrone_remote_idにある以下の4つのファイルをダウンロードする
  2. Arduino IDEで ダウンロードしたdrone_remote_id.ino を開き、必要なライブラリがインストールされていることを確認する
  3. 次章「設定」の値を、必要に応じて変更する
  4. M5StickCPlus2をPCに接続し、適切なボードとシリアルポートを選択する
  5. スケッチをM5StickCPlus2に書き込む
  6. 起動すると、画面にヘッダ情報(チャンネル、検出RID数、空きヒープ)と、検出されたRIDの情報がRSSIの高い順に表示される
    ※ドローンは電源ONしただけでは、リモートIDを発信しないので、アーム状態にする必要がある
    ※ドローンの「アーム状態」とは、ドローンのモーターが回転して、飛行可能(プロペラが回る準備完了)状態になることである
    ※DJIドローンの場合、コンビネーション スティック コマンド(CSC)によって、モーターを始動すると、アーム状態になる様だ
    view01.jpg↑ RIDが検出されていない時、(S)サーチモード
    view04.jpg↑ RIDが一つ検出された時、(S)サーチモード
    view05.jpg↑ RIDが一つ検出された時、(L)ロックモード
    view06.jpg↑ GNSS(=GPS)が有効な時
    ※リモートIDを発信できるドローンを一台しか持っていないため、二台以上の動作が確認できていない
    • 各RIDエントリには、RID文字列(シリアル番号)、RSSI、チャンネル、登録記号、緯度経度、気圧高度、GPS高度、最終受信時刻などが表示される
      ※DJIのドローンが衛星を10個ぐらい認識してGNSSのアイコンがグリーンにならないと、緯度と経度は0が返る様だ
      ※気圧高度とGPS高度は受信した値をただ表示しているだけなので、正確な高度を出すには何かしらの補正が必要と思う
    • チャンネルは自動で1chから13chまでスキャンする。表示は Ch:XX(S) のように(S)canモードを示す
  7. ボタン操作:
    • ボタンA (M5.BtnA / 本体正面ボタン): JSON送信
      • 押すと、シリアルモニター経由でJSONデータをPCに送信する
        view07.png
      • 送信モードはスケッチ内の #define SEND_MODE_TOP_RSSI で切り替えられる
        • 1 (デフォルト): RSSIが最も高い1つのRIDの履歴データを送信
        • 0: スケッチ内の TARGET_REG_NO_FOR_JSON で指定された登録記号を持つRIDの履歴データを送信
    • ボタンB (M5.BtnB / 本体側面ボタン): チャンネル固定モード切り替え
      • 押すごとに、チャンネル固定モードの有効/無効がトグルする
      • 有効にすると、SEND_MODE_TOP_RSSI の設定に応じて、ターゲットとなるRIDが受信された最後のチャンネルに固定しようと試みる。表示は Ch:XX(L) のように(L)ockモードを示します。ターゲットが見つからない場合は Ch:Lock? と表示され、スキャンを継続する
    • ボタンC (M5.BtnPWR / 電源ボタン): リセット
      • 押すとM5StickCPlus2が再起動する
  8. シリアルモニターを開く (ボーレート 115200) と、デバッグログやJSONデータを確認できる

設定

初期状態では少しのデータしか記録しない。必要に応じて調整すること。
ただし、ヒープ領域不足でPanicになるかもしれない。

  1. 対象のリモートIDを指定する
    探すRIDのシリアル番号がわかっているなら以下のコード(drone_remote_id.ino の40行目あたり)で指定する
    RemoteIDDataManager dataManager(""); 
    
    以下の様に指定する
    RemoteIDDataManager dataManager("1581F00LB000C000000R"); 
    
  2. RIDのデータエントリ数を調整する
    指定されたRIDと、それ以外のRIDで、保持するデータエントリ数を以下のコード(RemoteIDDataManager.hの180行目あたり)で定義しているので調整する
    static const size_t TARGET_RID_MAX_DATA = 1200;
    static const size_t OTHER_RID_MAX_DATA = 10;
    
    ※ビーコンは1秒に一回以上発信される
  3. JSONデータの最大エントリ数を調整する
    Aボタンクリック時にJSONデータを作る最大エントリー数を、以下のコード(drone_remote_id.ino の39行目あたり)で定義しているので調整する
    const size_t MAX_ENTRIES_IN_JSON = 600;
    
    以下の様に変更する(私の環境では40で安定した)
    const size_t MAX_ENTRIES_IN_JSON = 40;
    
    ※私の環境では、50だとAボタン押すタイミングでメモリを使い果たしてPanicになったw
    ※40だとPanicにならなくなったが、40秒未満のデータしかJSONで送れない微妙。JSONデータを見直すか、バイナリデータへの変更を検討したい

おわりに

iPhoneアプリでWi-Fi Beaconを見ることが出来ない点には驚いた。
リモートIDは三種類(Bluetooth 5.x、Wi-Fi Aware、Wi-Fi Beacon)のいずれかで発信されるので、汎用的に使えるように作るのは大変そうだ。
作った後にOpenDroneIDのESP32実装の存在を知ったので、次回があればそちらを利用したい。
今後は、PCで受け取ったjsonデータからKMLファイルを作って、Google Earthなどで表示させてみたい。
でもデータ数を増やすとメモリが足りなくなるので、メモリの無駄を見直したい。

参考サイト

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?