Monday 22 June 2015

imu - Magnetometer ∞ shaped calibration


In mobile phones and other devices using a 3-axis electronic compass, a ∞/8/S shaped movement is used to calibrate the magnetometer as shown in these videos.



Why is this movement performed, what is the theory, and can anyone give some example C code to implement it?


You must have to go through my another similar question containing more info.




Some additional info for this particular question: The platform is 8-bit AtMega32, using AVR Studio 5.


Till now I've tried: I tried dividing the average by 2 of vector values of the Magnetometer making the shape. Thinking might help in calculating offsets. I think some how the two identical parts/sides of the shape is cancelling the earth's magnetic field and giving out the offset values. I might be wrong. But particularly for the shape based calibration this is where I am currently. I think the calibration works out this way. The idea is to find out does that work out this way?




Ok the code by which I can calculate the offsets and later simply subtract those from the Raw magnetic 3D vector. I might be totally wrong and have no explanation how it works. Seeing after the video and the data plotted on the sphere, somehow has accelerated my thought and I used that thought on form of equation. B)


Code:


The Read_accl(); and Read_magnato(1); functions are reading the sensor data. I hope the code is self explanatory. Hoping wise ppl will surely be using this in much better ways. :\


void InfinityShapedCallibration()

{
unsigned char ProcessStarted = 0;
unsigned long cnt = 0;

while (1)
{

Read_accl();

// Keep reading Acc data

// Detect Horizontal position
// Detect Upside down position
// Then detect the Horizontal position again.
// Meanwhile an infinity shaped movement will be created.
// Sum up all the data, divide by the count, divide by 2 .
// !We've offsets.

if (ProcessStarted!=3)
{
//

//USART_Transmit_String("\r");
//rprintfFloat(4, g_structAccelerometerData.accx_RAW);
//USART_Transmit_String(",");
//rprintfFloat(4, g_structAccelerometerData.accy_RAW);
//USART_Transmit_String(",");
//rprintfFloat(4, g_structAccelerometerData.accz_RAW);

}



if (
abs( g_structAccelerometerData.accx_RAW) < 100
&& abs(g_structAccelerometerData.accy_RAW) < 100
&& g_structAccelerometerData.accz_RAW < -350
&& ProcessStarted != 2 && ProcessStarted != 3 && ProcessStarted != 1 )
{
ProcessStarted = 1;
}

if (ProcessStarted==1)

{

Read_magnato(1);

structMagnetometerOffsetDataToEEPROM.Off_X += g_structMegnetometerData.magx_RAW;
structMagnetometerOffsetDataToEEPROM.Off_Y += g_structMegnetometerData.magy_RAW;
structMagnetometerOffsetDataToEEPROM.Off_Z += g_structMegnetometerData.magz_RAW;

cnt++;


}
if ( g_structAccelerometerData.accz_RAW > 350
&& ProcessStarted==1)
{
ProcessStarted = 2;
}

if ( g_structAccelerometerData.accz_RAW < -350
&& ProcessStarted == 2 )
{

ProcessStarted=3;
structMagnetometerOffsetDataToEEPROM.Off_X /= cnt;
structMagnetometerOffsetDataToEEPROM.Off_X /= 2;

structMagnetometerOffsetDataToEEPROM.Off_Y /= cnt;
structMagnetometerOffsetDataToEEPROM.Off_Y /= 2;

structMagnetometerOffsetDataToEEPROM.Off_Z /= cnt;
structMagnetometerOffsetDataToEEPROM.Off_Z /= 2;


UpdateOFFSETDATAinEEPROM();

break;

}
}
}

After getting these offsets I used them as follows:


void main()

{
...

Read_magnato(1);
g_structMegnetometerData.magx_RAW -= structMagnetometerOffsetDataToEEPROM.Off_X ;
g_structMegnetometerData.magy_RAW -= structMagnetometerOffsetDataToEEPROM.Off_Y ;
g_structMegnetometerData.magz_RAW -= structMagnetometerOffsetDataToEEPROM.Off_Z ;
...
}


As I mentioned.




No comments:

Post a Comment

arduino - Can I use TI&#39;s cc2541 BLE as micro controller to perform operations/ processing instead of ATmega328P AU to save cost?

I am using arduino pro mini (which contains Atmega328p AU ) along with cc2541(HM-10) to process and transfer data over BLE to smartphone. I...