W telefonach komórkowych i innych urządzeniach korzystających z 3-osiowego kompasu elektronicznego do kalibracji magnetometru służy ruch w kształcie ∞ / 8 / S, jak pokazano na tych filmach .
Dlaczego ten ruch jest wykonywany, jaka jest teoria i czy ktoś może podać przykładowy kod C, aby go zaimplementować?
Musisz przejść przez moje kolejne podobne pytanie zawierające więcej informacji.
Kilka dodatkowych informacji na temat tego konkretnego pytania: Platforma to 8-bitowy AtMega32, korzystający z AVR Studio 5.
Do tej pory próbowałem: próbowałem podzielić średnią przez 2 wartości wektorowe magnetometru tworzącego kształt. Myślenie może pomóc w obliczaniu przesunięć. Myślę, że niektóre z dwóch identycznych części / boków kształtu niwelują pole magnetyczne ziemi i podają wartości przesunięcia. Mogę się mylić. Ale szczególnie w przypadku kalibracji opartej na kształcie właśnie tu jestem. Myślę, że kalibracja działa w ten sposób. Chodzi o to, aby dowiedzieć się, czy to działa w ten sposób?
Ok kod, za pomocą którego mogę obliczyć przesunięcia, a później po prostu odjąć je od surowego wektora magnetycznego 3D. Mogę się całkowicie mylić i nie mam wyjaśnienia, jak to działa. Widząc wideo i dane wykreślone na kuli, jakoś przyspieszyło moją myśl i wykorzystałem ją w formie równania. B)
Kod:
Funkcje Read_accl();
i Read_magnato(1);
odczytują dane czujnika. Mam nadzieję, że kod jest zrozumiały. Mam nadzieję, że mądry ppl z pewnością użyje tego na znacznie lepsze sposoby. : \
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;
}
}
}
Po uzyskaniu tych przesunięć użyłem ich w następujący sposób:
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 ;
...
}
Jak wspomniałem.