Friday, October 23, 2015

Connecting the Duinotech 3 Axis Compass to an Arduino

1. Duinotech 3 Axis Compass Magnetometer Module

*******************************
EDIT - 14 October 2022

You will see in the comments below that some time in 2021, something changed with the Duinotech 3-axis magnetometer and the Honeywell HMC5883L Arduino libraries stopped working.

I recently purchased a new module and compared it to the original I bought in 2015. They are very different, in particular there is one less pin and the magnetometer IC and supporting components have changed.

I've done a full write up on the Reefwing Medium site. If you can't be bothered reading this, the new chip being used is the Memsic MMC5883MA. I list some compatible Arduino libraries in my article - so you should read it!

*******************************

At a recent mini maker faire, I purchased the duinotech 3 Axis Compass Magnetometer Module (Part Number: XC-4496) from the Jaycar Electronics stand. I thought this would be handy for calculating heading information for AVA the robot.

Unfortunately, the module comes with no instructions and just these very brief specifications:
  • Operating Voltage: 5VDC (or 3.3 VDC)
  • Resolution: 12 bits
  • Interface: I2C
  • Includes: 5V to 3.3V level shifter (so you can operate it from 5 VDC)
  • Dimensions: 20(L) x 16(W) x 5(H) mm
We know that the module communicates via I2C but without knowing the module address or the available instructions, this isn't much use. No problem, I'll head over to the Jaycar website and look up the technical specs. Bzzzzzzzt! If you click on the link above, you will see the only information provided is the specifications printed on the packaging. It appears that Jaycar are moving away from Freetronics for their Arduino compatible boards, shields and sensors to duinotech a Chinese manufacturer. I assume they are doing this based on cost, the Freetronics stuff is good quality and very well documented. 

2. Honeywell HMC5883L 3-Axis Digital Compass IC


If you have good eye sight you will see HMC5883L printed on the PCB. A quick google will determine that this is a 3-Axis Digital Compass IC produced by Honeywell. The HMC5883L Data Sheet is very comprehensive and requires everything that you need to interface the chip to an Arduino via I2C. The duinotech module is apparently a break out board for the HMC5883L, similar to the one produced by SparkFun. It is in fact an improvement on the SparkFun version in that it can be driven from 5VDC and the interrupt line is also broken out.

3. HMC5883L Arduino Library


Armed with the data sheet you could work out how to get the module talking to an Arduino but as usual, a number of people have already done the hard work for you. I ended up using a library written by Korneliusz Jarzebski, a Polish chap. The HMC5883L Arduino Library is accompanied by a tutorial, which is in Polish but google translate does a pretty good job of converting this to English.

One thing that the library is missing is the keyword definition file which the Arduino IDE uses to colour highlight defined library names and methods. I have produced a keywords.txt file for the Jarzebski HMC5883L Library which you are free to download and use. It includes all of the public methods exposed by the HMC5883L class.

To use the library, create a folder called HMC5883L in the Arduino libraries folder. Within this copy the HMC5883L.h and HMC5883L.cpp files from the Jarzebski Github repository and the keywords.txt file. Also create a sub folder called examples and copy the HMC5883L_calibrate,  HMC5883L_compass, and HMC5883L_simple files into it. You will need to restart the Arduino IDE to see the new library. The HMC5883L_simple sketch example shows how to use the library and test your module.

Here is a quick video which shows the HMC5883L mounted on my robot AVA. On the OLED screen you can see when the compass is connected and the observed heading when the text scrolls up.


18 comments:

  1. Wow. Thank you for providing this great information.
    I will need to do some homework to understand all this.
    Cheers!

    ReplyDelete
  2. Despite both your and Korneliusz's excellent tutorials (and checking my wiring) my Arduino Uno still won't recognise this compass module :(

    "Could not find a valid HMC5883L sensor, check wiring!"

    Nothing you can do about this, David, I'm just sharing my pain of undocumented Jaycar products.

    ReplyDelete
    Replies
    1. Hi Peter - thanks for the kind words. The first thing I would check is that the arduino can see an I2C device on the bus. You may be using the wrong address. Use something like i2cscanner (https://gist.github.com/tfeldmann/5411375).

      Delete
    2. Thanks David. So the good news is that my Arduino Uno can detect the sensor at address 0x30 by using that above scanner, but the bad news is that I haven't quite worked out how to use the address in the example code. I did try to shortcut it by using the value as the address value in HMC5883L.h, but that didn't seem to work. I appreciate your help and advice, but I don't expect it for free :)

      Delete
    3. Oh, and I also found this http://electronoobs.com/eng_arduino_tut77.php which did let me use my own address (in case it helps others), but it didn't help me.

      Delete
    4. Happy to help if I can. Its good that you can see the device on the I2C bus. Pity the library doesn't work but it is getting a bit old, the API may have changed. The next thing I would try is getting some sort of response from the sensor. I would go back to first principles and try accessing the registers as per the data sheet. For example:

      Using the (power-on) initialization process for “single-measurement mode”:

      1. Write CRA (00) – send 0x3C 0x00 0x70 (8-average, 15 Hz default or any other rate, normal measurement)
      2. Write CRB (01) – send 0x3C 0x01 0xA0 (Gain=5, or any other desired gain)
      3. For each measurement query:
      Write Mode (02) – send 0x3C 0x02 0x01 (Single-measurement mode)
      Wait 6 ms or monitor status register or DRDY hardware interrupt pin
      Send 0x3D 0x06 (Read all 6 bytes. If gain is changed then this data set is using previous gain)
      Convert three 16-bit 2’s compliment hex values to decimal values and assign to X, Z, Y, respectively.

      Delete
    5. I am having the same issue as Peter. Using i2scanner my address is also 0x30. Any idea of how to fix this?

      Delete
    6. Hi @Hilary - VK2IUW,

      The library I link to above doesn't look like its being maintained. Try this one - https://www.arduino.cc/reference/en/libraries/grove-3-axis-digital-compass-hmc5883l/

      You will need to change the I2C address of the sensor (HMC5883L_ADDRESS) to 0x30.

      Delete
  3. I am having the same issue where the address comes up as 0x30 and sensor values do not change. I have tried what @David Such has suggested, changing the i2c address to 0x30 within the library (this library: https://www.arduino.cc/reference/en/libraries/grove-3-axis-digital-compass-hmc5883l/) but it has unfortunately made no difference. My module was also form Jaycar.

    ReplyDelete
    Replies
    1. Hi @Justin - can you have a look on the board and see if the sensor is still a HMC5883L? Its possible that they have changed the sensor type. The good news is that you can detect a device on the I2C bus.

      Delete
    2. I'll see if I can get one of the new boards myself today and work out what has changed. This is obviously a common problem.

      Delete
    3. I've worked out part of the problem - the new module is very different to the one I bought back in 2015. Even though the Jaycar model number is unchanged, the new breakout board has different parts. I suspect it is using a clone of the Honeywell magnetometer chip which is why the I2C address is different. I'll see if I can get it working and then do a write up on it.

      Delete
    4. Awesome, im eager to see what you find.

      Delete
    5. Ok I've worked it out! It looks like after 2021 the Duinotech 3-axis compass started using the Memsic MMC5883MA instead of the Honeywell HMC5883L. I've moved most of my writing to Medium these days, and I've done a full explanation there - https://reefwing.medium.com/connecting-the-duinotech-3-axis-compass-to-an-arduino-b13c28d7d936

      Delete