いよいよ面白くなりTelloを飛ばすことはできましたが、本来の機能であるカメラ画像の送信が生かされていない( ;∀;)
まだお持ちでない方、2台目希望の方 プログラミングドローン ”Tello” の購入はこちらドローンのプログラミングでどうやって画像をPCに送信したらいいだろう? YouTubeをたまたまみていたTechの部屋に出会いました。しかし私はプログラミング初心者でしかもTechの部屋のPCはMAC かなり勉強になりましたが、私はPCはWindowsでしたので、参考にして我流でしてみました。オープンソースはGitHub Tech の部屋「Pythonで小型ドローン Tello EDU を飛ばす!」サンプルプログラムからダウンロードできます。
まずOpenCvのダウンロードからです。


OpenCV(正式名称: Open Source Computer Vision Library)とは、オープンソースのコンピューター・ビジョン・ライブラリです。コンピューターで画像や動画を処理するのに必要な、さまざま機能が実装されており、BSDライセンスで配布されていることから学術用途だけでなく商用目的でも利用できます。加えて、マルチプラットフォーム対応されているため、幅広い場面で利用されていることが特徴です。
画像処理 (Image Processing)構造解析 (Structural Analysis)モーション解析と物体追跡 (Motion Analysis and Object Tracking)物体検出 (Object Detection)などが可能です。


リリースのウインドウズをクリックしダウンロードします。ダウンロードしたら展開してopencvのフォルダーをCドライブの直下に置きます。OPENCVのファイルの中のbild→x64→vc15→binを開きこのアドレスをコピーし、コントロールパネルから
システム&セキュリティのシステム環境変数に追加するため、Pathに先ほどコピーしたアドレスを追加します。
pythonでopencvを使いたいので opencv-pythonをpipを使用してインストールできます。
インストールする場合は以下のコマンドを使用します。
pip install opencv-python

コマンドプロンプトからですがアプリの右クリックで管理者として実行で起動させます。
オープンソースはGitHub Tech の部屋「Pythonで小型ドローン Tello EDU を飛ばす!」サンプルプログラムからダウンロードしたファイル cli.py(先のTello3.pyと同じプログラム) & vc.py(画像送信プログラム)
OpenCVが使われている箇所を強調してみました。
#vc.pyの内容は以下の通りです。
Tello Python3 Control Demo
http://www.ryzerobotics.com/
1/1/2018
Modified by MPS
#
import threading
import socket
import time
import cv2 ⇒ ここでOpenCVがインポートされている
host = ”
port = 9000
locaddr = (host, port)
Create a UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
tello_address = (‘192.168.10.1’, 8889)
sock.bind(locaddr)
def recv():
while True:
try:
data, server = sock.recvfrom(1518)
print(data.decode(encoding=”utf-8″))
except Exception:
print(‘\nExit . . . RECV\n’)
break
print(‘\r\n\r\nTello Python3 Demo.\r\n’)
print(‘Tello: command takeoff land flip forward back left right \r\n up down cw ccw speed speed?\r\n’)
print(‘end — quit demo.\r\n’)
recvThread create
recvThread = threading.Thread(target=recv)
recvThread.start()
sock.sendto(b’command’, tello_address)
print(‘command ok’)
time.sleep(0.5)
sock.sendto(b’streamon’, tello_address)
print(‘stream on’)
time.sleep(1)
sock.close()
cap = cv2.VideoCapture(“udp://%s:%s?overrun_nonfatal=1&fifo_size=50000000” % (‘192.168.10.1’, ‘11111’)) ⇒ #ここでビデをキャプチャーでTelloのカメラから画像受信
print(‘start cap’)
while True:
try:
ret, frame = cap.read()
if ret:
cv2.imshow(‘tello’, cv2.resize(frame, (360, 240))) #受信画像を画面表示
cv2.waitKey(1)
except KeyboardInterrupt:
cv2.destroyAllWindows()
cap.release()
print(‘\nExit . . .\n’)
break
をデスクトップでも貼り付けます。
あとは 各ファイルを実行できるようにコマンドプロンプトを2つ起動させます。
それでは、準備が整いましたので 2つのプログラムを同時に実行させてみます。動画をとってますので御覧ください。
次にOpenCvによる顔認識の仕方こちらへどうぞ!!





マッキーの趣味のドローン YouTube channel
-
保護中: RobotDogを音声でコントロールする。音声認識によりコマンドを選定し、赤外線リモコン作り赤外線を送信し、ロボットをコントロールする。
この投稿はパスワードで保護されているため抜粋文はありません。
-
加速度センサーとジャイロセンサーをArduinoで使って学び、Telloの慣性ユニットに触れる(^_-)-☆
魅力的な加速度センサー・ジャイロセンサー、ドローンがうまく飛ぶ秘密がここにあった!! そこで、加速度センサー・…
魅力的な加速度センサー・ジャイロセンサー、ドローンがうまく飛ぶ秘密がここにあった!!
そこで、加速度センサー・ジャイロセンサーを学んでいきたいと思います。
加速度センサーは、ドローンの傾き(ピッチ、ロール)や静止状態での重力方向を検知します。
これにより、飛行中の姿勢を常に監視し、必要に応じてモーター出力を調整します。
- ピッチ: 前後の傾き(例:前進・後退の動き)。
- ロール: 左右の傾き(例:横方向への移動)。
- ヨー: 回転(加速度センサー単体ではなくジャイロセンサーが主に担当)。
加速度センサーのデータを基に、ドローンがバランスを保つように制御します。
例えば、外部からの風や軽い衝撃でドローンが傾いた場合、加速度センサーがその変化を検知し、モーターを調整して水平を保つようにします。
- 例:
- 前方に傾いた場合 → 後部モーターの回転速度を上げてバランスを取る。
- 左に傾いた場合 → 右側モーターを調整して安定させる。
ドローンの操作性向について
加速度センサーは、操縦者の操作に対するドローンの応答を最適化します。具体的には、操縦スティックの入力に応じて加速度データを元にモーター出力を調整し、スムーズな飛行を実現します。
それでは、手ごろなArduino と ADXL345 加速度センサーを使用して加速度を測定し、ドローンに使われている方法を学びます。
まずは、動画をご覧ください。
Arduino と ADXL345 加速度センサーを使用して加速度を測定
接続方法
ADXL345 GND → Arduino GND
ADXL345 SCL → Arduino A5 *SCL(クロックライン): データ送受信を同期させるためのクロック信号。
ADXL345 SDA → Arduino A4 *SDA(データライン): データの送受信に使用される双方向ライン。
ADXL345 CS → 3.3Vまたは5V接続
軸デジタル加速度計ADXL345を制御するためのArduinoライブラリ。ADXL345 は、SPI モードと I2C モードの両方をサポートし、データ レートと「範囲」(+/-2/4/8/16g) を調整できるデジタル加速度計です。Adafruit_ADXL345 ドライバーをインストールします。
左のようにスケッチ例より、Adafruit ADLX345 ⇒sensortestのスケッチでまず動かしてみる。
Adafruit ADLX345 ⇒sensortestのスケッチ
#include <Wire.h> //Wire.h: I2C通信に必要なライブラリ。 #include <Adafruit_Sensor.h> //ADXL345用のAdafruitライブラリ #include <Adafruit_ADXL345_U.h> //ADXL345用のAdafruitライブラリ /* Assign a unique ID to this sensor at the same time *///センサーオブジェクトの初期化 Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345); //accelという名前でセンサーオブジェクトを作成//=12345はセンサーのユニークID void displaySensorDetails(void) //センサーの基本情報をシリアルモニターに出力します { sensor_t sensor;//sensor_t構造体を使用して、以下の情報を表示します。 accel.getSensor(&sensor); Serial.println("------------------------------------"); Serial.print ("Sensor: "); Serial.println(sensor.name);//センサー名 Serial.print ("Driver Ver: "); Serial.println(sensor.version);//ドライバのバージョン Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);//ユニークID Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" m/s^2");//加速度の最大値(単位は m/s²) Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" m/s^2");//加速度の最小値(単位は m/s²) Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" m/s^2"); //解像度(単位は m/s²) Serial.println("------------------------------------"); Serial.println(""); delay(500); } void displayDataRate(void) //センサーのデータ取得レート(サンプリングレート)を表示 { Serial.print ("Data Rate: "); switch(accel.getDataRate())//現在のデータレートを取得//switch文で該当する値を文字列として表示 { case ADXL345_DATARATE_3200_HZ: Serial.print ("3200 "); break; case ADXL345_DATARATE_1600_HZ: Serial.print ("1600 "); break; case ADXL345_DATARATE_800_HZ: Serial.print ("800 "); break; case ADXL345_DATARATE_400_HZ: Serial.print ("400 "); break; case ADXL345_DATARATE_200_HZ: Serial.print ("200 "); break; case ADXL345_DATARATE_100_HZ: Serial.print ("100 "); break; case ADXL345_DATARATE_50_HZ: Serial.print ("50 "); break; case ADXL345_DATARATE_25_HZ: Serial.print ("25 "); break; case ADXL345_DATARATE_12_5_HZ: Serial.print ("12.5 "); break; case ADXL345_DATARATE_6_25HZ: Serial.print ("6.25 "); break; case ADXL345_DATARATE_3_13_HZ: Serial.print ("3.13 "); break; case ADXL345_DATARATE_1_56_HZ: Serial.print ("1.56 "); break; case ADXL345_DATARATE_0_78_HZ: Serial.print ("0.78 "); break; case ADXL345_DATARATE_0_39_HZ: Serial.print ("0.39 "); break; case ADXL345_DATARATE_0_20_HZ: Serial.print ("0.20 "); break; case ADXL345_DATARATE_0_10_HZ: Serial.print ("0.10 "); break; default: Serial.print ("???? "); break; } Serial.println(" Hz"); } void displayRange(void) //加速度の計測範囲を表示します。 { Serial.print ("Range: +/- "); switch(accel.getRang()) //現在の範囲を取得し、±16g, ±8g, ±4g, ±2gのいずれかを表示 { case ADXL345_RANGE_16_G: Serial.print ("16 "); break; case ADXL345_RANGE_8_G: Serial.print ("8 "); break; case ADXL345_RANGE_4_G: Serial.print ("4 "); break; case ADXL345_RANGE_2_G: Serial.print ("2 "); break; default: Serial.print ("?? "); break; } Serial.println(" g"); } void setup(void) { #ifndef ESP8266 while (!Serial); // for Leonardo/Micro/Zero #endif Serial.begin(9600);//シリアル通信の初期化 Serial.println("Accelerometer Test"); Serial.println(""); /* Initialise the sensor */ if(!accel.begin()) { /* There was a problem detecting the ADXL345 ... check your connections */ Serial.println("Ooops, no ADXL345 detected ... Check your wiring!"); while(1); } /* Set the range to whatever is appropriate for your project */ accel.setRange(ADXL345_RANGE_16_G);//測定範囲を±16gに設定//コメントアウトを変更すれば、別の範囲も選択可能 // accel.setRange(ADXL345_RANGE_8_G); // accel.setRange(ADXL345_RANGE_4_G); // accel.setRange(ADXL345_RANGE_2_G); /* Display some basic information on this sensor */ displaySensorDetails(); /* Display additional settings (outside the scope of sensor_t) */ displayDataRate(); displayRange(); Serial.println(""); } void loop(void) { /* Get a new sensor event */ sensors_event_t event; accel.getEvent(&event); /* Display the results (acceleration is measured in m/s^2) */ Serial.print("X: "); Serial.print(event.acceleration.x); Serial.print(" "); //X軸: 横方向の加速度。 Serial.print("Y: "); Serial.print(event.acceleration.y); Serial.print(" ");//Y軸: 縦方向の加速度。 Serial.print("Z: "); Serial.print(event.acceleration.z); Serial.print(" ");Serial.println("m/s^2 "); //Z軸: 高さ方向の加速度。 delay(500); }
シリアルモニターには次のようなデーターが表示されます。
X: 2.28 Y: 2.31 Z: 9.85 m/s^2 X: 0.63 Y: 0.16 Z: 9.96 m/s^2 X: 1.61 Y: 2.35 Z: 10.12 m/s^2 X: -2.20 Y: 4.90 Z: 7.18 m/s^2
X軸:
- 横方向(左右)への加速度。
- 正の値は右方向への加速、負の値は左方向への加速を表します。
Y軸:
- 縦方向(前後)への加速度。
- 正の値は前方向への加速、負の値は後方向への加速を表します。
Z軸:
地球の重力加速度(約9.8 m/s²)がZ軸に常に含まれます
上下方向への加速度。
正の値は上方向への加速、負の値は下方向への加速を表します。
観測例
手で持って動かすと、各軸の値が変化します。
加速度データはm/s²で示され、重力加速度(約9.8 m/s²)が常にZ軸に含まれています。
なぜ傾きが加速度に影響するのか
重力加速度の影響
地球の重力(約9.8 m/s²)は常に下方向(Z軸方向)に向かっています。センサーを傾けると、重力がX軸やY軸にも分配されるため、各軸での加速度値が変化します。例えば:
センサーが水平な場合:
Z≈9.8m/s²、 X≈0、Y≈0センサーを45度傾けた場合:
重力がX軸またはY軸に一部分配されるため、Xや Y に値が現れます。傾き角度と加速度の関係
傾きの角度 θは、重力成分と各軸の加速度から次のように計算できます:$$θ=arcsin\frac{(加速度 (XまたはY))}{重力加速度 (約9.8))}$$
例えば、X軸が 4.9 m/s² を示す場合、対応する角度は約30度です。
水平に持った状態(静止)
X軸: ≈0 m/s²
Y軸: ≈0 m/s²
Z軸: ≈9.8 m/s²
前方に傾けた場合(X軸方向に傾ける)
X軸: 正の値(例: 4.9m/s²)
Y軸: ≈0 m/s²
Z軸: 値が減少(例: 8.5 m/s²)
横方向に傾けた場合(Y軸方向に傾ける)
X軸: ≈0 m/s²
Y軸: 正または負の値(例: −4.9 m/s²)
Z軸: 値が減少(例: 8.5 m/s²)
このデータを使用して、センサーの傾きや動きを計算することができます。
- 傾き(角度):
atan2()
関数を用いてX軸・Y軸から計算可能。 - 動きの方向: X軸とY軸の値を見て判定。
- 振動や衝撃の検出: 加速度の変化量を計測。
なぜADLX345で加速度数値が出力できるか?
センサーの基本構造
ADXL345は、内部にMEMS(Micro-Electro-Mechanical Systems)技術を採用しています。この技術により、以下のような構造が形成されています
質量とスプリング構造
- センサー内部には微小な質量(感知質量)があります。
- この質量はスプリング状の構造により、基板に取り付けられています。
- プローフ質量(感知質量)とは?
- センサー内部には微細なシリコン構造体があります。この構造体の一部が「質量」として動的に加速度の影響を受ける部分です。
- この質量はスプリング(薄いシリコン層)で固定されており、加速度がかかると質量が動き、構造全体が変形します。
電気的コンデンサ
- 感知質量に連結されたコンデンサのプレートがあります。
- 質量が動くと、このコンデンサのプレート間の距離が変化します。
2. 加速度の測定原理
質量の動きと慣性の法則
- センサーに加速度が加わると、慣性の影響で感知質量が動きます。
- この動きによって、コンデンサのプレート間の距離が変化します。
容量の変化を検出
- コンデンサのプレート間の距離が変化すると、容量(電気的な性質)が変化します。
- コンデンサの容量は、以下の式で計算されます: $$C=\frac{ε⋅A}{d}C$$
- C: コンデンサの容量
- ε: 誘電率(材料固有の値)
- A: プレートの面積
- d: プレート間の距離
電気信号への変換
- 容量の変化は電子回路で検出され、デジタル信号に変換されます。
- これが各軸(X、Y、Z)の加速度として出力されます。
3. デジタルデータの生成
アナログ信号の変換
- コンデンサの容量変化から生成されたアナログ信号は、センサー内部のA/Dコンバータ(アナログ-デジタル変換器)によってデジタルデータに変換されます。
I²C/SPI通信
- デジタルデータは、I²CまたはSPI通信プロトコルを通じて外部のマイコン(Arduino)に送られます。
- Arduinoはこのデータを解釈して、ユーザーが読める数値(m/s²)として表示します。
4. 実際の数値計算
ADXL345の出力は、16ビットのデジタル値として送信されます。この値は次のように処理されます
フルスケール範囲
- 出力値は、設定された範囲(±2g、±4g、±8g、±16g)に基づきます。
- 設定範囲と出力値から、加速度値(m/s²)が計算されます: $$加速度(g)=\frac{デジタル出力値×範囲加速度 (g)}{2^{15}}$$ 加速度(m/s^2)=加速度(g)×9.8
- 2^15=32,768 は、ADXL345の16ビットデータの最大値に対応する値です
ADLX345加速度センサーのX軸加速度をリアルタイムでpwm信号に変換して、DSO152オシロスコープで時間変化を波形に表示してみた😆
ADLX345加速度センサーのX軸加速度をリアルタイムでpwm信号に変換して、DSO152オシロスコープで時間変化を波形に表示してみた😆 結果、X軸を水平にするとデューティ比50%付近、傾けれると、デューティ比が変化。縦にするとX軸方向の重力成分が0になり、センサーからの出力が0Vになりました。こんな小さな基板の行動が凄い❣️
オシロスコープに表示される数値
Vmax(最大電圧): 出力信号の最大電圧
Vmin(最小電圧): 出力信号の最小電圧
Vpp(ピーク・トゥ・ピーク電圧): Vmax – Vmin
Fre(周波数): 信号の繰り返し回数(Hz)
Dut(デューティー比): PWM信号のHIGH(ON)の割合(%)X軸を水平にしている場合、重力はY軸やZ軸に影響を与えますが、X軸にはほぼ影響を与えません。そのため、中間の電圧(例えば1.65Vなど)が出ます。
X軸を完全に垂直(縦)にした場合、X軸方向の重力成分は0になり、センサーの出力が0VになるADXL345の出力は、次のような式で加速度に変換されます。
(1) アナログ出力を使用する場合
ADXL345は通常、I2CやSPIを使ったデジタル通信でデータを取得しますが、PWMやアナログ出力を使う場合、次のような関係になります。$$ax=\frac{(V_out) – (V_0g)}{S}$$
- axa_xax : X軸方向の加速度 (g)
- VoutV_{out}Vout : センサーの出力電圧 (V)
- V0gV_{0g}V0g : 0g(静止時)の基準電圧 (通常1.65V)
- SSS : センサーの感度(例えば0.3V/g)
例えば、基準電圧が1.65Vで感度が0.3V/gの場合、出力電圧が1.95Vなら$$ax= \frac{(1.95V – 1.65V)}{0.3V/g}=1.0g$$
つまり、+1gの加速度がかかっていることになります。
(2) PWM出力を使用する場合
ADXL345のPWM信号を使う場合、加速度はデューティー比(Dut)から計算できます。$$ax=\frac{(Dut – 50)}{50}×Range$$
- DutDutDut : デューティー比(%)
- Range : 設定した測定範囲(例えば±2g、±4g、±8gなど)
例えば、測定範囲が±2gで、デューティー比が60%だった場合、$$ax= \frac{(60 – 50)}{50} ×2=0.4g$$
つまり、+0.4gの加速度がかかっていることになります。
#include <Wire.h> #include <Adafruit_ADXL345_U.h> Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345); void setup() { Serial.begin(9600); if (!accel.begin()) { Serial.println("ADXL345 not detected!"); while (1); } accel.setRange(ADXL345_RANGE_2_G); } void loop() { sensors_event_t event; accel.getEvent(&event); // X軸の加速度 (-10 ~ 10 m/s^2) を 0~255 のPWMに変換 int pwmValue = map(event.acceleration.x, -10, 10, 0, 255); analogWrite(9, pwmValue); // PWM出力 (D9ピン) Serial.print("pwmValue: "); Serial.println(pwmValue); delay(200); Serial.print("acceleration: "); Serial.println(event.acceleration.x); delay(200); }
次にADXL345を使ってArduinoでX軸・Y軸の傾きに応じて4個のLEDを点灯させるコードを以下に示します。
- X軸、Y軸の傾きを判定し、LEDを次のように制御します:
- 前に傾けたらLED1を点灯
- 後ろに傾けたらLED2を点灯
- 右に傾けたらLED3を点灯
- 左に傾けたらLED4を点灯
ADXL345はI2C通信を使用します。
VCC
→ Arduino3.3V
GND
→ ArduinoGND
SCL
→ ArduinoA5
(UNOの場合)SDA
→ ArduinoA4
(UNOの場合)
4個のLEDはそれぞれ任意のデジタルピンに接続してください。
#include <Wire.h> #include <Adafruit_Sensor.h> #include <Adafruit_ADXL345_U.h> // ADXL345センサーを初期化 Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345); // LEDのピン番号 const int led1 = 2; // 前 const int led2 = 3; // 後ろ const int led3 = 4; // 右 const int led4 = 5; // 左 void setup() { Serial.begin(9600); // LEDピンを出力に設定 pinMode(led1, OUTPUT); pinMode(led2, OUTPUT); pinMode(led3, OUTPUT); pinMode(led4, OUTPUT); // ADXL345の初期化 if (!accel.begin()) { Serial.println("ADXL345を検出できません。接続を確認してください。"); while (1); } accel.setRange(ADXL345_RANGE_16_G); // 測定範囲を±16Gに設定 } void loop() { sensors_event_t event; accel.getEvent(&event); // ADXL345から加速度データを取得 float x = event.acceleration.x; float y = event.acceleration.y; Serial.print("X軸: "); Serial.print(x); Serial.print(" m/s^2 "); Serial.print("Y軸: "); Serial.print(y); Serial.println(" m/s^2 "); // 傾きの閾値(m/s^2) float threshold = 5.0; //threshold を5.0 m/s²に設定しています。この値を超えるかどうかで傾きを判定します。 // LEDの点灯制御 digitalWrite(led1, y > threshold); // 前に傾けたらLED1//傾きの方向に応じたLEDを点灯させます digitalWrite(led2, y < -threshold); // 後ろに傾けたらLED2 digitalWrite(led3, x > threshold); // 右に傾けたらLED3 digitalWrite(led4, x < -threshold); // 左に傾けたらLED4 delay(100); // 100msの遅延//100ミリ秒ごとにデータを更新し、LEDの点灯を切り替えます }
float threshold = 5.0;
というコードで設定された 閾値(いきち)は、特定の加速度を基準にしてLEDを点灯させるかどうかを判断するための値です。この場合、5.0 m/s² という値はX軸やY軸方向の加速度が5.0 m/s²を超えたときに、傾いていると見なしてLEDを点灯させるように設定されています。1. 閾値(いきち:ある判断下すための基準値)の決定方法
閾値は、使用する環境やセンサーの用途によって決まります。以下の要素を考慮して設定されます:
- 重力加速度との関係
静止している状態のセンサーには地球の重力(約9.8 m/s²)がZ軸方向にかかります。このため、X軸やY軸方向の加速度が0 m/s²に近い場合は水平とみなされ、ある程度の値を超えると傾きと見なすことができます。 - 許容する傾きの角度
センサーの加速度値を使って傾きを計算すると、加速度 aと重力 g=9.8 m/s²との比率から角度 θ を求められます:$$θ=arcsin\frac{a}{g}$$ 閾値を a=5.0 m/s² とした場合、対応する角度 θは次のようになります:$$θ=arcsin\frac{5.0}{9.8}$$≈30∘つまり、この場合はセンサーが約30度以上傾いたときにLEDが点灯するようになっています。
2. 閾値を調整する理由
- 高すぎる場合:小さな傾きでは反応しなくなり、より大きく傾けないとLEDが点灯しません。
- 低すぎる場合:少しの振動や誤差でLEDが点灯してしまい、誤動作が増えます。
この閾値
5.0
は、傾きの検出を約30度以上に設定するための目安として使用されています。プロジェクトの特性や必要な感度に応じて、この値を適宜調整することで最適な動作を得られます。今度はジャイロセンサーを使ってみます。
ジャイロセンサーはMPU6050を使用します。こちらは後々に使いますのでESP32と接続し、WiFi接続できるようにしています。
MPU6050 と ESP32 の接続例:
- VCC → 3.3V(ESP32の3.3V出力に接続)
- GND → GND
- SCL → GPIO 22(ESP32のデフォルトSCLピン)
- SDA → GPIO 21(ESP32のデフォルトSDAピン)
ライブラリのインストール
- Arduino IDE を開きます。
- メニューから スケッチ → ライブラリを管理 を選択。
- MPU6050 または Adafruit MPU6050 を検索してインストール。
#include <Wire.h> #include <MPU6050.h> MPU6050 mpu; void setup() { Serial.begin(115200); Wire.begin(); // Arduino AVRではピン番号を指定しない // MPU6050の初期化 mpu.initialize(); if (mpu.testConnection()) { Serial.println("MPU6050の接続に成功しました"); } else { Serial.println("MPU6050の接続に失敗しました"); while (1); // エラー時は停止 } } void loop() { int16_t ax, ay, az; int16_t gx, gy, gz; // 加速度とジャイロのデータを取得 mpu.getAcceleration(&ax, &ay, &az); mpu.getRotation(&gx, &gy, &gz); // データを表示 Serial.print("加速度 (X, Y, Z): "); Serial.print(ax); Serial.print(", "); Serial.print(ay); Serial.print(", "); Serial.println(az); Serial.print("ジャイロ (X, Y, Z): "); Serial.print(gx); Serial.print(", "); Serial.print(gy); Serial.print(", "); Serial.println(gz); delay(1000); // 0.5秒ごとにデータを取得 }
シアルモニターの表示は次の通りです。
ジャイロ (X, Y, Z): 1235, 290, -170 加速度 (X, Y, Z): 15076, 1992, -6080 ジャイロ (X, Y, Z): -950, 5698, -4739 加速度 (X, Y, Z): 6788, 9320, -1992 ジャイロ (X, Y, Z): 4236, -11815, -7154
ドローンTelloのattitude?’コマンドで慣性ユニットからの姿勢角を出力してみる。
import socket import time import matplotlib.pyplot as plt # TelloのIPアドレスとポート設定 TELLO_IP = '192.168.10.1' TELLO_PORT = 8889 LOCAL_PORT = 9000 # ソケットを作成してバインド sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind(('', LOCAL_PORT)) sock.settimeout(3) def send_command(command): """Telloにコマンドを送信""" sock.sendto(command.encode('utf-8'), (TELLO_IP, TELLO_PORT)) def receive_response(): """Telloからの応答を受信""" try: response, _ = sock.recvfrom(1024) return response.decode('utf-8') except socket.timeout: return 'timeout' # グラフ初期設定 plt.ion() fig, ax = plt.subplots() pitch_values, roll_values, yaw_values, time_stamps = [], [], [], [] start_time = time.time() # Telloを起動 send_command('command') print(receive_response()) try: while True: send_command('attitude?') response = receive_response() print(f"Attitude: {response}") if response != 'timeout': # attitude?の応答をパース(例: pitch:1;roll:2;yaw:3) data = response.split(';') pitch = int(data[0].split(':')[1]) roll = int(data[1].split(':')[1]) yaw = int(data[2].split(':')[1]) # データをリストに追加 elapsed_time = time.time() - start_time time_stamps.append(elapsed_time) pitch_values.append(pitch) roll_values.append(roll) yaw_values.append(yaw) # グラフの更新 ax.clear() ax.plot(time_stamps, pitch_values, label='Pitch') ax.plot(time_stamps, roll_values, label='Roll') ax.plot(time_stamps, yaw_values, label='Yaw') ax.set_xlabel('Time (s)') ax.set_ylabel('Angle (degrees)') ax.set_title('Tello Attitude Real-time Plot') ax.legend() plt.pause(0.1) # 100msごとにグラフを更新 time.sleep(0.4) # 400msごとにデータ取得 except KeyboardInterrupt: print("\n終了します。") finally: sock.close() plt.ioff() plt.show()
次は、Telloの実機にジャイロsennsa-
TelloにジャイロセンサーMPU6050(3 軸ジャイロ スコープ、3 軸加速度計)を外付けし、生データーを見てみたいと思います。*電源供給は、Telloバッテリーからです。
ESP32のArduino IDEコードです。
IPアドレスにデーターを飛ばしていきます。
#include <Wire.h> #include <Adafruit_MPU6050.h> #include <Adafruit_Sensor.h> #include <WiFi.h> // Wi-Fi設定 const char* ssid = "3*****CC****-2G"; const char* password = "2**********:"; WiFiServer server(12345); Adafruit_MPU6050 mpu; void setup() { Serial.begin(115200); // Wi-Fi接続 WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Wi-Fi接続中..."); } Serial.println("Wi-Fi接続完了"); Serial.print("IPアドレス: "); Serial.println(WiFi.localIP()); // サーバー開始 server.begin(); // MPU6050初期化 if (!mpu.begin()) { Serial.println("MPU6050初期化失敗"); while (1); } mpu.setAccelerometerRange(MPU6050_RANGE_8_G); mpu.setGyroRange(MPU6050_RANGE_500_DEG); } void loop() { WiFiClient client = server.available(); if (client) { while (client.connected()) { sensors_event_t a, g, temp; mpu.getEvent(&a, &g, &temp); // 加速度データ送信 client.println(String(a.acceleration.x, 2) + "," + String(a.acceleration.y, 2) + "," + String(a.acceleration.z, 2)); delay(100); } client.stop(); } }
グラフ表示のためのPythonコードです。
ESP32からのIPアドレスに送られてくるデーターをmatplotlibを使ってグラフ表示をしていきます。
import socket import time import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation # ESP32のIPアドレスとポート HOST = "192.168.3.**" # 必要に応じてESP32のIPアドレスに変更(Arduino IDEのシリアルモニターで確認) PORT = 12345 def connect_to_esp32(): """ ESP32に接続を試みる関数。 なぜか、これをしないとすぐに切れる。TelloのWiFiの影響か? 最大5回試行し、それでも失敗した場合はNoneを返す。 """ for attempt in range(5): try: print(f"ESP32への接続をトライしています... (試行 {attempt + 1}/5)") sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(10) # タイムアウトを10秒に設定 sock.connect((HOST, PORT)) print("ESP32に接続成功!(^^)/") return sock except Exception as e: print(f"再接続失敗: {e}") time.sleep(2) # 再接続までの待機時間 return None # 初回接続 sock = connect_to_esp32() if not sock: print("ESP32への接続ができませんでした(´;ω;`)") exit(1) # データ格納用リスト time_data = [] # 時間 x_data = [] # x軸 y_data = [] # y軸 z_data = [] # z軸 start_time = time.time() buffer = "" # 受信データのバッファ # グラフ更新関数 def update(frame): global sock, buffer current_time = time.time() - start_time try: # データ受信とバッファ処理 buffer += sock.recv(1024).decode("utf-8") lines = buffer.split("\n") # 改行で分割 buffer = lines.pop() # 最後の未完成データをバッファに残す for line in lines: line = line.strip() if line: print(f"受信データ: {line}") values = list(map(float, line.split(','))) if len(values) == 3: # データを格納 time_data.append(current_time) x_data.append(values[0]) y_data.append(values[1]) z_data.append(values[2]) # 古いデータを削除(必要なら) if len(time_data) > 100: # 表示するデータ数を100に制限(フィリーズするのを避けるため) time_data.pop(0) x_data.pop(0) y_data.pop(0) z_data.pop(0) # グラフを更新 ax.clear() ax.plot(time_data, x_data, label="X_data") ax.plot(time_data, y_data, label="Y_data") ax.plot(time_data, z_data, label="Z_data") ax.legend(loc="upper right") ax.set_title("Acceleration data") ax.set_xlabel("time (second)") ax.set_ylabel("Acceleration (m/s²)") ax.grid() except socket.timeout: print("データ受信がタイムアウトしました。再接続を試みます...") sock.close() sock = connect_to_esp32() if not sock: print("再接続に失敗しました。プログラムを終了します。") exit(1) except Exception as e: print(f"エラー: {e}") exit(1) # matplotlibのセットアップ fig, ax = plt.subplots() ani = FuncAnimation(fig, update, interval=100, cache_frame_data=False) # キャッシュ無効化 try: plt.show() except KeyboardInterrupt: print("プログラムを終了します。") # ソケットを閉じる if sock: sock.close()
ESP32の電源供給は、Telloバッテリーからです。
外付けジャイロでのTello飛行動画は、次の通りです。今回は、思うようなデーターは取れませんでした。
綺麗なデーターを取るには、安定した飛行の腕前も必要だとわかりました。
今後チャレンジします(^^)/
投稿
- 空撮事始め (2021年6月18日)
- 航空法施行規則改正されました。令和3年6月1日 (2021年6月19日)
- Tello(Ryze Technology 社 POWERED BY DJI)の飛ばし方マニュアル (2021年7月5日)
- 趣味におすすめ!ドローン(Tello)のいろいろな楽しさをお伝えします。 (2021年7月5日)
- プログラミング言語って?Pythonの導入前にプログラミング言語の種類をおおまかにまとめてみました。 (2021年7月6日)
- ドローンのプログラミングらしき事をやってみる! はじめてのPython&IDEのインストール方法 (2021年7月7日)
- Tello の画像をOpenCVでPCに写してみる!!OpenCVの導入方法 (2021年7月9日)
- これだけは知っておこう!ドローンを飛ばすのに法律って関係あるの? (2021年7月15日)
- ドローンの空撮は最高!きままに撮ってみました(^^♪ 空撮Gallery集 (2021年7月30日)
- ドローンを飛ばすなら これだけは知っておこう!ドローンの飛行ルール(令和3年6月施行) (2021年7月30日)
- これだけは知っておこう!ドローン空撮には注意が必要です。映像等のインターネット上での注意事項。 (2021年7月30日)
- socket通信プログラムの部分を少しだけ解説してみました (2021年9月2日)
- OpenCVで遊んでみる。 PC内蔵webカメラから動画の撮影。 (2021年9月14日)
- PCでOpenCVで顔認識して遊んでみる。(^^♪ カスケード分類器の使い方 (2021年10月30日)
- ドローン・無人航空機の登録が義務化されます。リモートIDの付け方 (2021年12月14日)
- ドローンのプログラミングでOpenCVをつかい顔認識をしてみる (2022年1月9日)
- ドローン(Tello)を飛ばしてOpenCVで顔認識してみる改良版 (2022年2月21日)
- TelloでOpenCVで顔認識させたらFLIP(フリップ)させる(^^♪ (2022年5月2日)
- Pythonを使いTello(ドローン)でOpenCV(顔認識)から自動追尾をしてみる!☺ (2022年6月13日)
- フィンガーサインでドローン(Tello)を操縦してみた!MediaPipeを使用 (2022年9月29日)
- Pythonプログラミング・OpenCv&MediaPipeを使いドローン(Tello)を自由に操縦してみた! (2022年11月21日)
- Pythonで「Tello(ドローン)で自動追尾プログラミング」改良版を紹介します!これはいける! (2023年3月22日)
- OpenCVで遊んでみる。 PC内蔵カメラから映像の表示 と ドローンからの映像を表示をする (2023年4月13日)
- Telloとパソコンの通信の部分を少しわかりやすくしてみました (2023年4月13日)
- 100g未満のドローン、100g以上のドローンを飛ばすには?法律や準備しないといけないことは何? (2023年4月21日)
- mediapipe(メディアパイプ)& OpenCV・ Pythonでposeランドマーク検出Telloの自動操縦 (2023年5月8日)
- プログラミングで動かせるオススメ!ドローン・ロボット ベスト2選!! (2023年6月1日)
- 海外、子供に人気!プログランミングで動かせるドローンLitebeeWing紹介(パソコン接続方法解説)します。 (2023年7月2日)
- 講座用ダウンロード サイト (2023年7月7日)
- ドローン(Tello)を音声認識コントロールできる?パソコンで2か所Wi-Fi接続してGoogle Speech to Text (2023年7月9日)
- 最近はまっている 楽しーい気分転換アイテム ドローン&プログラミング学習用教材&ラジコン (2023年7月26日)
- Scratch(スクラッチ)ビデオモーションセンサーでTello(ドローン)操作 AR「拡張現実」? (2024年1月31日)
- スクラッチ(Scratch3-Tello) & (マイコンボード)micro:bitを使って、Telllo(ドローン)をコントロールしてみた(^^♪ (2024年5月5日)
- マイコンでドローン感知ロボットを作ってみました(^^♪ microbit & arduino (2024年6月1日)
- mediapipe & Arduino で 自称ロボットのジェスチャーコントロール (2024年6月5日)
- M5Stackを内蔵のESP32でWiFiサーバーとして使い、コードレスで無線ジェスチャーコントロールをしてみました(^^)/ (2024年6月12日)
- ロボットアームのジェスチャーコントロールへの挑戦 からだアクション操作*目指せ老後の食事介助アーム* (2024年6月27日)
- LiteBee Wing/ SKY / Tello でドローンプログラミングを教えます。プログラミングしたい人集まれ(^^♪ (2024年7月3日)
- 自由研究に!「ドローンをつくろう!学ぼう!」by 神戸ロボットクラブ (2024年8月17日)
- 加速度センサーとジャイロセンサーをArduinoで使って学び、Telloの慣性ユニットに触れる(^_-)-☆ (2025年1月16日)
- RobotDogを音声でコントロールする。音声認識によりコマンドを選定し、赤外線リモコン作り赤外線を送信し、ロボットをコントロールする。 (2025年2月5日)
タグ
- オシロスコープ
- ドローンプログラミング
- 神戸ロボットクラブ
- 自由研究
- 小学生
- 組立
- 仕組み
- NPO法人神戸ロボットクラブ
- 特定非営利活動法人神戸ロボットクラブ
- python opencv
- マイコン、microbit
- ドローン自動追尾
- MPU6050
- ADLX345
- 加速度センサー
- ジャイロ
- 慣性ユニット
- IMU
- DSO152
- ロボット、レーダー、トイドローン
- arudino
- 教育
- 親子でプログラミング
- MediaPipe
- プログラミング、自動操縦
- プログラミング、顔認識、自動操縦
- プログラミング 自動追尾
- ロボット
- Otto
- 楽しい
- 知育教育
- マッキーの趣味のドローン
- litebee
- litebeewing
- Scratch
- ドローン
- スクラッチ
- 子供
- モーションセンサー
- OpenCv
- プログラミング
- tello
- プログラミング、大人の趣味、老後対策
- 食事介助、ロボットアーム、mediapipe
- arduino
-
自由研究に!「ドローンをつくろう!学ぼう!」by 神戸ロボットクラブ
ドローンを組み立てながら飛ぶ仕組みを学ぼう!! 開催者:NPO法人神戸ロボットクラブ 👉 ご…
ドローンを組み立てながら飛ぶ仕組みを学ぼう!!
開催(NPO法人神戸ロボットクラブ)概要
トイドローンを組み立てながら、実験をし飛ぶ仕組みを学んでいきます。組み立てるだけではなく、実験をしながらドローンの飛ぶ不思議に迫っていきます。夏の自由研究にもピッタリ!開催日程
2024年8月21日(水)、8月28日(水)いずれかの1日
時間:13:00~15:00
場所:阪神大石 KITEN(キテン)参加費:2800円
組み立てたトイドローンもらえます(^^♪
対象年齢:小中学生体験内容:
組み立て:分解したドローンのパーツキットで組み立てていきます。ネジも1本締めます。
仕組み: ドローンがどんな仕組みで飛んでいるの?部品やプロポを使って実験しながら学んでいきます。
操縦体験:自分で組み立てたドローンを操縦飛行します。開催者:NPO法人神戸ロボットクラブ
👉 ご予約:NPO法人神戸ロボットクラブ・予約サイト講座内容はこんな感じです。年齢層によって臨機応変に対応して優しく、わかりやすい進行で楽しく行きます。
教室に来て、是非、体験してみてください。神戸ロボットクラブの紹介