Utilisation d'un mpu6050

Bonjour,

je viens vers vous car je me retrouve dans une impasse suite à vouloir utiliser un MPU6050 dans un petit projet de microfusée.

Etant novice je me retrouve en incompréhension dans les autres forums de ce domaines

Ce petit MPU est monté sur un Arduino Mini Pro et je souhaiterais en récupérer l'accélération et arriver par la suite récupérer la vitesse de celui-ci.

Cependant rien qu'en récupérer l'accélération m'est compliqué. J'ai découvert il y a malheureusement pas si longtemps qu'il fallait d'abord l'étalonner, un étalonnage que je peux retrouver dans la bibliothèque Arduino. Premières questions je voulais savoir si il était essentiel de faire cet étalonnage qui me prend malgré tout quelques minutes avant chaque lancement pour avoir des données les plus vraies possible.

Deuxièmement, je me retrouve encore une fois dans une impasse quant à l'exploitation des données. Je ne sais pas comment avoir de vraies données. Je retrouve plein de programmes à droite à gauche, tous différents et j'ai du mal à saisir ce que je dois faire. J'ai donc un programme Arduino qui vient récupérer des valeurs en G et j'aimerais par la suite faire un programme Python. (Je ne sais pas si c'est exactement le bon endroit où je pourrais demander ça). Un programme Python cette fois-ci pour arriver à traiter ces données et je me retrouve bloqué parce que je ne sais pas exactement comment traiter ces données. Pour arriver d'un côté à supprimer les bruits et également à enlever la gravité. Je souhaiterais avoir cette accélération sur les trois axes et enfin une accélération totale. Si quelqu'un peut m'aider ce serait un grand merci!

Je précise que ces données seront enregistrées sur une carte SD dans un fichier CSV que je viens ensuite lire avec mon programme Python après vol car je ne peux pas avoir de transmission directe.

saisissez ou collez#include <Wire.h>
#include <SPI.h>
#include <SD.h>

#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>
#include <MPU6050.h>

Adafruit_BMP280 bmp;
MPU6050 mpu;

File dataFile;

const int chipSelect = 10;  // CS du module SD
float pression_reference = 1013.25;  // valeur par défaut, sera recalibrée au démarrage

void setup() {
  Serial.begin(115200);
  Wire.begin();

  // ----- INIT SD -----
  Serial.print("Initialisation SD...");
  if (!SD.begin(chipSelect)) {
    Serial.println("Erreur SD !");
    while (1);
  }
  Serial.println("OK");

  dataFile = SD.open("data.csv", FILE_WRITE);
  if (!dataFile) {
    Serial.println("Impossible d'ouvrir data.csv");
    while (1);
  }

  // En-tête du fichier CSV
  dataFile.println("time_ms,accelX,accelY,accelZ,gyroX,gyroY,gyroZ,temperature,pressure_hPa,altitude_m");
  dataFile.close();

  // ----- INIT BMP280 -----
  Serial.println("Initialisation BMP280...");
  if (!bmp.begin(0x76)) {
    Serial.println("BMP280 non detecte !");
    while (1);
  }
  Serial.println("BMP280 OK");

  // ----- INIT MPU6050 -----
  Serial.println("Initialisation MPU6050...");
  mpu.initialize();
  if (!mpu.testConnection()) {
    Serial.println("MPU6050 non detecte !");
    while (1);
  }
  Serial.println("MPU6050 OK");

  // Lire la pression du point de départ
  Serial.println("Calibration de la pression...");
  pression_reference = bmp.readPressure() / 100.0; // hPa
  Serial.print("Pression de reference = ");
  Serial.print(pression_reference);
  Serial.println(" hPa");

}

void loop() {

  // ----- Lecture MPU6050 -----
  int16_t ax, ay, az;
  mpu.getAcceleration(&ax, &ay, &az);

  // conversion en g
  float accelX = ax / 16384.0;
  float accelY = ay / 16384.0;
  float accelZ = az / 16384.0;

  int16_t gx, gy, gz;
  mpu.getRotation(&gx, &gy, &gz);

  float gyroX = gx / 131.0;  // deg/s
  float gyroY = gy / 131.0;
  float gyroZ = gz / 131.0;

  // ----- Lecture BMP280 -----
  float temperature = bmp.readTemperature();
  float pressure = bmp.readPressure() / 100.0;
  float altitude = bmp.readAltitude(pression_reference);


  // ----- Enregistrement SD -----
  dataFile = SD.open("data.csv", FILE_WRITE);
  if (dataFile) {
    dataFile.print(millis());
    dataFile.print(",");
    dataFile.print(accelX);
    dataFile.print(",");
    dataFile.print(accelY);
    dataFile.print(",");
    dataFile.print(accelZ);
    dataFile.print(",");
    dataFile.print(gyroX);
    dataFile.print(",");
    dataFile.print(gyroY);
    dataFile.print(",");
    dataFile.print(gyroZ);
    dataFile.print(",");
    dataFile.print(temperature);
    dataFile.print(",");
    dataFile.print(pressure);
    dataFile.print(",");
    dataFile.println(altitude);
    dataFile.close();
  } else {
    Serial.println("Erreur écriture SD !");
  }

  // ----- Affichage console -----
  Serial.print("Accel X=");
  Serial.print(accelX);
  Serial.print(" Y=");
  Serial.print(accelY);
  Serial.print(" Z=");
  Serial.print(accelZ);
  Serial.print("  Gyro X=");
  Serial.print(gyroX);
  Serial.print(" Y=");
  Serial.print(gyroY);
  Serial.print(" Z=");
  Serial.print(gyroZ);
  Serial.print(" | T=");
  Serial.print(temperature);
  Serial.print("C | P=");
  Serial.print(pressure);
  Serial.print(" hPa | Alt=");
  Serial.print(altitude);
  Serial.println(" m");

  delay(20); 
}

je vous laisse également le script python qui pourrait vous permet de mieux comprendre mes besoin( entièrement fait par GPT je n'ai clairement pas les compétences ...)

# -*- coding: utf-8 -*-
"""
Created on Sat Nov 22 21:22:32 2025

@author: victor
"""

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import CheckButtons
from scipy.signal import butter, filtfilt

plt.ion()  # mode interactif

# --- Fonctions utilitaires ---
def butter_lowpass(data, cutoff, fs, order=4):
    nyq = 0.5 * fs
    if cutoff >= nyq:
        cutoff = 0.49*fs
    b, a = butter(order, cutoff/nyq, btype='low')
    return filtfilt(b, a, data)

# --- Lecture CSV ---
filename = "data.csv"  # Remplacer par le nom réel
df = pd.read_csv(filename)
time = df['time_ms'].values / 1000.0
dt = np.mean(np.diff(time))
fs = 1/dt

# --- Filtrage du bruit ---
cutoff = min(5, fs/4)
accelX = butter_lowpass(df['accelX'].values, cutoff, fs)
accelY = butter_lowpass(df['accelY'].values, cutoff, fs)
accelZ = butter_lowpass(df['accelZ'].values, cutoff, fs)
gyroX = butter_lowpass(df['gyroX'].values, cutoff, fs)
gyroY = butter_lowpass(df['gyroY'].values, cutoff, fs)
gyroZ = butter_lowpass(df['gyroZ'].values, cutoff, fs)
temperature = butter_lowpass(df['temperature'].values, cutoff, fs)
pressure = butter_lowpass(df['pressure_hPa'].values, cutoff, fs)


pressure_alt = df['altitude_m'].values  # altitude par pression


# --- Vitesse verticale par dérivation de l'altitude pression ---
velZ_pressure = np.gradient(pressure_alt, time)


# --- Correction du biais des accels ---
accelX -= np.mean(accelX)
accelY -= np.mean(accelY)
accelZ -= np.mean(accelZ)

# --- Accélération totale ---
accel_total = np.sqrt(accelX**2 + accelY**2 + accelZ**2)

# --- Calcul vitesse par intégration ---
velX = np.cumsum(accelX)*dt
velY = np.cumsum(accelY)*dt
velZ = np.cumsum(accelZ)*dt
vel_total = np.cumsum(accel_total)*dt

# --- Altitude par intégration verticale ---
alt_accel = np.cumsum(velZ)*dt



# --- Filtre de Kalman 1D pour fusion altitude ---
n = len(time)
x = np.zeros(n)
P = np.zeros(n)
Q = 0.1
R = 1.0
x[0] = pressure_alt[0]
P[0] = 1.0

for k in range(1, n):
    x_pred = x[k-1] + velZ[k]*dt
    P_pred = P[k-1] + Q
    K = P_pred / (P_pred + R)
    x[k] = x_pred + K*(pressure_alt[k] - x_pred)
    P[k] = (1 - K)*P_pred

alt_fusion = x
# --- Vitesse verticale à partir de l'altitude fusionnée (Kalman) ---
velZ_kalman = np.gradient(alt_fusion, time)

gyro_total = np.sqrt(gyroX**2 + gyroY**2 + gyroZ**2)

# --- Fonction interactive améliorée ---
def interactive_plot(time, data_list, labels, colors, ylabel, title):
    fig, ax = plt.subplots(figsize=(10,6))
    plt.subplots_adjust(left=0.25)
    lines = []
    for d, l, c in zip(data_list, labels, colors):
        line, = ax.plot(time, d, label=l, color=c)
        lines.append(line)
    ax.set_xlabel("Temps (s)")
    ax.set_ylabel(ylabel)
    ax.set_title(title)
    ax.grid()
    ax.legend()

    # CheckButtons
    rax = plt.axes([0.01, 0.4, 0.2, 0.25])
    check = CheckButtons(rax, labels, [True]*len(labels))

    # Fonction toggle
    def toggle(label):
        idx = labels.index(label)
        lines[idx].set_visible(not lines[idx].get_visible())
        fig.canvas.draw_idle()

    check.on_clicked(toggle)

    # Clic sur le texte
    def on_click(event):
        if event.inaxes == rax:
            for i, text in enumerate(check.labels):
                bbox = text.get_window_extent()
                if bbox.contains(event.x, event.y):
                    toggle(labels[i])
                    break

    fig.canvas.mpl_connect('button_press_event', on_click)
    plt.show()

# --- Graphiques interactifs ---
interactive_plot(time, [accelX, accelY, accelZ, accel_total],
                 ['Accél X','Accél Y','Accél Z','Accél totale'],
                 ['r','g','b','k'],
                 "Accélération (m/s²)", "Accélérations X/Y/Z + totale")

interactive_plot(time, [velX, velY, velZ, vel_total],
                 ['Vitesse X','Vitesse Y','Vitesse Z','Vitesse totale'],
                 ['r','g','b','k'],
                 "Vitesse (m/s)", "Vitesses X/Y/Z + totale")

interactive_plot(time, [gyroX, gyroY, gyroZ, gyro_total],
                 ['Gyro X','Gyro Y','Gyro Z','Gyro totale'],
                 ['r','g','b','k'],
                 "Rotation (°/s)", "Accélérations gyroscopiques X/Y/Z + totale")

# --- Graphique température ---
plt.figure(figsize=(10,6))
plt.plot(time, temperature, label="Température (°C)")
plt.xlabel("Temps (s)")
plt.ylabel("Température (°C)")
plt.title("Température en fonction du temps")
plt.grid()
plt.show()

# --- Graphique altitude fusionnée ---
plt.figure(figsize=(10,6))
plt.plot(time, pressure_alt, label="Altitude pression (CSV)")
plt.plot(time, alt_accel, label="Altitude accéléromètre")
plt.plot(time, alt_fusion, label="Altitude fusion Kalman", linewidth=2, color='k')
plt.xlabel("Temps (s)")
plt.ylabel("Altitude (m)")
plt.title("Altitude : pression vs accéléromètre vs fusion")
plt.legend()
plt.grid()
plt.show()

# --- Graphique pression ---
plt.figure(figsize=(10,6))
plt.plot(time, pressure, label="Pression (hPa)", color='b')
plt.xlabel("Temps (s)")
plt.ylabel("Pression (hPa)")
plt.title("Pression en fonction du temps")
plt.grid()
plt.show()# --- Graphique vitesse verticale (à partir de l'altitude pression) ---
plt.figure(figsize=(10,6))
plt.plot(time, velZ_pressure, label="Vitesse verticale (dérivée altitude pression)", color='m')
plt.xlabel("Temps (s)")
plt.ylabel("Vitesse verticale (m/s)")
plt.title("Vitesse verticale calculée à partir de l'altitude (pression)")
plt.grid()
plt.legend()
plt.show()
# --- Graphique vitesse verticale (à partir de l'altitude fusion Kalman) ---
plt.figure(figsize=(10,6))
plt.plot(time, velZ_kalman, label="Vitesse verticale (dérivée altitude fusion Kalman)", color='k')
plt.xlabel("Temps (s)")
plt.ylabel("Vitesse verticale (m/s)")
plt.title("Vitesse verticale calculée à partir de l'altitude fusionnée (Kalman)")
plt.grid()
plt.legend()
plt.show()

Post mis dans la mauvaise section, on parle anglais dans les forums généraux, je viens de déplacer le post dans la section francophone.

Merci de prendre en compte les recommandations listées dans "Les bonnes pratiques du Forum Francophone".

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.