fumiLab

fumiが作ったもの、やったことについて書いていきます。

実際に飛ぶドローン名刺を作ってみた

English description below.

実装することで実際にドローンとして飛行できる,ドローン名刺を作ってみました.

長い間,バグっててあんまりきれいに飛ばなかったのですが息抜きに飛ぶように修正してみました. ESP32をコアとしており,6軸IMUのセンシングとモーターのPID制御します.スマホをプロポとするためにESP32上でWebサーバーを立て,Joystickを動かすとWebSocket通信で入力値をドローンに送信します.また,ドローンのRoll pitch yawの角度値や電圧といったテレメトリをスマホ側で見れるようにしています. イメージとしてはCrazyfileのようなフライトコントローラとフレーム兼用の基板を目指して作っています.リアルで私に会うことがあればお渡しします!

概要

実際に動いている様子は以下をご覧ください.

www.youtube.com

この名刺は部品を実装することで手のひらサイズの小型ドローンとして飛行させることができます。また、ダックスの首輪のLEDを実装しスマホのNFCアンテナ部を近づけるとLEDが点滅する機能があります。

ドローン名刺について

ESP32を搭載し、基板自体がドローンになります。以下の機能を持っています。

  • 6軸IMUとの通信と姿勢推定
  • PID制御による姿勢制御
  • ESP32自身がWi-Fiアクセスポイントとなり、スマホをコントローラーとしたWebSocket通信による機体操縦
  • 機体情報テレメトリ通信
  • PIDゲインやキャリブレーションが調整可能なWebUI
  • 角度制御飛行(Angle)

必要なもの

ドローン名刺基板 BOM表のパーツ 3Dプリンタ

ハードウェアの組み立て

以下のBOMと回路図を参考に実装してください。Kicadで設計しました.プロジェクトデータは名刺のため個人情報などがあり気になる方は個別に連絡してください. Githubで回路図とBOMを公開してます.

回路図

Item Qty Reference(s) Value Footprint 備考
1 1 C1 DNP Capacitor_SMD:C_0603_1608Metric
2 10 C2, C5, C7, C8, C9, C10, C11, C12, C13, C14 0.1u Capacitor_SMD:C_0603_1608Metric お好みで
3 3 C3, C4, C6 10u Capacitor_SMD:C_0603_1608Metric お好みで
4 1 D1 MBR0520 Diode_SMD:D_SOD-123 SS2040など
5 1 D2 blue LED_SMD:LED_0603_1608Metric お好みで
6 2 D3, D4 red LED_SMD:LED_0603_1608Metric お好みで
7 1 D5 green LED_SMD:LED_0603_1608Metric お好みで
8 4 D6, D7, D8, D9 1N4148W Diode_SMD:D_SOD-123 https://akizukidenshi.com/catalog/g/g107084/
9 1 FB1 FerriteBead Inductor_SMD:L_0603_1608Metric https://akizukidenshi.com/catalog/g/g104053/
10 1 J1 LIPO JST PH https://akizukidenshi.com/catalog/g/g112802/
11 1 J2 DNP Connector_PinSocket_1.27mm:PinSocket_1x03_P1.27mm_Vertical 拡張用
16 1 P1 USB_C_Plug_USB2.0 Connector_USB:USB_C_Receptacle_HCTL_HC-TYPE-C-16P-01A https://akizukidenshi.com/catalog/g/g114356/
17 1 Q1 AO3401A Package_TO_SOT_SMD:SOT-23 https://akizukidenshi.com/catalog/g/g114654/
18 3 Q2, Q3, Q4 MMBT3904 Package_TO_SOT_SMD:SOT-23 https://akizukidenshi.com/catalog/g/g105969/
19 4 Q5, Q6, Q7, Q8 AO3400A Package_TO_SOT_SMD:SOT-23 https://akizukidenshi.com/catalog/g/g114653/
20 2 R1, R2 2.2k Resistor_SMD:R_0603_1608Metric お好みで
21 15 R3, R4, R5, R6, R7, R8, R9, R11, R12, R14, R15, R21, R22, R26, R27 10k Resistor_SMD:R_0603_1608Metric お好みで
22 1 R10 5.1k Resistor_SMD:R_0603_1608Metric お好みで
23 9 R13, R16, R17, R18, R19, R20, R23, R24, R25 1k Resistor_SMD:R_0603_1608Metric お好みで
24 2 SW1, SW2 SKRPACE010 module:SKRPACE010 https://akizukidenshi.com/catalog/g/g106185/
25 1 U1 ADP3338AKCZ-3.3 Package_TO_SOT_SMD:SOT-223-3_TabPin2 https://akizukidenshi.com/catalog/g/g112635/
26 1 U2 ESP32-WROOM-32E RF_Module:ESP32-WROOM-32E https://akizukidenshi.com/catalog/g/g115675/
27 1 U3 MPU-6050 Sensor_Motion:InvenSense_QFN-24_4x4mm_P0.5mm https://www.mouser.jp/ProductDetail/TDK-InvenSense/MPU-6050?qs=u4fy%2FsgLU9O14B5JgyQFvg%3D%3D
28 1 U4 FT231XQ Package_DFN_QFN:QFN-20-1EP_4x4mm_P0.5mm_EP2.5x2.5mm https://www.digikey.jp/ja/products/detail/ftdi-future-technology-devices-international-ltd/FT231XQ-R/3029140

モーターホルダーの印刷

ドローンの脚兼モーターホルダーの印刷をします。GitHubにあるのでダウンロードしてください。筆者はBambuLab X1 carbonのBasic PLAで印刷していますが、精度によってはモーターが入らない場合があるのでその場合はstepファイルを編集してちょうどいい物に調整してください。なお、緩い場合は最悪テープで止めると良いです(自分も結局テープで止めてます)。

ソフトウェア

GitHubにソースコードを公開しています。Arduino CoreとESP32ライブラリを使用しています。

システムアーキテクチャ

システムアーキテクチャは以下の通りです.ドローン上ESP32にWebサーバーを立てて、そこにスマホのブラウザからアクセスすることでドローン制御用のコントローラーと調整用のWebUIがあります。 制御は500HzでIMU読み込み、姿勢推定計算、PID計算、モーター出力をしています。モーター制御は20khzです。ドローンの操縦を行うWebsocket通信は50Hzです。Webサーバー、Websocket周りはESPAsyncWebServer、AsyncWebSocketによるイベント駆動です。 ArduinoCoreによる実装で、Wi-FiやWebサーバー、Websocketなどは別コアで動いているので制御と通信周りは別コアによるDual Core構成になっています。

システムアーキテクチャ
操縦シーケンスは以下の通りです.
通信に関するシーケンス

プロペラ配置はX QuadでM0,M1がFrontとなっています.

書き込み

ArduinoとESP32ライブラリ、をインストールします。

  • ESPAsyncWebServer
  • AsyncTCP

BoardはESP32 Devkitに設定し書き込みます。

飛行方法

www.youtube.com

  1. ESP32が起動するとWiFi APが立ち上がる
    • SSID: ESP32-DRONE
    • パスワード: 12345678
  2. スマホで接続し、ブラウザで http://192.168.4.1/ を開く
  3. Web UIでテレメトリが送られていることを確認する。Websocket通信が確立されると素早い点滅(Failsafe状態)から蛍(通常状態)のようになります。
  4. SETTINGSでGYROのキャリブレーションを実行、その後にACCのキャリブレーションをします。機体を動かし正しく姿勢推定できていることを確認してください。
  5. 必要に応じてPIDゲインを調整します。
  6. 必要に応じて、MOTOR TESTでプロペラ番号が合っていることを確認してください。
  7. 横画面にし、ARMチェックボックスを入れると800ms後にARMします。Joystickで操縦してください。
    1. 機体に対して揚力がかなり大きいので飛び上がりに注意してください。
    2. Joystickをあげた瞬間にWIFIが切れ、テレメトリがとまり高速点滅を始める場合バッテリーの電圧が足りないかバッテリーが十分に電流を流せないものの可能性があります。(安全装置がついてるバッテリーは過電流でよく止まります)
  8. DISARMボタンもしくはARMチェックボックス外すと即時DISARMします。機体が80度以上傾くとクラッシュ検知となりDISARMします。

CONTROL

横画面でJoystickによる操縦ができます。縦画面だとテレメトリが見えます。ARM Requestのチェックボックスを入れることでARMします。ARMできない場合はFSにARMできない理由が書いてあります。 横画面にしたところ

SETTINGS

PIDゲインの調整とセンサのキャリブレーションができます。Applyを押して反映してください。良ければSAVEを押すと不揮発領域に書き込まれ、次回電源を入れた際に読み出されます。

MOTOR TEST

プロペラを外してください。回る場所が違う場合、kMotor0Pinなどをソースコードで調整してください。

飛行している様子

youtube.com

note:

現状姿勢推定はMahonyフィルタとしていますが、試験的にMadgwickフィルタも実装しています。動いているようですがどちらでもあまりパフォーマンスは変わりませんでした。 static const FilterMode kFilterMode = FILTER_MAHONY; をFILTER_MADGWICKにすることで変更できます。

制御ループは500Hzです.プロポ通信は50Hzになってます.

制御ループ

WebSocket メッセージ仕様について

Client → Drone

Type Format 用途 レート
C C,throttle,roll,pitch,yaw,arm 操縦入力 50 Hz
PID PID,ANGLE|RATE|YAW,kp,ki,kd PIDゲイン更新 任意
CFG CFG,KEY,VALUE 設定変更 任意
CAL CAL,LEVEL|GYRO キャリブレーション要求 任意
MTEST MTEST,idx,thr,dur_ms / MTEST,STOP モータテスト 任意
GET GET 設定同期要求 接続時
SAVE SAVE NVSへ保存 任意
K K 強制Disarm 任意

Drone → Client (JSON)

Type 主なフィールド 用途 レート
tel t, armed, roll, pitch, yaw, m0..m3, vbatt, loop_hz, fs, cmd_age テレメトリ 20 Hz
cfg PID/制限/オフセット一式 接続時の設定通知 接続時
ack op, tag, ok, msg コマンド応答 都度

ピン/ポート割当

機能 信号 GPIO / ポート 備考
I2C IMU SDA GPIO 21 400 kHz
I2C IMU SCL GPIO 22 addr 0x68
Motor M0 (FL) PWM GPIO 15 LEDC ch0
Motor M1 (FR) PWM GPIO 13 LEDC ch1
Motor M2 (RR) PWM GPIO 12 LEDC ch2
Motor M3 (RL) PWM GPIO 14 LEDC ch3
Web Server TCP :80 (HTTP / WS) ESPAsyncWebServer
Wi-Fi SoftAP 2.4GHz SSID ESP32-DRONE / IP 192.168.4.1
Debug UART0 USB 115200 bps

フェイルセーフ

トリガ 動作 備考
WebSocket切断 Disarm FS_WS_DISCONNECT
操縦コマンド未受信 > 300ms Disarm cmd_to で変更可能
機体傾き > 80° のとき Auto Disarm tilt_dis で変更可能
IMU異常 Disarm 姿勢推定値が不正な場合
Armラッチ後の再Arm抑止 キル状態保持 明示的にDisarm要求が必要

English

I made a Drone Business Card that can actually fly as a drone when its components are assembled.

It was buggy and didn't fly very well for a long time, but I fixed it up for a change of pace so it can fly now. It uses an ESP32 as its core, performing 6-axis IMU sensing and PID control for the motors. To use a smartphone as a transmitter, a web server is set up on the ESP32. When you move the joystick, the input values are sent to the drone via WebSocket communication. Additionally, telemetry data such as the drone's roll, pitch, and yaw angle values, as well as voltage, can be viewed on the smartphone. The concept aims for a PCB that doubles as a flight controller and frame, similar to the Crazyflie.

Overview

Please check out the video below to see it in action.

www.youtube.com

By assembling the components, this business card can be flown as a palm-sized miniature drone. Additionally, it has a feature where mounting a Dachshund collar LED will cause it to flash when a smartphone's NFC antenna is brought close to it.

About the Drone Business Card

Equipped with an ESP32, the PCB itself becomes the drone. It has the following features:

  • Communication with a 6-axis IMU and attitude estimation
  • Attitude control via PID control
  • The ESP32 itself acts as a Wi-Fi access point, enabling aircraft piloting via WebSocket communication using a smartphone as a controller
  • Aircraft telemetry communication
  • A Web UI for adjusting PID gains and calibration
  • Angle mode flight (Angle control)

What You Need

Drone Business Card PCB Parts from the BOM 3D Printer

Hardware Assembly

Please assemble it by referring to the BOM and schematic below. I designed it using KiCad. Since the project data is for a business card and contains personal information, please contact me directly if you are interested. The schematic and BOM are available on GitHub.

Schematic

Printing the Motor Holders

Print the motor holders, which also serve as the drone's legs. They are available on GitHub, so please download them. I printed them using Basic PLA on a Bambu Lab X1 Carbon, but depending on the printing precision, the motors might not fit. In that case, edit the step file to adjust it to the right size. If it's too loose, taping it as a last resort works well (I ended up securing mine with tape too).

Software

The source code is published on GitHub. It uses Arduino Core and the ESP32 library.

System Architecture

The system architecture is as follows. A web server is set up on the ESP32 aboard the drone, and by accessing it from a smartphone browser, you get a controller for operating the drone and a Web UI for adjustments. The control loop runs at 500Hz, handling IMU reading, attitude estimation calculations, PID calculations, and motor output. Motor control operates at 20kHz. WebSocket communication for piloting the drone runs at 50Hz. The web server and WebSocket components are event-driven, utilizing ESPAsyncWebServer and AsyncWebSocket. Built with Arduino Core, the Wi-Fi, web server, and WebSockets run on a separate core, creating a Dual Core configuration that isolates the control and communication processes.

System Architecture

The piloting sequence is as follows.

Communication Sequence

The propeller layout is an X Quad configuration, with M0 and M1 at the front.

Flashing

Install Arduino and the ESP32 library.

  • ESPAsyncWebServer
  • AsyncTCP

Set the board to ESP32 Devkit and flash it.

How to Fly

www.youtube.com

  1. Once the ESP32 boots up, the WiFi AP will start.
    • SSID: ESP32-DRONE
    • Password: 12345678
  2. Connect via smartphone and open http://192.168.4.1/ in your browser.
  3. Verify that telemetry is being sent on the Web UI. When the WebSocket communication is established, the LED will change from rapid flashing (Failsafe state) to glowing like a firefly (Normal state).
  4. In SETTINGS, perform the GYRO calibration, followed by the ACC calibration. Move the drone around to confirm that the attitude estimation is working correctly.
  5. Adjust the PID gains as needed.
  6. If necessary, use the MOTOR TEST to confirm that the propeller numbers are correct.
  7. Switch to landscape mode and check the ARM checkbox; it will ARM after 800ms. Pilot it using the Joystick.
    1. The lift is quite strong relative to the drone's weight, so be careful of it jumping up.
    2. If the Wi-Fi disconnects, telemetry stops, and rapid flashing begins the moment you raise the joystick, the battery voltage might be insufficient, or the battery cannot supply enough current. (Batteries with safety circuits often shut off due to overcurrent.)
  8. Pressing the DISARM button or unchecking the ARM checkbox will instantly DISARM the drone. If the drone tilts more than 80 degrees, it will detect a crash and DISARM automatically.

CONTROL

You can pilot it using the Joystick in landscape mode. In portrait mode, you can see the telemetry. Checking the ARM Request box will ARM the drone. If it fails to ARM, the reason will be displayed in the FS section. Landscape view

SETTINGS

You can adjust PID gains and calibrate the sensors. Press Apply to reflect the changes. If it looks good, press SAVE to write the settings to non-volatile memory, which will be loaded the next time it's powered on.

MOTOR TEST

Please remove the propellers. If the wrong motor spins, adjust kMotor0Pin, etc., in the source code.

Flight Footage

youtube.com

note:

Currently, the attitude estimation uses a Mahony filter, but I've also experimentally implemented a Madgwick filter. It seems to work, but the performance didn't change much with either. You can change it by setting static const FilterMode kFilterMode = FILTER_MAHONY; to FILTER_MADGWICK.

The control loop runs at 500Hz. Transmitter communication operates at 50Hz.

Control Loop

WebSocket Message Specifications

Client → Drone

Type Format Purpose Rate
C C,throttle,roll,pitch,yaw,arm Control Input 50 Hz
PID PID,ANGLE|RATE|YAW,kp,ki,kd PID Gain Update Any
CFG CFG,KEY,VALUE Configuration Change Any
CAL CAL,LEVEL|GYRO Calibration Request Any
MTEST MTEST,idx,thr,dur_ms / MTEST,STOP Motor Test Any
GET GET Settings Sync Request On Conn
SAVE SAVE Save to NVS Any
K K Force Disarm Any

Drone → Client (JSON)

Type Main Fields Purpose Rate
tel t, armed, roll, pitch, yaw, m0..m3, vbatt, loop_hz, fs, cmd_age Telemetry 20 Hz
cfg Full set of PID / Limits / Offsets Settings Notification on Conn On Conn
ack op, tag, ok, msg Command Response Each time

Pin/Port Assignments

Function Signal GPIO / Port Notes
I2C IMU SDA GPIO 21 400 kHz
I2C IMU SCL GPIO 22 addr 0x68
Motor M0 (FL) PWM GPIO 15 LEDC ch0
Motor M1 (FR) PWM GPIO 13 LEDC ch1
Motor M2 (RR) PWM GPIO 12 LEDC ch2
Motor M3 (RL) PWM GPIO 14 LEDC ch3
Web Server TCP :80 (HTTP / WS) ESPAsyncWebServer
Wi-Fi SoftAP 2.4GHz SSID ESP32-DRONE / IP 192.168.4.1
Debug UART0 USB 115200 bps

Failsafe

Trigger Action Notes
WebSocket Disconnect Disarm FS_WS_DISCONNECT
Control command not received > 300ms Disarm Configurable via cmd_to
Aircraft tilt > 80° Auto Disarm Configurable via tilt_dis
IMU Error Disarm When attitude estimation values are invalid
Prevent Re-Arming after Arm Latch Maintain Kill State Requires an explicit Disarm request