building a better compass

Several projects on my bench are waiting for me to create a high quality compass. I tried earlier with some rat shack parts but have since picked up a pair of GY-80 so everything is on one package. (3/comp, 3/accel, 3/gyro, 1/pressure)

I FINALLY got the tilt compensation working last night. While the guides I found online contained examples of implementing the formula, they were all very light on the nature of the sensor data, including orientation, sign, and range. Having passed the hurdle, I intend to write a library that allows for easy identification of arbitrary compass and tilt hardware and orientations. (I'll look into kalman filtering at a later time)

Before I get into that however, I would like to make sure I am making the most accurate use of the sensor data. And that brings me to calibration. The compass and the accelerometer have similar but separate problems.

The accelerometer provides an integer in the range ~ -270 - +255 for the x and the y axis. Problem 1: is 0,0 level? Problem 2: are -270 and +255 actualy the same magnitude? (-90 / +90 deg, or at least, are they equal opposites?) Right now I don't have any simple way to put the board precisely level or at any well-calibrated angle. I'd like to assume one or the other though. Currently my code is assuming 0,0 is always level, and is scaling the outputs separately to produce a range of +/- 230. (-270 and +255 are used to scale the negative and positive offsets separately) Another strategy I am considering is to assume that 0,0 is NOT necessarily level, but that -270 nd +255 ARE equal magnitudes, and use that to redefine level (in that case, at -7.5) Comments?

The compass could have the same issue of zeroing, but in its case I'm aware there will be a much greater variance in field strength generated, as the numbers are only meaningful when compared relative to each other to provide an angle. But the zeroing question remains, is a reading of 0 exactly 90 degrees off from magnetic axis? I assume in this case I can't simply add a zeroing bias, but have to convert to an angle and then add to that instead. But again I really have no easy way to provide it with a "perfect north" fixture to mesure to see how far it's off. Comments?

Lastly, I've got several bits of hardare here, I'm sure they vary in quality. Anyone care to toss their hat into the ring and praise or bash on the quality of some of the available accelerometers and gyros?

I toyed with gy-80 in past, after messing with various drivers I found out there is multiwii firmware for arduino (atmega328p) which worked fine with the module, the detailed GUI allowed some calibration as well.

Other than that I found only one single driver where the calibration worked somehow - search for HMC5843_basic.pde by Fabio Varesano.

The hmc5883l is quite sensitive sensor, so messing with it inside a room would most probably not show you where the north is, also any metallic objects, even small one, in sensor's vicinity will mess the readings..

Yep I have definitely ran into near-field effects when testing it. Nearby metal, directon of USB cable from board, magnets anywhere near the unit, etc. There's a long screw that helps hold the side panel of my wooden desk to the top that has gotten me on several occasions recently.

One other thing I wanted to add to the above: the maximum magnitudes are ALL different. The line that defines the maximum ranges (minus one or two) of each of the three accelerometers is:
Heading.AccelSetCal(-251,271,-257,270,-265,240);

And I see a similar variance in the x/y/z compass's field strength range limits. Everything is different.

My current plan is to put seeral calibration functions into my library. The first group will simply be to determine physical orientation of the sensors, relative to installation and relative to each other. And at the same time establish polarity. Next will be to determine the maximums. The user should be able to note these values from serial, and update a .h file in the library folder to import (via #define) these calibrations so they are available for all sketches.

I have two of these units I will compare this evening, and see if they actually have the same calibration, it's possible I suppose. But I'd expect there to be differences, and not be possible to simply use a "pre-calibrated" library. But to be fair, these calibrations may not be meaningful. Here's one other wrinkle I ran into which surprised me that so many missed it:

Of all the sources I looked at (close to a dozen), all but ONE did a proportional conversion between the sensor reading (in milli-gs) to degrees. Since the g force magnitude changes by 50% at 60 degrees instead of 45, and has VERY non-linear behavior near 0 and 90, I was surprised those other people's code were working. (you have to pass the scaled -1 to +1 g force through asin to straighten out the response curve, though that one library used a rather short table….) Eiter that or my accelerometer is an "oddball", outputting actual g's that aren't pre-adjusted for asin? I found one unit in Parallax's archive that is out of production, that included both a compass and an accelerometer, and processed the adjustment onboard, supplying a pre-corrected value… I wonder why on earth they stopped making that with no replacement?

(and if anyone has any easy code for the kalman filter, I'd love to see it)

My favorite procedure for calibration of both the accelerometers and magnetometers is discussed in detail here: Sailboat Instruments: Improved magnetometer calibration (Part 1)

It is important that the sensor be held as still as possible when each accelerometer measurement is made.

yep I did notice that any shock or bumping while trying to determine maximum ranges produced spikes in the maxima. I will definitely watch for and factor that into the calibration functions I write.

Part of my issue is I don't really have any good way to perfectly level it, so I'm hoping that EITHER the maximums OR the centering is calibrated from the factory for the accelerometer anyway.

You should not attempt to level the compass. In the procedure I linked, it is important that as many different 3D orientations as possible be included in the calibration.

yup I intend to give it the 360 on all axis. My intention is to exercise the compass so that it "sees" the absolute maximum values possible at both ends of the range, for all three compasses. Since I don't think anyone has a good way to align all three magnetometers to a perfect North, I hope we can assume that the compass's outer ranges are opposite equivelents. In other words, if one compass's readings can vary between +1410 and -1525, that we can assume that exactly in between those two points is the center (where the compass is precisely 90 degrees between north and south)

For the compass, the gauss changes with conditions. This is quite different than the accelerometer, which should always be able to achieve the same range of readings since conditions don't affect gravitometers unless you're leaving on a rocket :wink: For THOSE, knowing the range of readings may either be useful for zeroing (similar to the compass) for finding level, OR may be simply useful for scaling to +/- 90 degrees pitch or roll.

Right now I'd like to know if 0,0 is calibrated for level on my accelerometer. A lot of people are saying I need to calibrate it, and I know this, but it's a question of what needs calibrating… I know I have to normalize the min/max so I end up with +/- 90 degrees, but does that mean separately scaling the + and the - readings and assuming 0 is level, or do I also have to figure out what level is? (and then possbily not have to have a separate scale value for + as for -)

Why not spend a few moments looking at the material here? Sailboat Instruments: Improved magnetometer calibration (Part 1)

ummm, that looks like the link you posted earliler? (unless you mean I overlooked something discussed in my last post, in which case can you be my cpt obv?)