[There is now a better method for removing offsets in flight. See this discussion. - WJP]

The picture shows a UAV DevBoard connected to Jordi's magnetometer breakout board.

First, since my discussions tend to get long winded, if you want to "cut to the chase", you might want to read this.

I recently integrated Jordi's HMC5843 magnetometer breakout board with the UAV DevBoard (UDB).

Jordi's board is really great, having the onboard bidirectional level shifters and builtin pullup resistors made it possible to simply connect Jordi's board directly to the I2C pins in the programming connector. Thank you very much, Jordi.

So, heli and quadcopter pilots who are using the UDB would do well to buy Jordi's board, my plan is to integrate it into the heli firmware that is being developed for the UDB. There is now a magnetometer demo and instructions for the UDB.

But that is all besides the point of this discussion....

Along the way to implementing the magnetometer demo, I realized the hardest part was going to be determining the offsets of the magnetometer. The integration of the magnetometer itself into the DCM algorithm was trivial, but what to do about the offsets?

The HMC5843 has a self calibration feature, so you can determine the gains just fine. But the first magnetometer I bought had rather large offsets. So I bought 3 more (1 more from Jordi, and 2 more from Sparkfun). It turned out that all 4 units had some offsets. Even if they did not have offsets, it would still be possible for stray magnetic fields in the aircraft to create offsets.

So, some sort of procedure is needed to null the offsets.

I thought of several manual ways to do that, and I read several postings on the subject....

Then I wondered if there might be some way to use the direction cosine matrix to automatically compute the offsets in flight. And there is....even for dynamically changing offsets, such as from power leads to the motors...

The basic idea is the following...

When the aircraft is rotating, the offset fields rotate with the aircraft, while the earth's magnetic field is stationary. So it should be possible to use the direction cosines to separate the two fields.

The basis of the idea is the same as flipping the magnetometer exactly 180 degrees along one of the axis and averaging the two readings. The result is the offset.

The idea can be extended to rotations other than 180 degrees, even small rotations, by using the direction cosine matrix and some vector algebra.

The resulting theory and implementation is described here, and it has been tested. It works rather well.

It was interesting to watch the computations of the offsets during the tests. A few random turns along a couple of the axes was all that was needed to compute the offsets. So, you can either null the offsets prior to takeoff by rotating your aircraft a bit, or simply let it happen automatically during the first few turns of the flight.

It was also interesting to see what would happen if I deliberately manually set the offsets to the wrong values, they would quickly reset to the correct values after a few turns.

The bottom line is that now both the calibration and the nulling of offsets can be done completely automatically, without any manual operations or entry of measurements. It is possible to extend any DCM-based IMU, such as the ArduIMU, to use this method to simplify the integration of a magnetometer.

Best regards,
Bill

Tags: DCM, DevBoard, UAV, magnetometer

Views: 3268

Reply to This

Replies to This Discussion

Hello Jean-Louis,
Super, it is necessary to keep this solution of breakdown service, useful for all the users of the magnetometer.
Regard
DODY

Hi everyone,

 

I am getting a BUILD FAILED error when trying to build the demo project to program it to the devboard.  I was able to run the roll/pitch/yaw demo fine, so I don't know why I'm getting an error now.  Here is the error message:

-------------------------------------------------------------------------------------------------------------------------

Program Memory  [Origin = 0x100, Length = 0x7f00]

section                    address   length (PC units)   length (bytes) (dec)
-------                    -------   -----------------   --------------------
.text                        0x100              0x23d8          0x35c4  (13764)
.const                      0x24d8               0x2ca           0x42f  (1071)
.text                       0x27a2               0xa6c           0xfa2  (4002)
.dinit                      0x320e               0x414           0x61e  (1566)
.text                       0x3622              0x21e2          0x32d3  (13011)
.isr                        0x5804                 0x2             0x3  (3)

Total program memory used (bytes):         0x8289  (33417) 68%


Data Memory  [Origin = 0x800, Length = 0x800]

section                    address      alignment gaps    total length  (dec)
-------                    -------      --------------    -------------------
.nbss                        0x800                   0           0x102  (258)
.ndata                       0x902                   0            0x94  (148)
.nbss                        0x996                   0            0x90  (144)
.ndata                       0xa26                   0            0x3c  (60)
.nbss                        0xa62                   0            0x92  (146)
.ndata                       0xaf4                   0            0x2a  (42)
.nbss                        0xb1e                   0            0x24  (36)
.ndata                       0xb42                   0            0x4a  (74)
.nbss                        0xb8c                   0             0xc  (12)
.ndata                       0xb98                   0            0x10  (16)
.nbss                        0xba8                   0             0xc  (12)
.ndata                       0xbb4                   0             0x2  (2)
.data                        0xbb6                   0           0x330  (816)
.dconst                      0xee6                   0            0x2a  (42)
.bss                         0xf10                   0            0x18  (24)
.data                        0xf28                   0             0x2  (2)

Total data memory used (bytes):          0x72a  (1834) 89%


Dynamic Memory Usage

region                     address                      maximum length  (dec)
------                     -------                      ---------------------
heap                             0                                   0  (0)
stack                        0xf2a                                0xd6  (214)

Maximum dynamic memory (bytes):           0xd6  (214)

c:/program files/microchip/mplabc30/v3.25/bin/bin/../../lib\libc-coff.a(vsnprintf.o)(.libc.vsnprintf+0x1e):fake: undefined reference to `assert'
c:/program files/microchip/mplabc30/v3.25/bin/bin/../../lib\libc-coff.a(vsnprintf.o)(.libc.vsnprintf+0x22):fake: undefined reference to `alloc'
Link step failed.
----------------------------------------------------------------------
Release build of project `C:\Documents and Settings\Administrator\Desktop\UAV\magnetometer\Magnetometer\MagnetometerDemo.mcp' failed.
Language tool versions: pic30-as.exe v3.25, pic30-gcc.exe v3.25, pic30-ld.exe v3.25, pic30-ar.exe v3.25
Wed Dec 22 12:54:57 2010
----------------------------------------------------------------------
BUILD FAILED

 

-------------------------------------------------------------------------------------------------------------------------

 

I am a beginner, so please bear with me.  If anyone can help, it would be greatly appreciated.

 

Thanks,

-Paul

Hi Paul,

 

This problem has been reported a couple of times. Most users have not had any trouble, only a few have reported it. It has something to do with the linker and the library code for the vsnprintf function.

 

I suggest you repost your question on the uavdevboard group, there may be someone there who can help you. In fact, someone recently posted a similar question.

 

The code compiles and links ok on my computer, so I am not sure what is going on.

 

By the way, the demo code only runs on the "green-board" and the "red-board", it does not work on the newest board, the "UDB3", which has the flat-mounted Invensense gyros. If you have the newer board, and want to use the magnetometer in conjunction with MatrixPilot, you should use a recent release of MatrixPilot.

 

Best regards,

Bill

Hi Bill,

I read your paper on DCM yesterday and today, and I started to understand a bit of how DCM works. Although I  did not understand everything, i think I caught the idea. You use a PI loop for the correction of the three component vectors of the plane seen from the earth frame that automatically corrects for all kind of offsets like wind and gyro drift etc. A cute idea. But rather intensive computationally-wise.

My idea is to use three complimentary filters that will also free me of gyro drift and saturation problems.

I have a 3axis HMC5843, 3 axis gyro and 3 axis accel. If I compensate the HMC with roll and pitch from the accel, I have a heading in earth frame. Right?

Now if I want to fuse this heading with my yaw gyro angle, I would need to tranform the gyro angle into the earth frame. Can you help me explaining how to do that?

Thanks! Andreas

 

Hi Andreas,

Integration of the magnetometer data into your computations is rather easy if you maintain the 9 elements of the direction cosine matrix (DCM):

1. Use the DCM to transform the body frame magnetometer 3D vector into the earth frame.

2. Throw away the Z component of the magnetic field in the earth frame. Take the cross product of the measured X and Y magnetic field components in the earth frame with X and Y magnetic field that should be present in the earth frame. This will give you a yaw error in the earth frame that is a vector in the Z direction.

3. Transform the earth frame Z yaw magnetic error back into the body frame of reference, using the DCM.

4. Use the 3D yaw magnetic error vector in the body frame any way you want to adjust for drift.

 

The transformations of vectors back and forth between body and earth frame of reference is easy to do with DCM, it involves multiplying a matrix times a vector.

 

Best regards,

Bill

 

Thanks, Bill, for your answer.

I don't understand it all. Point 2.: do you mean that I have to take the cross product of the gyro X and Y components in the earth frame with the X and Y components of the magnetic field in the earth frame? Then I would get an error vector which I can use for correction of drift after transposing it into the body frame. If you mean that, I think I can follow.

But as I am dealing with an IMU for a boat, I really only need the gyro yaw angle in the earth frame. That's all. Is there any way to get this angle without computing the DCM?

There may be a way to calculate the yaw angle in the earth frame from the gyros if one has the roll and pitch angles, just the same way as one can calculate the earth frame of the magnetic vectors with the help of the Euler angles.

Thanks for your comment, and my congratulations for the neat code you write!

Andreas

Hi Bill,

I have implemented the Roll/Pitch Error using DCM (smartphone applications)and I am getting very good results (Roll And Pitch)but i have observed one thing that i get no improvement after numerical error correction. Anyhow  now I am implementing yaw error using magnetometer, I have some questions for understanding

1- are you using magnetometer values in micro tesla in magnetic field vector  for calculation or some other scaling conversion.

2- After obtaining magnetic field vector in earth frame of reference, it has been multiplied with declination vector to get magnetic error in earth plane. I am confused at this point because declination angle is difference  angle between the true North and compass North.  How it can be considered as the known horizontal component of the earth's magnetic field. (As cog in GPS/compass is the angle wrt North)

regards

Navigator

Hi Navigator,

1. I am not sure what the units are in MatrixPilot. I use whatever the default gains are for the Honeywell magnetometers. The binary values for the horizontal component are around 400, if that helps. The way things are set up in MatrixPilot, the actual units do not much matter, these days I normalize the magnetic vector to have a fixed value. In other words, I divide the vector by its magnitude.

2. Here is how the magnetic field is used to compensate the gyros: the measured magnetic field is transformed from the body frame to the earth frame using the rotation matrix. The convention for the rotation matrix is that true north is the reference. So, the rotation matrix will transform the magnetic field measurement from the body to the earth frame. The result that comes out will not be aligned to the north, but will be offset by the declination angle. What I do next is to take the cross product of the horizontal component of the measured magnetic field in the earth frame with the horizontal component of the known magnetic field in the earth frame of reference. The known magnetic field is computed from the known declination angle. When the rotation matrix is aligned correctly, the two horizontal magnetic vectors (measured and known) will be parallel, and the cross product will be zero. Both vectors will be rotated from north by the declination angle.

Note that this method is not the same as a tilt-compensated compass. It works no matter what the orientation of the aircraft is, it can even have a pitch angle of 90 degrees.

Best regards,

Bill

Hi Bill,

(Yes, replying in a two-year old thread because I have just found your document on the offset nulling.  I had come to pretty much the same equation but my algebra being as bad as it is I didn't arrive at the final formula for the offset integration, so I'm trying to use yours.)

In the implementation you shift offsetSum to the right, but you shift magFieldEarth to the left, why's that?  I understand the right shift is the implementation of the filter so that rare spikes from the magnetometer don't introduce too much error.  But the left shift will cause the [b21 * b1 + b12 * b2] part to be 4 times too big.  Or am I misreading?

Many thanks

Hi Andrew,

You are right, this is a stale thread. Since then, I came up with a better way to remove magnetometer offsets. Take a look at this discussion.

Best regards,

Bill

RSS

Social Networking

Contests

Season Two of the Trust Time Trial (T3) Contest has now begun. The fourth round is an accuracy round for multicopters, which requires contestants to fly a cube. The deadline is April 14th.

A list of all T3 contests is here

Advertisement

© 2013   Created by Chris Anderson.   Powered by

Badges  |  Report an Issue  |  Terms of Service