Site icon Renzo Mischianti

GY-273 QMC5883L clone HMC5883L magnetometer for Arduino, esp8266 and esp32

Spread the love

GY-273 QMC5883L HMC5883L magnetometer sensor Arduino esp8266 esp32

magnetometer is a device that measures magnetic field or magnetic dipole moment. Some magnetometers measure a magnetic field’s direction, strength, or relative change at a particular location.

For example, a compass is a simple magnetometer

Stanley compass

With this principle, a device can understand if It’s changed its position or direction on the 3 axis x, y, and z.

I bought this sensor (and others of the same type) for my projects, and found that it is not that simple to use.

First, because many of that isn’t an HMC5883L but a QMC5883L, and the library and address aren’t the same.

Wiring

Here are some simple wiring examples.

esp32:

esp32 dev kit and gy 273 wiring

esp8266, WeMos D1 mini:

esp8266 WeMos D1 and gy 273 wiring

Arduino UNO:

Arduino UNO and gy 273 wiring

Start prototyping

esp32 lolin32 and gy 273 QMC5883L HMC5883L on breadboard

Check variant

The simple way to identify if It’s a QMC5883L variant is to use an i2c scanner. The variant had an address (0x0D) different from the HMC5883L original one.

/*
 * i2c scanner
 * Renzo Mischianti www.mischianti.org
 */
#include <Wire.h>

void setup() {
  Wire.begin();
  Serial.begin(115200);
  while (!Serial) {delay(100);};
  Serial.println();
  Serial.println("I2C Scanner");
}

void loop() {
  byte error, address;
  int nDevices;
  Serial.println("Scanning...");
  nDevices = 0;
  for(address = 1; address < 127; address++ ) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if (error == 0) {
      Serial.print("I2C device found at address 0x");
      if (address<16) {
        Serial.print("0");
      }
      Serial.println(address,HEX);
      nDevices++;
    }
    else if (error==4) {
      Serial.print("Unknow error at address 0x");
      if (address<16) {
        Serial.print("0");
      }
      Serial.println(address,HEX);
    }
  }
  if (nDevices == 0) {
    Serial.println("No I2C devices found\n");
  }
  else {
    Serial.println("done\n");
  }
  delay(5000);
}

if you obtain this output, you have a QMC5883L variant

Scanning...
I2C device found at address 0x0D
done

Scanning...
I2C device found at address 0x0D
done

Library

I use QMC5883LCompass library that you can find on GitHub, or you can directly download from Arduino Libray manager.

GY-273 QMC5883L HMC5883L magnetometer Arduino library manager

Code

Here is a small code that I wrote, taking parts from some examples and adding the print of the coordinates calculated by the azimuth.

Conversione tra azimut e bearing

So in the code, first, It asks to calibrate the device and after calibration, start to output the values.

/*
 * Simple sketch that use
 * QMC5883LCompass.h from https://github.com/mprograms/QMC5883LCompass
 * library.
 * First the sketch ask to calibrate device so move It, then
 * start to output the data
 *
 *  by Mischianti Renzo <https://mischianti.org>
 *
 *  https://mischianti.org
 *
 */

#include <QMC5883LCompass.h>

QMC5883LCompass compass;

int calibrationData[3][2];
bool changed = false;
bool done = false;
int t = 0;
int c = 0;

bool calibrated = false;

void setup() {
  Serial.begin(9600);
  // Initialize device with i2c 0x0D address
  compass.init();
}

void loop() {
	if (!calibrated){
		// If not calibrated
	  int x, y, z;

	  // Read compass values
	  compass.read();

	  // Return XYZ readings
	  x = compass.getX();
	  y = compass.getY();
	  z = compass.getZ();

	  changed = false;

	  if(x < calibrationData[0][0]) {
	    calibrationData[0][0] = x;
	    changed = true;
	  }
	  if(x > calibrationData[0][1]) {
	    calibrationData[0][1] = x;
	    changed = true;
	  }

	  if(y < calibrationData[1][0]) {
	    calibrationData[1][0] = y;
	    changed = true;
	  }
	  if(y > calibrationData[1][1]) {
	    calibrationData[1][1] = y;
	    changed = true;
	  }

	  if(z < calibrationData[2][0]) {
	    calibrationData[2][0] = z;
	    changed = true;
	  }
	  if(z > calibrationData[2][1]) {
	    calibrationData[2][1] = z;
	    changed = true;
	  }

	  if (changed && !done) {
	    Serial.println("CALIBRATING... Keep moving your sensor around.");
	    c = millis();
	  }
	    t = millis();


	  if ( (t - c > 5000) && !done) {
	    done = true;
	    Serial.println("DONE.");
	    Serial.println();

	    Serial.print("compass.setCalibration(");
	    Serial.print(calibrationData[0][0]);
	    Serial.print(", ");
	    Serial.print(calibrationData[0][1]);
	    Serial.print(", ");
	    Serial.print(calibrationData[1][0]);
	    Serial.print(", ");
	    Serial.print(calibrationData[1][1]);
	    Serial.print(", ");
	    Serial.print(calibrationData[2][0]);
	    Serial.print(", ");
	    Serial.print(calibrationData[2][1]);
	    Serial.println(");");

	    compass.setCalibration(	calibrationData[0][0], calibrationData[0][1], calibrationData[1][0],
	    						calibrationData[1][1], calibrationData[2][0], calibrationData[2][1]);
	    calibrated = true;
	    }
	}else{
		// If calibrating
		  int x, y, z;

		  // Read compass values
		  compass.read();

		  // Return XYZ readings
		  x = compass.getX();
		  y = compass.getY();
		  z = compass.getZ();

		  int azimut = compass.getAzimuth();

		  float bearing = compass.getBearing(azimut);

		  Serial.println();

		  // Write direction
		  if((azimut < 22.5)  || (azimut > 337.5 ))  Serial.print("North     ");
		  if((azimut > 22.5)  && (azimut < 67.5 ))   Serial.print("North-East");
		  if((azimut > 67.5)  && (azimut < 112.5 ))  Serial.print("East      ");
		  if((azimut > 112.5) && (azimut < 157.5 ))  Serial.print("South-East");
		  if((azimut > 157.5) && (azimut < 202.5 ))  Serial.print("South     ");
		  if((azimut > 202.5) && (azimut < 247.5 ))  Serial.print("SOuth-West");
		  if((azimut > 247.5) && (azimut < 292.5 ))  Serial.print("West      ");
		  if((azimut > 292.5) && (azimut < 337.5 ))  Serial.print("North-West");

		  Serial.print(" Azimuth: ");Serial.print(azimut);
		  Serial.print(" Bearing: ");Serial.print(bearing);

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

		  delay(250);
	}
}

Here is the serial output result

CALIBRATING... Keep moving your sensor around.
[...]
CALIBRATING... Keep moving your sensor around. 
DONE. Copy the line below and paste it into your projects sketch.); 
 
compass.setCalibration(0, 1372, -1106, 0, 0, 966); 
 
North-West Azimuth: 321 Bearing: 14.00 - X: 1130 Y: -948 Z: 492 
North-West Azimuth: 320 Bearing: 14.00 - X: 1035 Y: -881 Z: 432 
North-West Azimuth: 320 Bearing: 14.00 - X: 941 Y: -814 Z: 374 
North-West Azimuth: 319 Bearing: 14.00 - X: 845 Y: -747 Z: 316 
North-West Azimuth: 318 Bearing: 14.00 - X: 752 Y: -681 Z: 257 
North-West Azimuth: 317 Bearing: 14.00 - X: 656 Y: -614 Z: 197 
North-West Azimuth: 316 Bearing: 14.00 - X: 561 Y: -550 Z: 138 
North-West Azimuth: 314 Bearing: 13.00 - X: 466 Y: -483 Z: 80 
North-West Azimuth: 312 Bearing: 13.00 - X: 372 Y: -417 Z: 22 
North-West Azimuth: 312 Bearing: 13.00 - X: 372 Y: -416 Z: 21 
North-West Azimuth: 312 Bearing: 13.00 - X: 373 Y: -416 Z: 22 
North-West Azimuth: 314 Bearing: 13.00 - X: 383 Y: -399 Z: 24 
North-West Azimuth: 319 Bearing: 14.00 - X: 383 Y: -335 Z: 60 
North-West Azimuth: 326 Bearing: 14.00 - X: 369 Y: -257 Z: 107 
North-West Azimuth: 333 Bearing: 14.00 - X: 348 Y: -179 Z: 165 
North      Azimuth: 346 Bearing: 15.00 - X: 328 Y: -83 Z: 227 
North      Azimuth: 4 Bearing: 0.00 - X: 307 Y: 25 Z: 292 
North-East Azimuth: 26 Bearing: 1.00 - X: 289 Y: 142 Z: 356 
North-East Azimuth: 43 Bearing: 1.00 - X: 272 Y: 260 Z: 420 
North-East Azimuth: 55 Bearing: 2.00 - X: 253 Y: 363 Z: 484 
North-East Azimuth: 61 Bearing: 2.00 - X: 226 Y: 418 Z: 513 
North-East Azimuth: 63 Bearing: 2.00 - X: 223 Y: 447 Z: 515 
North-East Azimuth: 63 Bearing: 2.00 - X: 230 Y: 458 Z: 515 
North-East Azimuth: 63 Bearing: 2.00 - X: 230 Y: 458 Z: 514 
North-East Azimuth: 59 Bearing: 2.00 - X: 247 Y: 425 Z: 496 
North-East Azimuth: 53 Bearing: 2.00 - X: 246 Y: 328 Z: 444 
North-East Azimuth: 40 Bearing: 1.00 - X: 246 Y: 208 Z: 391 
North      Azimuth: 18 Bearing: 0.00 - X: 245 Y: 83 Z: 326 
North      Azimuth: 354 Bearing: 15.00 - X: 259 Y: -31 Z: 264 
North-West Azimuth: 332 Bearing: 14.00 - X: 277 Y: -148 Z: 202 
North-West Azimuth: 320 Bearing: 14.00 - X: 294 Y: -252 Z: 144 
North-West Azimuth: 313 Bearing: 13.00 - X: 312 Y: -338 Z: 99

Thanks


Spread the love
Exit mobile version