Coder Social home page Coder Social logo

mprograms / qmc5883lcompass Goto Github PK

View Code? Open in Web Editor NEW
87.0 5.0 36.0 68 KB

QMC5883L Compass is a Arduino library for using QMC5583L series chip boards as a compass. Supports: - Getting values of XYZ axis. - Calculating Azimuth. - Getting 16 point Azimuth bearing direction (0 - 15). - Getting 16 point Azimuth bearing Names (N, NNE, NE, ENE, E, ESE, SE, SSE, S, SSW, SW, WSW, W, WNW, NW, NNW) - Smoothing of XYZ readings via rolling averaging and min / max removal. - Optional chipset modes

License: GNU General Public License v3.0

C++ 100.00%
qmc5883l arduino compass azimuth xyz bearing heading qmc5883l-library

qmc5883lcompass's Introduction

QMC5883L Compass Arduino Library

by MPrograms | Github Project Page


Overview

QMC5883L Compass is a Arduino library for using QMC5583L series chip boards as a compass.

Supports:

  • Getting values of XYZ axis.
  • Calculating Azimuth.
  • Getting 16 point Azimuth bearing direction (0 - 15).
  • Getting 16 point Azimuth bearing Names (N, NNE, NE, ENE, E, ESE, SE, SSE, S, SSW, SW, WSW, W, WNW, NW, NNW)
  • Smoothing of XYZ readings via rolling averaging and min / max removal.
  • Optional chipset modes (see below)

Required Libraries

  • Wire.h - No need to included it at the top of your sketch. QMC5883L Compass will included it for you. Just ensure that it is installed in your IDE.

Board Hookup Reference

QMC5883L hookup to Arduino Uno / Nano. For other boards see Arduino Wire Reference

VCC  O ---- O +5v
GND  O ---- O GND
SCL  O ---- O A5
SDA  O ---- O A4
DRDY O ---- X NOT CONNECTED

Arduino Code

Getting Started

To begin, include the QMC5883L Compass Library at the top of your sketch.

#include <QMC5883LCompass.h>
QMC5883LCompass compass;

Then in the setup() function add:

void setup(){
  compass.init();
}

Getting Values

QMC5883L Compass Library makes it easy to get sensor values. Call any of the following within the loop.

Getting X, Y, or Z Axis

To get the X, Y, or Z sensor readings, simply call the desired function.

void loop(){
   int x = compass.getX();
   int y = compass.getY();
   int z = compass.getZ();
}

Getting Azimuth

To get the calculated azimuth (compass degree) value, simply call getAzimuth();.

void loop(){
   int a = compass.getAzimuth();
}

Getting Direction / Bearings

QMC5883L Compass Library calculates the direction range and direction in which the sensor is pointing. There are two functions you can call.

To get a 16 point value of the direction the sensor is facing you can call getBearing(azimuth). This will divide the 360 range of the compass into 16 parts and return a value of 0-15 in clockwise order. In this case 0 = N, 4 = E, 8 = S, 12 = W. This function is helpful if you wish to roll your own direction output function without the need for calculations.

void loop(){
   azimuth = compass.getAzimuth();
   byte b = compass.getBearing(azimuth);
}

To get a 16 point text representation of the direction the sensor is facing you can call getDirection(azimuth);. This will produce a char array[3] with letters representing each direction. Because we can't return an array we need to pass the values by reference.

void loop(){
   azimuth = compass.getAzimuth();
   char myArray[3];
   getDirection(myArray, azimuth);
}

If you want to print these values you can do so like this:

void loop(){
   azimuth = compass.getAzimuth();
   char myArray[3];
   
   getDirection(myArray, azimuth);
   
   Serial.print(myArray[0]);
   Serial.print(myArray[1]);
   Serial.print(myArray[2]);
   Serial.println();
}

Example Sketch & Output

Example Code

#include <QMC5883LCompass.h>

QMC5883LCompass compass;

void setup() {
  Serial.begin(9600);
  compass.init();
}

void loop() {

	int x, y, z, a, b;
	char myArray[3];
	
	compass.read();
  
	x = compass.getX();
	y = compass.getY();
	z = compass.getZ();
	
	a = compass.getAzimuth();
	
	b = compass.getBearing(a);

	compass.getDirection(myArray, a);
  
  
	Serial.print("X: ");
	Serial.print(x);

	Serial.print(" Y: ");
	Serial.print(y);

	Serial.print(" Z: ");
	Serial.print(z);

	Serial.print(" Azimuth: ");
	Serial.print(a);

	Serial.print(" Bearing: ");
	Serial.print(b);

	Serial.print(" Direction: ");
	Serial.print(myArray[0]);
	Serial.print(myArray[1]);
	Serial.print(myArray[2]);

	Serial.println();

	delay(250);
}

Example Output

X: 1005 Y: -147 Z: 1281 Azimuth: 352 Bearing: 15 Direction: NNW

Options & Settings

Changing Chip Settings

The QMC5583L chip provides several different settings you can select.

Change I2C Address

To change the I2C address call compass.setADDR(BYTE_VALUE); before you call compass.init(); like so:

void setup(){
  compass.setADDR(BYTE);
  compass.init();
}

Change Mode, Data Rate, Scale, Sample Ratio

You can also change the mode, sensitivity, sample rate and output rate of the QMC5583L chip. To do this, simply call compass.setMode(MODE, ODR, RNG, OSR); after you have called compass.init(). Note that each value must be a byte.

The values to set each mode are in the table below and were taken from the QST QMC5583L datasheet.

MODE CONTROL (MODE) Value
Standby 0x00
Continuous 0x01
OUTPUT DATA RATE (ODR) Value
10Hz 0x00
50Hz 0x04
100Hz 0x08
200Hz 0x0C
FULL SCALE (RNG) Value
2G 0x00
8G 0x10
OVER SAMPLE RATIO (OSR) Value
64 0xC0
128 0x80
256 0x40
512 0x00

Smoothing Sensor Output

Smoothing can help in cases where sensor readings seem to bounce around. QMC5883L Compass Library uses a rolling average function to store (n) sensor readings and return the average of each axis. This averaging also places smoothing on azimuth and directional output as well.

If enabled, a second part of the function will take the current minimum and maximum values the current rolling average pass and remove them from the overall average. This can help remove unwanted highs and lows that might occur in an erroneous reading.

It should be noted that the built-in smoothing function will result in extra processing time.

To enable smoothing call compass.setSmoothing(STEPS, ADVANCED); before the loop.

  • STEPS : int, The number of steps to smooth the results by. Valid 1 to 10. Higher steps equals more smoothing but longer process time.
  • ADVANCED : bool, True will remove the max and min values from each step and then process as normal. Turning this feature on will results in even more smoothing but will take longer to process. *
void setup(){
  compass.init();
  compass.setSmoothing(10, true);
}

Calibrating The Sensor

QMC5883LCompass library includes a calibration function and utility sketch to help you calibrate your QMC5883L chip. Calibration is a two-step process.

Step 1: Run Calibration Sketch

  1. Ensure that your QMC5883L chip is connected.
  2. Locate the included calibration sketch under EXAMPLES > QMC5883LCOMPASS > CALIBRATION.
  3. Upload the calibration sketch to your arduino and then open the serial monitor.
  4. Follow the directions on the screen by moving your sensor around when the calibration process starts.
  5. Once all calibration data has been collected, the sketch will tell provide you with some code that will look like compass.setCalibration(-1537, 1266, -1961, 958, -1342, 1492); Copy this code. You may want to save it for future reference.

Step 2: Using Calibration Data

  1. Open your project's sketch and paste the line of code you copied directly below the compass.init() call.
  2. Use the QMC5883LCompass library as normal.

It is recommended that you use the provided calibration sketch to generate your sensor's min and max values but you can also add your own by using the compass.setCalibration(X_MIN, X_MAX, Y_MIN, Y_MAX, Z_MIN, Z_MAX); function.

Contributions

Special thanks is given to the following individuals who have contributed to this library:

- Claus Näveke : [TheNitek](https://github.com/TheNitek) for adding calibration functions to the library.
- Paulo C. B. Sincos : [paulosincos](https://github.com/paulosincos)https://github.com/paulosincos) for enhancements to the calibration script.
- ATsaruk : [ATsaruk](https://github.com/ATsaruk) for enhancements to the calibration script.

qmc5883lcompass's People

Contributors

mprograms avatar paulosincos avatar thenitek avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

qmc5883lcompass's Issues

Negative azimuth numbers make bearing and "NNW" ect not work.

The bearing calculation barfs on negative azimuth numbers, bearing code should be modified to:

byte QMC5883LCompass::getBearing(int azimuth){
unsigned long a = ( azimuth > -0.5 ) ? azimuth / 22.5 : (azimuth+360)/22.5;
unsigned long r = a - (int)a;
byte sexdec = 0;
sexdec = ( r >= .5 ) ? ceil(a) : floor(a);
return sexdec;

which produces the correct bearings of 0-15. Previously all W headings were clipped to 0 so only half the rose worked. The second line was my modification. Seems someone changed the bearings over 180' to negative numbers and caused this problem. It may be a difference in QMC5883 that I have too I suppose. Seems other folks online have had this issue. If I compared azimuth to 0, I got a 16 occasionally from the bearing, hence the -0.5' offset.

error: narrowing conversion of '65000' from 'long int' to 'int'

When trying to compile using platformIO and lgt8f328p I get the following error:
.pio/libdeps/program_via_ArduinoISP/QMC5883LCompass/src/QMC5883LCompass.cpp:152:80: error: narrowing conversion of '65000' from 'long int' to 'int' inside { } [-Wnarrowing]

I changed line 152 of QMC5883LCompass.cpp from
int calibrationData[3][2] = {{65000, -65000}, {65000, -65000}, {65000, -65000}};
to
int calibrationData[3][2] = {{32767, -32768}, {32767, -32768}, {32767, -32768}};

and that solved the error and seemed to give the correct results in my test code. I haven't studied the code so I don't know if this is a viable solution.

confusion between N and S

hello,
i am having funny error with the compass directions.
when turning on compass and calibrating it like the example shows sometimes i read N as S and others N as true N.
is there any reason for this behavior? and how can i fixed it ?
Thanks,

QMC5883 library to Attiny85

Since the wire.h library dont work with Attiny85, we need to use TinyWireM lib.
What do I need to change at QMC5883 library to wok with Attiny85?
Could you help me?
Thank you.

Filtering the Influence of Surrounding Objects

Hi,

Thank you for writing this useful library.

When I am operating the compass, I noticed that the readings of the compass is vulnerable to surrounding objects. The readings are very different when I put the compass on my table and 30 centimeters above the table, while keeping the compass pointing to the same direction. Also, when I move the compass to different places (and the same height) on my table, the readings are also quite different.

I am already doing the calibration and reading smoothing. Do you think there is a way to filter out the influence of surrounding objects, and make the compass only respond to the magnetic field of the Earth?

Thank you for your assistance.

All the best,
HC

mgPerDigit

compared to other libraries (for HMC5883) not found the normalization function with respect to offset and gain, or am I doing something wrong?

Wemos D1 Mini usage

Hey, i have this chip and would like to use it in combination with my wemos d1 mini, i used the pinout d1 -> scl d2 -> sda and 5v and gnd but i'm not getting any output at all except for 0's. any idea?

solving hangup of the sensor (in continuous mode)

sometimes the sensor hangs, resetting or init doesn´t solve the problem. There are 2 ways to solve the problem:

  1. powercycle the sensor
  2. modify the Data_Ready method as shown below

bool QMC5883LCompass::Data_Ready () {
Wire.beginTransmission ( _ADDR ) ;
Wire.write ( 0x06 ) ;
int err = Wire.endTransmission();
if (!err) {
Wire.requestFrom(_ADDR, (byte)1);
uint8_t Status = Wire.read() ;
if ( ( Status & 0x01 ) > 0 ) return true ;

// *********************************************************************
//SM: to prevent hangup, if skipbit DOR (0x04) is set
// youe to perform a read to get it working again (but data will be invalid)
if ( ( Status & 0x04 ) > 0 ) read() ;
// *********************************************************************

}
return false ;
}

How to detect a car around the sensor

Hi.
This is not an issue, but an advice request or an example request.

Firstly, this library is quite awesome and I can make it work with the QMC5883L sensor, but I need an action that does not exist in any example, as I see. Maybe I'm wrong, cause I'm still new in the Arduino code world, so please excuse me if there is already there.

So, what I need is to be able to detect the presence of a car above the sensor.
I am working on an application that basically detects a car in front of the gate and triggers the gate to open, so the driver doesn't have to get out and open the gate. I am also new in the magnetometry field, but I researched a bit and it seems that you can detect the car by determining the change that it triggers in the magnetic field around the sensor.
Is there an example of that or can you possibly give some advice in that direction?
Thank you very much for your time and support!

The i2c scanner don’t find QMC5883LCompass and it don’t work on ESP32

Hi!
I used this code to find QMC5883L Compass, but don’t found.
The code compile on ESP32, but don’t show data.
What can I do to test it ?

`#include <Wire.h>

// Set I2C bus to use: Wire, Wire1, etc.
#define WIRE Wire

#define SDA 14 //3 // para teste 14
#define SCL 2 // para teste 2

void setup() {
Wire.begin(SDA, SCL);
//Wire.begin();

Serial.begin(9600);
while (!Serial)
delay(10);
Serial.println("\nI2C Scanner");
}

void loop() {
byte error, address;
int nDevices;

Serial.println("Scanning...");

nDevices = 0;
for(address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
WIRE.beginTransmission(address);
error = WIRE.endTransmission();
Serial.print (" # ");
Serial.print (address);
if (error == 0)
{
Serial.print("\n I2C device found at address 0x");
if (address<16)
Serial.print("0");
Serial.print(address,HEX);
Serial.println(" !");

  nDevices++;
}
else if (error==4) 
{
  Serial.print("Unknown 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); // wait 5 seconds for next scan
}`

Need help with applying calibration data

I am trying to convert your QMC5883LCompass.cpp calibration code to run in a multi-threaded application on a Raspberry Pi. The problem I am having is the use of the calibration data.

To illustrate by way of an example - and I'll restrict it to the x axis for simplicity.

Let xMin = 102 and xMax = 108, this gives xOffset = 105, xDelta = 3 and xScale = 1.

Now assume that xRaw = 103. Therefore xRaw - xOffset = -2 and then xCalibrated = -2!!!!.

What have I misunderstood?

TIA,
Kevin Gilbert

GetAzimuth does not change with, and can not get my magnetic heading.

Hello, I am looking to build a prototype for an autopilot for a boat. I am using the knock off gy-271 and this library to get the magenetic heading of the boat, in degrees (for example heading 176 degrees) so that I can plug in my actual heading to the PID controller to steer towards my desired heading.

The problem I have is that every time I call compass.getAzimuth(), it returns a consitent value, no mater what direction I point the chip in. The value does change based on the calibration settings of the compass. For example, with this calibration: [[-19061,23237],[416,27639],[-3631,432]] the chip returns 280. I have tried to change the smoothing, mode and read the documenation, but I can not figure out what I am doing wrong. Here is the code I am writing: https://github.com/radding/Autopilot. Specifically, here is where I am setting up the compass: https://github.com/radding/Autopilot/blob/main/microcontroller/microcontroller.ino#L57.

I have the chip upright, and SDA is connected to PIN A4, and SCL is connected to pin A5 on my arduino uno. Any pointers would be appreciated!

Bearing angle is not correct, except North=0

Hi ,
At first , I run the calibration.ino ont the GY-271(QMC5883L). and get the calibration data.
I copy its to bearing.ino.

And then I run the bearing.ino.
The North is 0 deg, NE=2 deg, E=4, SE=5, S=6, SW=7, W=4, NW=8.
Does it SW or HW issue??

=== bearing.ino ==
#include <QMC5883LCompass.h>
QMC5883LCompass compass;
void setup() {
Serial.begin(9600);
compass.init();
compass.setCalibrationOffsets(41.00, -159.00, -436.00);
compass.setCalibrationScales(1.09, 0.93, 0.99);
}
void loop() {
compass.read();

byte a = compass.getAzimuth();
// Output here will be a value from 0 - 15 based on the direction of the bearing / azimuth.
byte b = compass.getBearing(a);

Serial.print("B: ");
Serial.print(b);
Serial.println();

delay(250);
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.