Utilisation du module magnétomètre 3 axes QMC5883P (GY-271) avec Arduino

Sommaire

Introduction

Le QMC5883P est un magnétomètre 3 axes numérique compact, fonctionnant via une interface I2C (adresse par défaut 0x2C), idéal pour mesurer le champ magnétique terrestre. Il dispose de quatre broches principales : VCC (alimentation 3,3–5V), GND, SDA (données I2C) et SCL (horloge I2C), ce qui le rend facilement intégrable dans tout projet Arduino ou ESP32 nécessitant une boussole électronique fiable et précise.

Grâce à sa capacité à détecter les composantes du champ magnétique terrestre sur trois axes (X, Y, Z), le QMC5883P permet de déterminer l’orientation d’un objet dans l’espace, ce qui en fait un outil précieux pour les systèmes de navigation, les drones, les robots mobiles ou encore les stations météo amateurs. Comparé à son prédécesseur, le HMC5883L, le QMC5883P intègre une interface I2C améliorée, une meilleure sensibilité, et une gestion du bruit optimisée. Son faible encombrement, sa faible consommation d’énergie et sa compatibilité avec des tensions de 3,3V à 5V facilitent son intégration dans des projets embarqués. En utilisant des bibliothèques Arduino adaptées, sa mise en œuvre reste simple même pour les débutants.

Le montage avec la carte Arduino UNO

Nous allons connecter le module QMC5883P à la carte Arduino UNO :

Schéma de montage du module QMC5883P avec la carte Arduino UNO
Schéma de montage du module QMC5883P avec la carte Arduino UNO

Nous allons connecter le module QMC5883P à la carte Arduino UNO :

Arduino Uno QMC5883P
5V VCC
GND GND
A5 SCL
 A4 SDA

Les code Arduino

Lecture des données du champ magnétique

Ce programme Arduino communique avec le capteur magnétomètre QMC5883P via le bus I2C pour lire les valeurs du champ magnétique sur les trois axes X, Y et Z.

				
					#include <Wire.h>

#define QMC5883P_ADDR 0x2C
#define REG_CHIP_ID   0x00
#define REG_DATA_X_L  0x01
#define REG_DATA_X_H  0x02
#define REG_DATA_Y_L  0x03
#define REG_DATA_Y_H  0x04
#define REG_DATA_Z_L  0x05
#define REG_DATA_Z_H  0x06
#define REG_STATUS    0x09
#define REG_CTRL1     0x0A
#define REG_CTRL2     0x0B

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

  // Vérification de l'identifiant
  Wire.beginTransmission(QMC5883P_ADDR);
  Wire.write(REG_CHIP_ID);
  Wire.endTransmission();
  Wire.requestFrom(QMC5883P_ADDR, 1);
  uint8_t id = Wire.read();
  Serial.print("Chip ID = 0x");
  Serial.println(id, HEX);

  // Contrôle 1 : Continuous mode, ODR=200 Hz, OSR=512 (OSR1=11, OSR2=11, ODR=11, MODE=11)
  uint8_t ctrl1 = (0b11 << 6) | (0b11 << 4) | (0b11 << 2) | (0b11);
  Wire.beginTransmission(QMC5883P_ADDR);
  Wire.write(REG_CTRL1);
  Wire.write(ctrl1);
  Wire.endTransmission();

  // Contrôle 2 : Soft reset off, self test off, RNG=30 Gauss (10), Set/Reset auto
  uint8_t ctrl2 = (0 << 7) | (0 << 6) | (0 << 5) | (0b10 << 3) | (0b00);
  Wire.beginTransmission(QMC5883P_ADDR);
  Wire.write(REG_CTRL2);
  Wire.write(ctrl2);
  Wire.endTransmission();

  delay(20);
}

void loop() {
  // On lit le status pour DRDY
  Wire.beginTransmission(QMC5883P_ADDR);
  Wire.write(REG_STATUS);
  Wire.endTransmission();
  Wire.requestFrom(QMC5883P_ADDR, 1);
  uint8_t status = Wire.read();

  if (status & 0x01) { // DRDY = bit 0
    Wire.beginTransmission(QMC5883P_ADDR);
    Wire.write(REG_DATA_X_L);
    Wire.endTransmission();
    Wire.requestFrom(QMC5883P_ADDR, 6);

    int16_t xl = Wire.read() | (Wire.read() << 8);
    int16_t yl = Wire.read() | (Wire.read() << 8);
    int16_t zl = Wire.read() | (Wire.read() << 8);

    Serial.print("X="); Serial.print(xl);
    Serial.print(" Y="); Serial.print(yl);
    Serial.print(" Z="); Serial.println(zl);
  } else {
    Serial.println("Aucune donnée prête");
  }

  delay(100);
}

				
			

Calcul de l'orientation en degrés (Azimut)

Ce programme Arduino lit les données magnétiques brutes du capteur QMC5883P sur les axes X, Y et Z, puis calcule l’azimut, c’est-à-dire l’orientation en degrés par rapport au Nord magnétique. C’est l’équivalent d’une boussole numérique simple.

				
					#include <Wire.h>
#include <math.h>

#define QMC5883P_ADDR 0x2C
#define REG_CHIP_ID   0x00
#define REG_DATA_X_L  0x01
#define REG_STATUS    0x09
#define REG_CTRL1     0x0A
#define REG_CTRL2     0x0B

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

  // Lecture de l'identifiant
  Wire.beginTransmission(QMC5883P_ADDR);
  Wire.write(REG_CHIP_ID);
  Wire.endTransmission();
  Wire.requestFrom(QMC5883P_ADDR, 1);
  uint8_t id = Wire.read();
  Serial.print("Chip ID = 0x");
  Serial.println(id, HEX);

  // Configuration du QMC5883P
  uint8_t ctrl1 = (0b11 << 6) | (0b11 << 4) | (0b11 << 2) | (0b11); // OSR=512, ODR=200Hz, Mode=Continuous
  Wire.beginTransmission(QMC5883P_ADDR);
  Wire.write(REG_CTRL1);
  Wire.write(ctrl1);
  Wire.endTransmission();

  uint8_t ctrl2 = (0 << 7) | (0 << 6) | (0 << 5) | (0b10 << 3) | (0b00); // ±30 Gauss
  Wire.beginTransmission(QMC5883P_ADDR);
  Wire.write(REG_CTRL2);
  Wire.write(ctrl2);
  Wire.endTransmission();

  delay(20);
}

void loop() {
  int16_t x, y, z;

  // Lire le bit DRDY
  Wire.beginTransmission(QMC5883P_ADDR);
  Wire.write(REG_STATUS);
  Wire.endTransmission();
  Wire.requestFrom(QMC5883P_ADDR, 1);
  uint8_t status = Wire.read();

  if (status & 0x01) {
    // Lire les 6 octets de données
    Wire.beginTransmission(QMC5883P_ADDR);
    Wire.write(REG_DATA_X_L);
    Wire.endTransmission();
    Wire.requestFrom(QMC5883P_ADDR, 6);

    x = Wire.read() | (Wire.read() << 8);
    y = Wire.read() | (Wire.read() << 8);
    z = Wire.read() | (Wire.read() << 8);

    Serial.print("X: "); Serial.print(x);
    Serial.print("  Y: "); Serial.print(y);
    Serial.print("  Z: "); Serial.print(z);

    // Calcul de l’azimut (angle par rapport au Nord)
    float heading = atan2((float)y, (float)x) * 180.0 / PI;
    if (heading < 0) heading += 360.0;

    Serial.print("  → Orientation: ");
    Serial.print(heading, 1);
    Serial.println("°");
  }

  delay(200);
}

				
			

Code complet avec affichage des points cardinaux et calibration simple

Voici une version améliorée du programme Arduino pour le QMC5883P qui :

  1. Affiche les points cardinaux (Nord, Nord-Est, Est, etc.) en plus de l’azimut en degrés.

  2. Ajoute une calibration simple par offset manuel (optionnelle et ajustable si vous avez mesuré un décalage dans vos valeurs X/Y).

				
					#include <Wire.h>
#include <math.h>

#define QMC5883P_ADDR 0x2C
#define REG_CHIP_ID   0x00
#define REG_DATA_X_L  0x01
#define REG_STATUS    0x09
#define REG_CTRL1     0x0A
#define REG_CTRL2     0x0B

// Offsets de calibration manuelle (à ajuster selon votre capteur)
int16_t offsetX = 0;
int16_t offsetY = 0;

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

  // Lire l'ID du capteur
  Wire.beginTransmission(QMC5883P_ADDR);
  Wire.write(REG_CHIP_ID);
  Wire.endTransmission();
  Wire.requestFrom(QMC5883P_ADDR, 1);
  uint8_t id = Wire.read();
  Serial.print("Chip ID = 0x");
  Serial.println(id, HEX);

  // Configuration du QMC5883P
  uint8_t ctrl1 = (0b11 << 6) | (0b11 << 4) | (0b11 << 2) | (0b11); // OSR=512, ODR=200Hz, mode continu
  Wire.beginTransmission(QMC5883P_ADDR);
  Wire.write(REG_CTRL1);
  Wire.write(ctrl1);
  Wire.endTransmission();

  uint8_t ctrl2 = (0 << 7) | (0 << 6) | (0 << 5) | (0b10 << 3) | (0b00); // Plage ±30 Gauss
  Wire.beginTransmission(QMC5883P_ADDR);
  Wire.write(REG_CTRL2);
  Wire.write(ctrl2);
  Wire.endTransmission();

  delay(20);
}

void loop() {
  int16_t x, y, z;

  // Vérifie si des données sont prêtes
  Wire.beginTransmission(QMC5883P_ADDR);
  Wire.write(REG_STATUS);
  Wire.endTransmission();
  Wire.requestFrom(QMC5883P_ADDR, 1);
  uint8_t status = Wire.read();

  if (status & 0x01) {
    // Lire les valeurs magnétiques brutes
    Wire.beginTransmission(QMC5883P_ADDR);
    Wire.write(REG_DATA_X_L);
    Wire.endTransmission();
    Wire.requestFrom(QMC5883P_ADDR, 6);

    x = Wire.read() | (Wire.read() << 8);
    y = Wire.read() | (Wire.read() << 8);
    z = Wire.read() | (Wire.read() << 8);

    // Appliquer les offsets de calibration
    x -= offsetX;
    y -= offsetY;

    // Calcul de l'azimut
    float heading = atan2((float)y, (float)x) * 180.0 / PI;
    if (heading < 0) heading += 360.0;

    // Conversion en point cardinal
    const char* direction = cardinalFromAngle(heading);

    // Affichage
    Serial.print("X: "); Serial.print(x);
    Serial.print("  Y: "); Serial.print(y);
    Serial.print("  Z: "); Serial.print(z);
    Serial.print("  → Azimut: ");
    Serial.print(heading, 1);
    Serial.print("° (");
    Serial.print(direction);
    Serial.println(")");
  }

  delay(250);
}

// Fonction qui convertit l'azimut en direction cardinales
const char* cardinalFromAngle(float angle) {
  const char* directions[] = {
    "Nord", "Nord-Est", "Est", "Sud-Est",
    "Sud", "Sud-Ouest", "Ouest", "Nord-Ouest"
  };
  int index = int((angle + 22.5) / 45.0) % 8;
  return directions[index];
}

				
			

Offset de calibration :

  • Si votre capteur affiche toujours un angle décalé (par exemple : 20° alors qu’il est orienté plein Nord), vous pouvez ajuster les variables offsetX et offsetY.

  • Pour une vraie calibration, il faudrait balayer le capteur dans un cercle complet et ajuster dynamiquement les min/max.

Mesures de l'orientation avec le QMC5883P et Arduino
Affichage des mesures sur le moniteur série Arduino

Conclusion

En résumé, le QMC5883P est un capteur magnétique simple à utiliser et très efficace pour vos projets nécessitant une boussole numérique ou une détection d’orientation. Grâce à son interface I2C et à une programmation relativement accessible, il s’intègre facilement à un Arduino ou un ESP32. Que ce soit pour orienter un robot, suivre un mouvement ou simplement afficher un cap Nord sur un écran, ce petit composant a de quoi enrichir vos projets DIY. À vous de jouer ! 🧭

Bonjour ! 🌟 Rejoignez notre newsletter pour ne rien manquer.

Recevez nos offres spéciales et les derniers articles directement dans votre boîte de réception

Nous ne faisons pas de spam, promis ! Consultez notre politique de confidentialité pour en savoir plus.

Panier
Retour en haut