I would appreciate some assistance with developing some code that is capable of using a MicroMag3 magneto to provide a tilt compensated heading. I have searched these forums and the net; however, I have been unable to get this to work.
My understanding is that to calculate the heading the following formulas should be used:
So far, I am only able to get a heading when the device is level. My tilt values also seem accurate.
My X and Y values have been calibrated, however I am unsure on how to use the Z value, do you just use the raw sampled value? I find that tilt is sometimes compensated when the magneto is pointing in certain directions and the tilt is one way. I have played about with the roll and pitch values such that they range from 0 to 360, as well as 0 to +/- 180.
Does anyone have sample code? This is driving me crazy!
Also this is my first post and I’d just like to say I think sparkfun is great, though I think I’m getting addicted to buying new parts!
I can see one error I’ve made, my calculation for roll and pitch assumed that roll was in relation the the pitch plane, rather than the ground (if that makes sense).
Though, I’ve changed this now, but still no joy
Oh and should "Actual Roll= arcsin(Y/(G*cos(pitch)) " this have read "Actual Roll= arcsin(Y/G * (cos(pitch))
My MicroMag3 has an arrow on it pointing in a direction, is this the pitch plane?
Make sure the mag3’s x-axis & y-axis are parallell with the axis of the device you use to measure gravity. What device is your mag3 connected to and what languge do you write in? Mine is connected to an atmega128 and I use the Bascom compiler. In Bascom you can only have one calculation per line, I’ll give you my code, hopefully it will make sense.
The following variables are used:
Magx,Magy,Magz readings from Mag3 (defined as integer).
Magxm,Magym,Magzm modified readings from Mag3 (defined as integer).
Isx,Isy,Isz readings from inertial sensor (defined as integer).
Gtot,Roll,Pitch,Tmp,Tmp1,Maghead defined as singles.
Calculate Roll & Pitch:
Gtot = Isx * Isx
Tmp = Isy * Isy
Gtot = Gtot + Tmp
Tmp = Isz * Isz
Gtot = Gtot + Tmp
Gtot = Sqr(Gtot)
Pitch = Isx / Gtot
Pitch = -Asin(pitch)
Tmp = Cos(pitch)
Tmp = Tmp * Gtot
Tmp = Isy / Tmp
Roll = Asin(Tmp)
Calculate modified magnetic x & y and heading:
Tmp = Magx * Cos(Pitch)
Tmp1= Magy * Sin(Roll)
Tmp1 = Tmp1 * Sin(Pitch)
Tmp = Tmp + Tmp1
Tmp1 = Magz * Cos(Roll)
Tmp1 = Tmp1 * Sin(pitch)
Magxm = Tmp - Tmp1
Tmp = Magy * Cos(Roll)
Tmp1 = Magz * Sin(Roll)
Magym = Tmp + Tmp1
Maghead = Magym / Magxm
Maghead = Atn(maghead)
Maghead = Rad2deg(maghead)
Maghead = Abs(maghead)
If Magxm >= 0 And Magym >= 0 Then Maghead = 180 - Maghead
If Magxm >= 0 And Magym < 0 Then Maghead = Maghead + 180
If Magxm < 0 And Magym < 0 Then Maghead = 360 - Maghead
Thanks for your answer. Could you also tell me what raw values should i expect for each axis? I get something from the spi but it’s pretty strange… i mean i only get values from +80 to +110…
I’m assuming that lsb and msb are 8-bit variables. Some C compilers will perform all math on 8-bit values at only 8-bit resolution, causing a loss of bits when a left shift or multiplication is done. This is actually a violation of the C specification, but following the spec would lead to poor performance on 8-bit microcontrollers. Casting one of the values to the size of the desired result will fix this.
I’ve tried that and it still doesn’t work… I found a small bug and fixed it and now i can get values for each axis between -20 to +20.
Robert, I could really use to know what values i should expect from the micromag during normal operation. I think that the values i’m getting are way too small. If i put a strong magnet close to it it goes up to 320-350. I think it should go up to 32768…
Another strange thing is that msb is either 0 or 255 and lsb varies from 0 to 255.
If Magxm >= 0 And Magym >= 0 Then Maghead = 180 - Maghead
If Magxm >= 0 And Magym < 0 Then Maghead = Maghead + 180
If Magxm < 0 And Magym < 0 Then Maghead = 360 - Maghead
Clear as mud?
TTFN
Robert
I am following Roberts example to get a tilt compensated heading from the Micromag3. I am not sure about a couple of things and hope someone is still around to help. I have a calibration routine where I rotate the Mag3 360 degrees while on a flat surface. From that I get the max and min values of the x and y axis. As the ranges of each axis are slightly different I work out a scale factor and then work out an offset to center the ranges. So now I have eg, -1400 to +1400 for both x and y axis. Without looking at the tilt yet, I can use these values to get a heading. So now I am looking at incorporating the tilt part of the formulas but I am unsure about the z axis readings from the Mag3. Should I treat it similarly in the calibration, ie work out a scale factor and an offset so it's range is the same as the x and y axis? I'd have to tilt the micromag 90 degrees and rotate it to do that, but then if I do this the x and y readings go outside the original calibration range. Any thoughts?
Edit: I found another device that does a similar thing and they roll the device 90 degrees and rotate it 360 degrees to calibrate the z axis. I have tried this, but regardless of what I do with the z axis I am only getting a tilt compensated reading if I tilt it one direction only, towards the south. Tilting it any other direction and the heading swings a lot. If anyone can help I would greatly appreciate it.
Finally got it working. I was using different formulas to calculate pitch and roll, so I thought I better try Robert’s way and see if it makes a difference. And it did. Thanks for the code Robert
Hi probebly some one ellse willhave the same problem as me.
So if you get to small values you have change the period Select to a larger value. if you only still think you get the hige byte try with a magnet and try overflow it.