I’ve bought recently some cheap dual axis magnetic sensors at SureElectronics (http://www.sureelectronics.net/goods.php?id=944), I’ve tried first to use them as straight compass.

Annoying problem : it’s impossible to accurately compensate the tilt of the sensor without using a gyro sensor. On the other end, if you stay on the same horizontal plan, the measures are pretty accurate even if you consider their low price (6$), I was really surprised. Three axis sensor can simplify the problem but they are more expensive …

Usage of the sensor is pretty simple : the communication is based on I2C and you can read new data 50 times per second. Furthermore, there is a reset command that put the sensor back in its initial state, which is necessary when it has to handle strong magnetic fields.

After a few tries and some code, I was able to get the angle of the compass. For that, I had to calibrate it first to know the minimal and maximal values on each axis. The calibration procedure is easy : I’ve placed the sensor on the edge of my workbench, red the x and y values, then I’ve rotated it by 90°, then 180° and finally 270°. After that, I’ve taken the minimal and maximal values along both axis from the different orientations.

The calibrated values are computed this way :

cal_x=(raw_x-((max_x+min_x)/2))/((max_x-min_x)/2) cal_y=(raw_y-((max_y+min_y)/2))/((max_y-min_y)/2)

The calibrated values varies more or less between -1 and 1, the angle can be determined thanks to some trigonometry :

if (( cal_x ==0) && ( cal_y <0)) angle=PI/2; else if (( cal_x ==0) && ( cal_y >0)) angle=-PI/2; else if (cal_x<0) angle=PI-atan(cal_y/cal_x); else if ((cal_x>0) && (cal_y<0)) angle=-atan( cal_y/cal_x ); else if (( cal_x >0) && ( cal_y >0)) angle=(2*PI)-atan( cal_y/cal_x );

While playing with some magnets borrowed from my fridge, I’ve noticed that the sensor can detect accurately the orientation of the magnet as well as its presence. The sensed values increase strongly but the angle calculus is still totally valid. The magnetic field intensity can be computed like this :

intensity=sqrt(cal_x*cal_x+cal_y*cal_y)

If there is no magnet, the intensity stays under 1.5 (unless I tilt the sensor) and it moves to higher values which depends on the distance between the magnet and the sensor and on the strenght of the magnet. Above a certain threshold, the sensor has to be reset as it gives totally random values. This is not a real problem for my specific usage as there will always be a minimal distance of an inch of wood between the sensor and the magnet, I just have to avoid strong magnets.

But there is a small data stability issue when you stay on the same orientation. To reduce that jitter, I’ve dampened the data depending on their variation : if the offset between the previous read and the new one is small, the data is slightly taken into account, on the other hand, if the offset is bigger, the data has more weight. This has the advantage of stabilyzing the data while ensuring a good reactivity when bigger changes are done.

Read more: Hidden light control using Arduino