esp32とMPU6050を繋いでPCに仮想シリアルでデータを渡すCのプログラムとPC側では3軸の加速度データに応じて立方体を動かすPythonのプログラムを作ってください
PythonはPyOpenGLとpygameのライブラリを使ってください
はい、承知いたしました。ESP32とMPU6050で加速度データを取得し、PC上のPythonプログラムで立方体を動かすサンプルプログラムを作成します。
ESP32とMPU6050は、I2C通信で以下のように接続してください。
ESP32 SCL (GPIO 22) <-> MPU6050 SCL
ESP32 SDA (GPIO 21) <-> MPU6050 SDA
ESP32 3V3 <-> MPU6050 VCC
ESP32 GND <-> MPU6050 GND
1. ESP32側のプログラム (C/C++)
まず、Arduino IDEにAdafruitのMPU6050ライブラリをインストールする必要があります。
ツール > ライブラリを管理 から Adafruit MPU6050 を検索してインストールしてください。依存ライブラリである Adafruit Unified Sensor と Adafruit BusIO も一緒にインストールされます。
以下のコードをESP32に書き込んでください。MPU6050から取得したX, Y, Z軸の加速度データを x,y,z\n の形式でシリアルポートに出力します。
C++
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
// MPU6050オブジェクトを作成
Adafruit_MPU6050 mpu;
void setup() {
// シリアル通信を開始 (ボーレートはPython側と合わせる)
Serial.begin(115200);
while (!Serial) {
delay(10); // シリアルポートの接続を待つ
}
// MPU6050の初期化
if (!mpu.begin()) {
Serial.println("Failed to find MPU6050 chip");
while (1) {
delay(10);
}
}
Serial.println("MPU6050 Found!");
// センサーのレンジ設定
mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
mpu.setGyroRange(MPU6050_RANGE_500_DEG);
mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
delay(100);
}
void loop() {
// センサーイベント(加速度、ジャイロ、温度)を取得するための変数
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
// 3軸の加速度データをカンマ区切りでシリアルポートに出力
// フォーマット: "x,y,z\n"
Serial.printf("%.2f,%.2f,%.2f\n", a.acceleration.x, a.acceleration.y, a.acceleration.z);
// 50ms待機 (送信レート: 約20Hz)
delay(50);
}
2. PC側のプログラム (Python)
PC側では、まず必要なライブラリをインストールします。
Bash
pip install pyserial pygame PyOpenGL PyOpenGL_accelerate
以下のPythonコードを実行すると、ウィンドウが開き、ESP32から送られてくる加速度データに応じて立方体が回転します。
**注意:**コード内の SERIAL_PORT は、お使いの環境に合わせて変更してください。Windowsなら 'COM3' や 'COM4'、macOSやLinuxなら '/dev/tty.usbserial-XXXX' のような名前になります。Arduino IDEのシリアルモニタで確認できるポート名と同じものを指定してください。
Python
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
import serial
import time
# --- 設定 ---
# ESP32が接続されているシリアルポート名を指定
SERIAL_PORT = 'COM3' # ★★★★★自分の環境に合わせて変更★★★★★
BAUD_RATE = 115200 # ESP32のプログラムと合わせる
WINDOW_WIDTH = 800
WINDOW_HEIGHT = 600
# --- 設定ここまで ---
def draw_cube():
"""立方体を描画する関数"""
vertices = (
(1, -1, -1), (1, 1, -1), (-1, 1, -1), (-1, -1, -1),
(1, -1, 1), (1, 1, 1), (-1, -1, 1), (-1, 1, 1)
)
edges = (
(0, 1), (0, 3), (0, 4), (2, 1), (2, 3), (2, 7),
(6, 3), (6, 4), (6, 7), (5, 1), (5, 4), (5, 7)
)
surfaces = (
(0, 1, 2, 3), (3, 2, 7, 6), (6, 7, 5, 4),
(4, 5, 1, 0), (1, 5, 7, 2), (4, 0, 3, 6)
)
colors = (
(1, 0, 0), (0, 1, 0), (0, 0, 1),
(1, 1, 0), (0, 1, 1), (1, 0, 1)
)
glBegin(GL_QUADS)
for i, surface in enumerate(surfaces):
glColor3fv(colors[i])
for vertex_index in surface:
glVertex3fv(vertices[vertex_index])
glEnd()
# 立方体のエッジを黒で描画
glColor3fv((0, 0, 0))
glBegin(GL_LINES)
for edge in edges:
for vertex_index in edge:
glVertex3fv(vertices[vertex_index])
glEnd()
def main():
# PygameとOpenGLの初期化
pygame.init()
display = (WINDOW_WIDTH, WINDOW_HEIGHT)
pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
pygame.display.set_caption("ESP32 MPU6050 Cube Demo")
# OpenGLの射影設定
gluPerspective(45, (display[0] / display[1]), 0.1, 50.0)
glTranslatef(0.0, 0.0, -10) # カメラを少し後ろに下げる
glEnable(GL_DEPTH_TEST) # Zバッファを有効にする
# シリアルポートの初期化
try:
ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1)
time.sleep(2) # 接続が安定するまで待機
print(f"Connected to {SERIAL_PORT}")
except serial.SerialException as e:
print(f"Error: Could not open port {SERIAL_PORT}. {e}")
return
# メインループ
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
ser.close()
pygame.quit()
quit()
# シリアルデータの読み込みと解析
accel_x, accel_y = 0, 0
try:
if ser.in_waiting > 0:
line = ser.readline().decode('utf-8').strip()
data = line.split(',')
if len(data) == 3:
# Y軸の加速度でX軸周りの回転、X軸の加速度でY軸周りの回転を行う
accel_x = float(data[0])
accel_y = float(data[1])
# z_val = float(data[2]) # Z軸データは今回は使用しない
except (ValueError, UnicodeDecodeError):
# 不正なデータは無視
continue
# OpenGLの描画処理
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glPushMatrix() # 現在の行列を保存
# 加速度データに基づいて回転
# 傾きをより大きく反映させるために係数(例: 5)をかける
# MPU6050のX加速度でY軸周りに回転
glRotatef(accel_x * 5, 0, 1, 0)
# MPU6050のY加速度でX軸周りに回転
glRotatef(accel_y * 5, 1, 0, 0)
draw_cube() # 立方体を描画
glPopMatrix() # 行列を元に戻す
pygame.display.flip() # 画面を更新
pygame.time.wait(10) # 少し待機
if __name__ == '__main__':
main()
実行方法
上記のC++コードをESP32に書き込みます。
ESP32をPCに接続したままにします。
上記のPythonコードのSERIAL_PORTを正しいポート名に修正します。
Pythonスクリプトを実行します (python your_script_name.py)。
ウィンドウが表示され、ESP32/MPU6050を傾けると、その動きに応じて立方体が回転します。
コメント
コメントを投稿