In this video lesson we show you how to calibrate the QMC5883L 3-axis magnetometer. The lesson is geared toward this specific magnetometer, but the procedure will be the same for any 3-axis magnetometer. We then use the calibrated reading to measure and calculate the magnetic heading of the device. With this, we have created a calibrated digital compass. In this lesson we are using the GY-87 module, which contains the QMC5883L magnetometer. We are connecting the module to the arduino using the following schematic:

In the video we develop two programs. The first program determines your sensor’s calibration constants. Then the second program uses those calibration constants to calculate heading, or yaw. The second program uses the offsets and scale parameters for MY PARTICULAR SENSOR. These values were determined using the first program. You must determine these values for your sensor, and then edit the second program to use your particular calibration parameters.
Program to determine your calibration parameters:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | #include <Adafruit_MPU6050.h> #include <Adafruit_Sensor.h> #include <Wire.h> #include <QMC5883LCompass.h> int x, y, z; int xMax = -10000; int xMin = 10000; int yMax = -10000; int yMin = 10000; int zMax = -10000; int zMin = 10000; float xOffset, xScale, yOffset, yScale, zOffset, zScale; Adafruit_MPU6050 mpu; QMC5883LCompass compass; void setup() { Serial.begin(115200); mpu.begin(); mpu.setI2CBypass(true); compass.init(); } void loop() { compass.read(); x = compass.getX(); y = compass.getY(); z = compass.getZ(); if (x > xMax) { xMax = x; } if (x < xMin) { xMin = x; } if (y>yMax){ yMax=y; } if (y<yMin){ yMin=y; } if (z > zMax) { zMax = z; } if (z < zMin) { zMin = z; } xOffset = (xMax + xMin) / 2.; yOffset = (yMax + yMin) / 2.; zOffset = (zMax + zMin) / 2.; xScale = 2. / (xMax - xMin); yScale = 2. / (yMax - yMin); zScale = 2. / (zMax - zMin); Serial.print(x); Serial.print(','); Serial.print(y); Serial.print(','); Serial.print(z); Serial.print(','); Serial.print(xMax); Serial.print(','); Serial.print(xMin); Serial.print(','); Serial.print(yMax); Serial.print(','); Serial.print(yMin); Serial.print(','); Serial.print(zMax); Serial.print(','); Serial.print(zMin); Serial.print(','); Serial.print(xOffset); Serial.print(','); Serial.print(yOffset); Serial.print(','); Serial.print(zOffset); Serial.print(','); Serial.print(xScale,5); Serial.print(','); Serial.print(yScale,5); Serial.print(','); Serial.println(zScale,5); delay(100); } |
Once you get your calibration parameters, then put them into this program. This program will then calculate your compass heading:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #include <Adafruit_MPU6050.h> #include <Adafruit_Sensor.h> #include <Wire.h> #include <QMC5883LCompass.h> float x,y,z; //The following numbers are for my particular sensor. You need //to edit the following lines to put in your sensor calibration //numbers float xOffset=-382.5; float yOffset=378.5; float zOffset=1014.5; float xScale = .00121; float yScale=.00115; float zScale=.00105; float head; Adafruit_MPU6050 mpu; QMC5883LCompass compass; void setup() { Serial.begin(115200); mpu.begin(); mpu.setI2CBypass(true); compass.init(); } void loop() { compass.read(); x = (compass.getX()-xOffset)*xScale; y = (compass.getY()-yOffset)*yScale; z = (compass.getZ()-zOffset)*zScale; // Serial.print(x); // Serial.print(','); // Serial.print(y); // Serial.print(','); // Serial.println(z); head = atan2(y,x)*360/2/PI; Serial.print("Heading: "); Serial.println(head); delay(100); } |