EDIT: Solved, by changing the following in this file: AP_Compass_HMC5843.cpp

change this line (274): cal[2] > 0.7f && cal[2] < 1.3f) {

to this:                       cal[2] > 0.7f && cal[2] < 1.35f) {

(Issue reported here: (thx James)

I bought a HMC5883L external compass and installed it on my APM2.5, v3.0.1 equipped quad, cutting the trace on the board as required and mounting it raised above the frame. Seemed to work OK but I noticed that on occasion the toiletbowling and erratic Loiter was still present.

Anyway to cut a long story short, my compass is technically functioning all the time while APM is booted, as evidenced by slight but constantly fluctuating Mx, My, Mz and Mag Field Strength values consistent with the behaviour of an electronic compass.

The weird thing is that sometimes the APM sees those values and updates the yaw heading in conjunction with the inertial navigation system and shows the correct heading on start-up. Loiter works great and all is well. More often than not though, the APM ignores these working valid compass values and shows only the inertial navigational yaw output, heading is zero degrees on start-up and Loiter is useless.

There is no pattern as to when or why this happens.

The graphs below shows the two times when I was able to log the problem. In both cases I detached the magnetometer from the frame and secured it independently, then, first I rotated the APM and frame while keeping the magnetometer stationary and in the second instance I rotated the magnetometer while keeping the APM and frame stationary. The first graph clearly shows the compass rotating but APM doesn't register it. The second is the opposite.

I have cleaned any flux off the boards and triple checked all the connections, visually and electrically, I didn't have a I2C plug so I have carefully soldered the 4 wire cable onto the I2C pins on the back of the board and there's a 4 pin header on the magnetometer side. The compass check shows no issues when the APM "sees" the compass and a "compass not initialized" error when it doesn't.

I have ordered another mag but it will take two weeks to arrive, in the meantime I fear that the new one might exhibit the same problem especially if the problem is not actually with the mag but with the APM or something else hence this appeal for some insight into this problem now.


APM does not "see" the changing magetometer Y value:



APM "sees" the changing Y value and updates the heading accordingly:


APM 'sees' Mag TLOG

APM doesn't 'see' Mag TLOG

You need to be a member of diydrones to add comments!

Join diydrones

Email me when people reply –


  • Hi,

    I have bought a non 3dr compass module said to be hmc5883L but I notice it dies not have the 'translator' fitted to the 3dr module?   I hope this will work direct into the I2C port on the APM.

    What does the translator do?

    Or do we have to use the 3dr board?



    • John,

      This is an old thread. People may not monitor it much.

      I suggest you start a new thread. Or actually I recommend you just post it on the main 3.1 release thread to get help because odd questions like this don't draw much attention as far as I have experienced.

      I once posted a question (using a new thread) about an external compass. Didn't get a single reply...

      With this said, I too bought a non-3DR external compass (HMC5883L) several weeks ago but didn't get a chance to use it yet. 

      I got something like this

      I wonder what you got...

  • Moderator

    Hi James, don't know if you saw Randy's comments in the issue you posted but maybe you'll see this note.


  • Developer

    Ok, so after a little chasing from Graham, I've looked into this issue and there are a few theories about why people are having problems:

    1. the limits checking on the calibration numbers (i.e. >0.7f && <1.3f) are too tight and we should increase the upper limit to 1.35f.  This is super easy and those limits are a bit arbitrary anyway.
    2. some users have a blown 3.3V regulator and this is messing up the calibration.  Could people here with this problem please test their 3.3V lines are actually only 3.3V?  By the way, there is a wider discussion of the 3.3V regulator issue here.  Please be careful not to short out the pins when you do this test!
    3. the calibration routine doesn't match the datasheet (look for "Self Test" on page 2) causing some good compass to fail and some bad ones to pass.   In particular the expected length of the compass vector for x & y axis should be the same.  This difference from the datasheet was done on purpose (commit here).  I've double checked it just now (although not super thoroughly) and it seems the current method produces a more consistent mag field that if we were to follow the datasheet.  The way I tested was I made the proposed change to expect the same length from the x and y axis..I then re-did the compass calibration, then tested the magnetic field length with the APM pointing north, east, south and west.  The magfield length was more consistent with the current code than with the modified code.  The lenght stayed within about 3% with the current code but diverged by about 10% with the proposed code (i.e. code that matched the datasheet).

        So basically I'm proposing #1 and I think that'll fix the problem.  Thoughts?


  • Hi Graham, James just summarized what had happened here. I have a better understanding of your issue now.

    Your issue has been solved maybe but you still have another compass on the way (or may be it already arrived).

    I think when you try that compass, there is chance that everything would be alright even when that line left original as 1.3f. Because if I understood correctly each HMC5883L has slightly different self-test output values. In other words, No two are the same exact.

    If I have a similar problem when I make the switch to external mag., I know where to start:)

  • Hi Graham,

    I was following your issue from time to time as I will start using external compass soon. It seems you solved your issue but clearly I didn't understand what the problem was.

    Would you care to tell me briefly what the real issue was please? I am really wondering...


  • Moderator

    I'm getting the following Arduino errors for the compass test?:

    J:\unzipped\ArduCopter-3.0.1\libraries\AP_Compass\AP_Compass_HMC5843.cpp: In member function 'virtual bool AP_Compass_HMC5843::init()':
    J:\unzipped\ArduCopter-3.0.1\libraries\AP_Compass\AP_Compass_HMC5843.cpp:239: error: 'Serial' was not declared in this scope
    J:\unzipped\ArduCopter-3.0.1\libraries\AP_Compass\AP_Compass_HMC5843.cpp:274: error: 'Serial' was not declared in this scope

    Do I need to add another #include or #define?

  • Developer

    I've been reading your posts as well but it does seem very specific to this particular set-up and hardware.  It's likely failing during the compass initialisation, the APM sees that failure and ignores it from then on.  It perhaps continues to read in the values it's providing but because the initialisation failed it means that the compass's configuration might be incorrect so it's best that it ignores it actually.

  • Hi Graham,

    I realise that this must be frustrating for you but in light of the fact that there are many of us now using an external compass without any issues, I suspect that the fault lies in your setup specifically rather than with APM or Arducopter in general. From what I can tell from your description, the compass intermittently fails to initialise. I would suspect: 1. Your external compass is faulty. 2. There is a intermittent connection problem between the external compass and the APM (bad solder joint/broken wire etc). 3. The on board compass is not fully disconnected and is intermittently connecting to the bus and corrupting the data. 

    I have gone over the compass code in an effort to see if anything more can be determined from a failed initialisation. In the file AP_Compass_HMC5843.cpp around line 237 there is a compiler directive to enable/disable some additional output from the initialisation routine. If you alter this line: "#if 0" to be "#if 1" and re-compile the compass test application that I pointed you to last time, you should get additional output at the beginning of the serial stream when the compass is initialised. You may also want to add the following after the line "/* useful for debugging */"

    Serial.print("numAttempts: ");
    Serial.print("good_count: ");

    Also adding this after "_i2c_sem->give();" at approx line 268 (before the above mods) and before the line "return;"

    Serial.println("Failed re-initialisation");

    I have attached the amended file if this is more convenient.

    I have not done a lot of SPI programming (other than tinkering with existing examples) and I am not sure why the code assumes a bad connection and allows for up to 20 attempts (numAttempts) but this might be a useful figure to monitor in your situation. Let me know how you go....

This reply was deleted.