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 :
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
#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
#include
#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 :
-
Affiche les points cardinaux (Nord, Nord-Est, Est, etc.) en plus de l’azimut en degrés.
-
Ajoute une calibration simple par offset manuel (optionnelle et ajustable si vous avez mesuré un décalage dans vos valeurs X/Y).
#include
#include
#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
offsetXetoffsetY. -
Pour une vraie calibration, il faudrait balayer le capteur dans un cercle complet et ajuster dynamiquement les min/max.
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 ! 🧭




