20#include <linux/i2c-dev.h>
24 : QObject(parent), m_data(data), m_fileDescriptor(-1) {
25 m_timer =
new QTimer(
this);
26 connect(m_timer, &QTimer::timeout,
this, &Mpu9250Source::readSensor);
35 qDebug() <<
"Tentative d'ouverture du bus I2C-1...";
36 m_fileDescriptor = open(
"/dev/i2c-1", O_RDWR);
37 if (m_fileDescriptor < 0) {
38 qWarning() <<
"Échec de l'ouverture du bus I2C.";
43 ioctl(m_fileDescriptor, I2C_SLAVE, 0x68);
46 char config[2] = {0x6B, 0x00};
47 write(m_fileDescriptor, config, 2);
50 config[0] = 0x1C; config[1] = 0x00; write(m_fileDescriptor, config, 2);
51 config[0] = 0x1B; config[1] = 0x00; write(m_fileDescriptor, config, 2);
55 config[0] = 0x1A; config[1] = 0x03; write(m_fileDescriptor, config, 2);
56 config[0] = 0x1D; config[1] = 0x03; write(m_fileDescriptor, config, 2);
60 qDebug() <<
"Calibration du gyroscope en cours (maintenir le capteur immobile)...";
61 float gyroSum[3] = {0, 0, 0};
66 for (
int i = 0; i < samples; i++) {
67 write(m_fileDescriptor, ®, 1);
68 if (read(m_fileDescriptor, dataG, 6) == 6) {
70 gyroSum[0] += (int16_t)((dataG[0] << 8) | dataG[1]) * (250.0f / 32768.0f) * (M_PI / 180.0f);
71 gyroSum[1] += (int16_t)((dataG[2] << 8) | dataG[3]) * (250.0f / 32768.0f) * (M_PI / 180.0f);
72 gyroSum[2] += (int16_t)((dataG[4] << 8) | dataG[5]) * (250.0f / 32768.0f) * (M_PI / 180.0f);
76 m_gyroBias[0] = gyroSum[0] / samples;
77 m_gyroBias[1] = gyroSum[1] / samples;
78 m_gyroBias[2] = gyroSum[2] / samples;
79 qDebug() <<
"Calibration terminée. Biais du gyroscope calculés.";
83 config[0] = 0x37; config[1] = 0x02; write(m_fileDescriptor, config, 2);
84 ioctl(m_fileDescriptor, I2C_SLAVE, 0x0C);
87 config[0] = 0x0A; config[1] = 0x16; write(m_fileDescriptor, config, 2);
88 qDebug() <<
"Acquisition MPU9250 démarrée avec succès.";
91 qWarning() <<
"[MODE SIMULATION] - Code compilé sous Windows/Autre. Le matériel I2C est bypassé.";
94 m_elapsedTimer.start();
98void Mpu9250Source::readSensor() {
107 float dt = m_elapsedTimer.restart() / 1000.0f;
111 if (m_fileDescriptor < 0)
return;
118 ioctl(m_fileDescriptor, I2C_SLAVE, 0x68);
130 if (write(m_fileDescriptor, ®, 1) == 1 && read(m_fileDescriptor, dataAG, 14) == 14) {
139 float ax = (int16_t)((dataAG[0] << 8) | dataAG[1]) * (2.0f / 32768.0f);
140 float ay = (int16_t)((dataAG[2] << 8) | dataAG[3]) * (2.0f / 32768.0f);
141 float az = (int16_t)((dataAG[4] << 8) | dataAG[5]) * (2.0f / 32768.0f);
149 float gx = ((int16_t)((dataAG[8] << 8) | dataAG[9])) * (250.0f / 32768.0f) * (M_PI / 180.0f) - m_gyroBias[0];
150 float gy = ((int16_t)((dataAG[10] << 8) | dataAG[11])) * (250.0f / 32768.0f) * (M_PI / 180.0f) - m_gyroBias[1];
151 float gz = ((int16_t)((dataAG[12] << 8) | dataAG[13])) * (250.0f / 32768.0f) * (M_PI / 180.0f) - m_gyroBias[2];
158 ioctl(m_fileDescriptor, I2C_SLAVE, 0x0C);
162 write(m_fileDescriptor, ®St1, 1);
166 if (read(m_fileDescriptor, &st1, 1) == 1 && (st1 & 0x01)) {
170 write(m_fileDescriptor, ®Mag, 1);
172 if (read(m_fileDescriptor, dataM, 7) == 7) {
180 float mx = ((int16_t)((dataM[1] << 8) | dataM[0]) - m_magBias[0]) * m_magScale[0];
181 float my = ((int16_t)((dataM[3] << 8) | dataM[2]) - m_magBias[1]) * m_magScale[1];
182 float mz = ((int16_t)((dataM[5] << 8) | dataM[4]) - m_magBias[2]) * m_magScale[2];
192 madgwickUpdate(-ax, ay, az, gx, -gy, -gz, my, -mx, mz, dt);
200 float roll = std::atan2(2.0f * (q[0] * q[1] + q[2] * q[3]), 1.0f - 2.0f * (q[1] * q[1] + q[2] * q[2]));
201 float pitch = std::asin(2.0f * (q[0] * q[2] - q[3] * q[1]));
206 float mag_x_horiz = my * std::cos(pitch) + (-mx) * std::sin(roll) * std::sin(pitch) - mz * std::cos(roll) * std::sin(pitch);
207 float mag_y_horiz = (-mx) * std::cos(roll) + mz * std::sin(roll);
210 float yaw = std::atan2(mag_y_horiz, mag_x_horiz);
215 float heading = -yaw * (180.0f / M_PI);
222 if (heading < 0) heading += 360.0f;
223 if (heading >= 360.0f) heading -= 360.0f;
231 static float smoothedHeading = heading;
235 float diff = heading - smoothedHeading;
236 if (diff > 180.0f) smoothedHeading += 360.0f;
237 else if (diff < -180.0f) smoothedHeading -= 360.0f;
239 smoothedHeading = (smoothedHeading * 0.90f) + (heading * 0.10f);
242 if (smoothedHeading >= 360.0f) smoothedHeading -= 360.0f;
243 else if (smoothedHeading < 0.0f) smoothedHeading += 360.0f;
246 qDebug() <<
" Cap :" << smoothedHeading <<
"° | dt:" << dt;
249 if (m_data) m_data->setHeading(
static_cast<double>(smoothedHeading));
253 qDebug() <<
"Erreur de lecture I2C sur l'adresse 0x68 (Capteur débranché ou indisponible).";
269void Mpu9250Source::madgwickUpdate(
float ax,
float ay,
float az,
float gx,
float gy,
float gz,
float mx,
float my,
float mz,
float dt) {
270 float q1 = q[0], q2 = q[1], q3 = q[2], q4 = q[3];
272 float hx, hy, _2bx, _2bz;
273 float s1, s2, s3, s4;
274 float qDot1, qDot2, qDot3, qDot4;
277 float _2q1mx;
float _2q1my;
float _2q1mz;
float _2q2mx;
278 float _4bx;
float _4bz;
279 float _2q1 = 2.0f * q1;
float _2q2 = 2.0f * q2;
float _2q3 = 2.0f * q3;
float _2q4 = 2.0f * q4;
280 float _2q1q3 = 2.0f * q1 * q3;
float _2q3q4 = 2.0f * q3 * q4;
281 float q1q1 = q1 * q1;
float q1q2 = q1 * q2;
float q1q3 = q1 * q3;
float q1q4 = q1 * q4;
282 float q2q2 = q2 * q2;
float q2q3 = q2 * q3;
float q2q4 = q2 * q4;
283 float q3q3 = q3 * q3;
float q3q4 = q3 * q4;
float q4q4 = q4 * q4;
286 norm = std::sqrt(ax * ax + ay * ay + az * az);
287 if (norm == 0.0f)
return;
289 ax *= norm; ay *= norm; az *= norm;
292 norm = std::sqrt(mx * mx + my * my + mz * mz);
293 if (norm == 0.0f)
return;
295 mx *= norm; my *= norm; mz *= norm;
298 _2q1mx = 2.0f * q1 * mx;
299 _2q1my = 2.0f * q1 * my;
300 _2q1mz = 2.0f * q1 * mz;
301 _2q2mx = 2.0f * q2 * mx;
302 hx = mx * q1q1 - _2q1my * q4 + _2q1mz * q3 + mx * q2q2 + _2q2 * my * q3 + _2q2 * mz * q4 - mx * q3q3 - mx * q4q4;
303 hy = _2q1mx * q4 + my * q1q1 - _2q1mz * q2 + _2q2mx * q3 - my * q2q2 + my * q3q3 + _2q3 * mz * q4 - my * q4q4;
304 _2bx = std::sqrt(hx * hx + hy * hy);
305 _2bz = -_2q1mx * q3 + _2q1my * q2 + mz * q1q1 + _2q2mx * q4 - mz * q2q2 + _2q3 * my * q4 - mz * q3q3 + mz * q4q4;
310 s1 = -_2q3 * (2.0f * q2q4 - _2q1q3 - ax) + _2q2 * (2.0f * q1q2 + _2q3q4 - ay) - _2bz * q3 * (_2bx * (0.5f - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mx) + (-_2bx * q4 + _2bz * q2) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - my) + _2bx * q3 * (_2bx * (q1q3 + q2q4) + _2bz * (0.5f - q2q2 - q3q3) - mz);
311 s2 = _2q4 * (2.0f * q2q4 - _2q1q3 - ax) + _2q1 * (2.0f * q1q2 + _2q3q4 - ay) - 4.0f * q2 * (1.0f - 2.0f * q2q2 - 2.0f * q3q3 - az) + _2bz * q4 * (_2bx * (0.5f - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mx) + (_2bx * q3 + _2bz * q1) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - my) + (_2bx * q4 - _4bz * q2) * (_2bx * (q1q3 + q2q4) + _2bz * (0.5f - q2q2 - q3q3) - mz);
312 s3 = -_2q1 * (2.0f * q2q4 - _2q1q3 - ax) + _2q4 * (2.0f * q1q2 + _2q3q4 - ay) - 4.0f * q3 * (1.0f - 2.0f * q2q2 - 2.0f * q3q3 - az) + (-_4bx * q3 - _2bz * q1) * (_2bx * (0.5f - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mx) + (_2bx * q2 + _2bz * q4) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - my) + (_2bx * q1 - _4bz * q3) * (_2bx * (q1q3 + q2q4) + _2bz * (0.5f - q2q2 - q3q3) - mz);
313 s4 = _2q2 * (2.0f * q2q4 - _2q1q3 - ax) + _2q3 * (2.0f * q1q2 + _2q3q4 - ay) + (-_4bx * q4 + _2bz * q2) * (_2bx * (0.5f - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mx) + (-_2bx * q1 + _2bz * q3) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - my) + _2bx * q2 * (_2bx * (q1q3 + q2q4) + _2bz * (0.5f - q2q2 - q3q3) - mz);
314 norm = std::sqrt(s1 * s1 + s2 * s2 + s3 * s3 + s4 * s4);
316 s1 *= norm; s2 *= norm; s3 *= norm; s4 *= norm;
319 qDot1 = 0.5f * (-q2 * gx - q3 * gy - q4 * gz) - beta * s1;
320 qDot2 = 0.5f * (q1 * gx + q3 * gz - q4 * gy) - beta * s2;
321 qDot3 = 0.5f * (q1 * gy - q2 * gz + q4 * gx) - beta * s3;
322 qDot4 = 0.5f * (q1 * gz + q2 * gy - q3 * gx) - beta * s4;
331 norm = std::sqrt(q1 * q1 + q2 * q2 + q3 * q3 + q4 * q4);
343 if (m_fileDescriptor >= 0) {
344 close(m_fileDescriptor);
345 m_fileDescriptor = -1;
Mpu9250Source(TelemetryData *data, QObject *parent=nullptr)
Constructeur de la source MPU9250.
void stop()
Arrête l'acquisition et ferme la connexion I2C.
void start()
Démarre l'acquisition matérielle.
~Mpu9250Source()
Destructeur. Assure la fermeture propre du descripteur de fichier I2C.
Classe représentant les données en temps réel du véhicule. Cette classe hérite de QObject et centrali...
Rôle architectural : Source de données inertielles et boussole matérielle (I2C).
Rôle architectural : Modèle central de télémétrie partagé entre les modules C++ et l'interface QML.