about the QMC5883L code

Hi,
When I am compiling the code of QMC5883L, found that's a kind of complex as the code attached, not like the HMC5883L code seems simple, such as "#define OSR 0b00 " etc. and I even can't find more Arduino+QMC5883L code examples. Is this complex necessary for QMC5883L or just because not many people use it?
Thanks
Adam

// Reference the I2C Library
#include <Wire.h>
// Reference the QMC5883L Compass Library
#include <QMC5883L.h>

// configure the compass as reqiured
#define OSR 0b00               // over sampling rate set to 512. 0b01 is 256, 0b10 is 128 and 0b11 is 64
#define RNG 0b00               // Full Scale set to +/- 2 Gauss, 0b01 is +/- 8.
#define ODR 0b00               // output data rate set to 10Hz, 0b01 is 50Hz, 0b10 is 100Hz, 0b11 is 200Hz
#define MODE 0b01              // continuous measurement mode, 0b00 is standby
#define CR2 0b00000000          // control register 2: disable soft reset and pointer rollover, interrupt pin not enabled
#define RESETPERIOD 0b00000001  // datasheet recommends this be 1, not sure why!

// Store our compass as a variable.
QMC5883L compass;
// Record any errors that may occur in the compass.
int error = 0;

// Out setup routine, here we will configure the microcontroller and compass.
void setup()
{
  // Initialize the serial port.
  Serial.begin(9600);

  Serial.println("Starting the I2C interface.");
  Wire.begin(); // Start the I2C interface.
  TWBR = 12;    //Set the I2C clock speed to 400kHz - only works with Arduino UNO

  Serial.println("Constructing new QMC5883L");
  compass = QMC5883L(); // Construct a new HMC5883 compass.

  // Check that a device responds at the compass address - don't continue if it doesn't - 
  do {
      delay(100);
      Wire.beginTransmission(QMC5883L_Address);
      error = Wire.endTransmission();
      if (error) Serial.println("Can't find compass - is it connected and powered up?");
  } while (error);

  // configure the control registers using static settings above
  // compass autoranges, but starts in the mode given
  compass.dataRegister.OSR_RNG_ODR_MODE = (OSR << 6) |(RNG << 4)  | (ODR <<2) |  MODE;
  compass.dataRegister.CR2_INT_ENABLE = CR2;
  compass.dataRegister.SET_RESET_PERIOD = RESETPERIOD;
    
  Serial.println("Configuring QMC5883L - OSR 512, range +/-2 Gauss, ODR 10, Continuous");
  error = compass.Configure(compass.dataRegister); // use static settings from above - can access register data directly if required..
  if(error != 0) // If there is an error, print it out, although no way to get error with this sensor....
    Serial.println(compass.GetErrorText(error));
  
}

// Our main program loop.
void loop()
{
  // Retrive the raw values from the compass (not scaled).
  MagnetometerRaw raw = compass.ReadRawAxis(&compass.dataRegister);
  // Retrived the scaled values from the compass (scaled to the configured scale).
  MagnetometerScaled scaled = compass.ReadScaledAxis(&compass.dataRegister);
  
  // Values are accessed like so:
  int MilliGauss_OnThe_XAxis = scaled.XAxis;     // (or YAxis, or ZAxis)

  // Calculate heading when the magnetometer is level, then correct for signs of axis.
  // heading (degrees): 0 = +X, 90 = +Y, 180 = -X, 270 = -Y
  float heading = atan2(scaled.YAxis, scaled.XAxis);
 
  // Once you have your heading, you must then add your 'Declination Angle', which is the 'Error' of the magnetic field in your location.
  // Find yours here: http://www.magnetic-declination.com/
  // Example is: 2� 37' W, which is 2.617 Degrees, or (which we need) 0.0456752665 radians, I will use 0.0457
  // If you cannot find your Declination, comment out these two lines, your compass will be slightly off.
  // float declinationAngle = 0.0457;
  float declinationAngle = 0;
  heading += declinationAngle;
  
  // Correct for when signs are reversed.
  if(heading < 0)
    heading += 2*PI;
    
  // Check for wrap due to addition of declination.
  if(heading > 2*PI)
    heading -= 2*PI;
   
  // Convert radians to degrees for readability.
  float headingDegrees = heading * 180/M_PI; 

  // Output the data via the serial port.
  Output(raw, scaled, heading, headingDegrees);

  // Normally we would either:
  // 1. delay the application by 100ms to allow the loop to run at 10Hz (default bandwidth for the QMC5883L)
  // 2. poll the dataready flag in the dataRegister.OVL_DRDY register
  // 3. set the interrupt flat and set a hardware interrupt on the DRDY pin 
  // The first of these options is the easiest.
  delay(100);
}

// Output the data down the serial port.
void Output(MagnetometerRaw raw, MagnetometerScaled scaled, float heading, float headingDegrees)
{
   Serial.print("Raw (X,Y,Z): (");
   Serial.print(raw.XAxis);
   Serial.print(", ");   
   Serial.print(raw.YAxis);
   Serial.print(", ");   
   Serial.print(raw.ZAxis);
   
   Serial.print(")\tScaled (X,Y,Z): (");
   Serial.print(scaled.XAxis, 4);
   Serial.print(", ");   
   Serial.print(scaled.YAxis, 4);
   Serial.print(", ");   
   Serial.print(scaled.ZAxis, 4);
   Serial.println(")");

 
   Serial.print("Magnitude (0.25 to 0.6 on Earth surface): ");
   Serial.print(sqrt(scaled.XAxis * scaled.XAxis + scaled.YAxis * scaled.YAxis + scaled.ZAxis * scaled.ZAxis));
   Serial.print(" Heading: ");
   Serial.print(headingDegrees);
   Serial.print(" Bearing: ");
   Serial.print(bearingDegrees(headingDegrees));
   Serial.println(" (Degrees)");
}

  // Cacluate bearing from heading.
  // bearing 0 = Y pointing North, 90 = Y pointing E, 180 = Y pointing S, 270 = Y pointing W
  float bearingDegrees(float headingDegrees) {
     
     float bearing = 450 - headingDegrees;
     if (bearing >= 360)
     {
      bearing -= 360;
     }
     return bearing;
  }

here is a example of HMC5883L code:

// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#include "Wire.h"

// I2Cdev and HMC5883L must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include "I2Cdev.h"
#include "MechaQMC5883.h"  //// WAS: #include "HMC5883L.h"

// class default I2C address is 0x1E
// specific I2C addresses may be passed as a parameter here
// this device only supports one I2C address (0x1E)
HMC5883L mag;

int16_t mx, my, mz;

#define LED_PIN 13
bool blinkState = false;

void setup() {
    // join I2C bus (I2Cdev library doesn't do this automatically)
    Wire.begin();

    // initialize serial communication
    // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
    // it's really up to you depending on your project)
    Serial.begin(38400);

    // initialize device
    Serial.println("Initializing I2C devices...");
    mag.initialize();

    // verify connection
    Serial.println("Testing device connections...");
    Serial.println(mag.testConnection() ? "HMC5883L connection successful" : "HMC5883L connection failed");

    // configure Arduino LED for
    pinMode(LED_PIN, OUTPUT);
}

void loop() {
    // read raw heading measurements from device
    mag.getHeading(&mx, &my, &mz);

    // display tab-separated gyro x/y/z values
    Serial.print("mag:\t");
    Serial.print(mx); Serial.print("\t");
    Serial.print(my); Serial.print("\t");
    Serial.print(mz); Serial.print("\t");
    
// To calculate heading in degrees. 0 degree indicates North
    float heading = atan2(my, mx);
    if(heading < 0)
      heading += 2 * M_PI;
    Serial.print("heading:\t");
    Serial.println(heading * 180/M_PI);

    // blink LED to indicate activity
    blinkState = !blinkState;
    digitalWrite(LED_PIN, blinkState);
}

The two programs do different things, so they are not strictly comparable.

With some study of the data sheet, I'm sure that the library and code for the QMC5883L could be simplified, as it allows many different options to be selected.

jremington:
The two programs do very different things, so they are not comparable.

However, with some study of the data sheet, I'm sure that the library and code for the QMC5883L could be simplified, as it allows many different options to be selected.

Thank you.
I'll find simple one.

Or study the data sheet, and write your own code. No library is needed, just the proper initialization and data read functions.

jremington:
Or study the data sheet, and write your own code. No library is needed, just the proper initialization and data read functions.

Thanks.
I'll try it.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.