In Mobiltelefonen und anderen Geräten, die einen elektronischen 3-Achsen-Kompass verwenden, wird eine ∞/8/S-förmige Bewegung verwendet, um das Magnetometer zu kalibrieren, wie in diesen Videos gezeigt .
Warum wird diese Bewegung ausgeführt, was ist die Theorie, und kann jemand einen Beispiel-C-Code geben, um sie zu implementieren?
Sie müssen meine andere ähnliche Frage durchgehen, die weitere Informationen enthält.
Einige zusätzliche Informationen zu dieser speziellen Frage: Die Plattform ist 8-Bit AtMega32 und verwendet AVR Studio 5.
Bis jetzt habe ich es versucht: Ich habe versucht, den Durchschnitt der Vektorwerte des Magnetometers, der die Form macht, durch 2 zu teilen. Nachdenken kann bei der Berechnung von Offsets helfen. Ich denke, dass die beiden identischen Teile / Seiten der Form das Magnetfeld der Erde aufheben und die Offset-Werte ausgeben. Ich könnte falsch liegen. Aber speziell für die formbasierte Kalibrierung bin ich hier gerade. Ich denke, die Kalibrierung funktioniert so. Die Idee ist herauszufinden, ob das so funktioniert?
Ok, der Code, mit dem ich die Offsets berechnen und später einfach vom rohen magnetischen 3D-Vektor subtrahieren kann. Ich könnte völlig falsch liegen und habe keine Erklärung, wie es funktioniert. Nach dem Video und den auf der Kugel aufgetragenen Daten zu sehen, hat irgendwie meinen Gedanken beschleunigt und ich habe diesen Gedanken in Form einer Gleichung verwendet. B)
Code:
Die Funktionen Read_accl();
und Read_magnato(1);
lesen die Sensordaten aus. Ich hoffe der Code ist selbsterklärend. In der Hoffnung, dass kluge Leute dies sicherlich auf viel bessere Weise nutzen werden. :\
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;
}
}
}
Nachdem ich diese Offsets erhalten hatte, verwendete ich sie wie folgt:
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 ;
...
}
Wie ich erwähnt habe.
Das 8/S-förmige Muster wird verwendet, um Magnetometer in Mobiltelefonen und anderen Geräten zu kalibrieren.
Hintergrund
Typische Magnetometer aus der Handyzeit messen die magnetische Feldstärke entlang dreier orthogonaler Achsen, z. B.:
Mit der Größe des Feldes gegeben durch
und der Rotationswinkel von jeder Achse als
Kalibrierung
Da das Magnetfeld der Erde relativ konstant ist, sollte die Größe des vom Magnetometer gemessenen as-Feldes auch konstant sein, unabhängig von der Ausrichtung des Sensors. dh wenn man den Sensor herumdreht und zeichnet , , und in 3D sollten die Pfade die Oberfläche einer Kugel mit konstantem Radius darstellen.
Idealerweise sollte es so aussehen:
Aufgrund von Hart- und Weicheiseneffekten und anderen Verzerrungen sieht es jedoch am Ende wie eine deformierte Kugel aus:
Dies liegt daran, dass sich die vom Sensor gemessene Größe des Magnetfelds mit der Ausrichtung ändert. Das Ergebnis ist, dass die Richtung des Magnetfelds, wenn es nach den obigen Formeln berechnet wird, von der wahren Richtung abweicht.
Eine Kalibrierung muss durchgeführt werden, um jeden der drei Achsenmesswerte so anzupassen, dass die Größe unabhängig von der Ausrichtung konstant ist – Sie können sich das so vorstellen, als ob die deformierte Kugel zu einer perfekten Kugel verzerrt werden muss. Der LSM303- Anwendungshinweis enthält viele detaillierte Anweisungen dazu.
Was ist also mit dem Muster der Figur 8!?
Wenn Sie das Muster der Figur 8 ausführen, wird ein Teil der darüber liegenden verformten Kugel „nachgezeichnet“. Aus den erhaltenen Koordinaten kann die Deformation der Kugel abgeschätzt und die Kalibrierungskoeffizienten erhalten werden. Ein gutes Muster ist eines, das den größten Orientierungsbereich durchläuft und daher die größte Abweichung von der wahren konstanten Größe schätzt.
Um die Form der verformten Kugel abzuschätzen , kann eine Ellipsenanpassung nach der Methode der kleinsten Quadrate verwendet werden. Auch hierzu gibt der LSM303 Application Note Hinweise.
Eine einfache Methode für eine Grundkalibrierung
Wenn Sie keine Weicheisenverzerrung annehmen, wird die deformierte Kugel laut App-Hinweis nicht gekippt. Daher kann eine einfache Methode für eine Grundkalibrierung möglich sein:
Dies basiert auf dem hier gefundenen Code.
Lösen mit der Methode der kleinsten Quadrate
Der MATLAB-Code zum Lösen mit der Methode der kleinsten Quadrate ist unten dargestellt. Der Code geht von einer Variablen aus, mag
bei der die Spalten die xyz-Werte sind.
H = [mag(:,1), mag(:,2), mag(:,3), - mag(:,2).^2, - mag(:,3).^2, ones(size(mag(:,1)))];
w = mag(:,1).^2;
X = (H'*H)\H'*w;
offX = X(1)/2;
offY = X(2)/(2*X(4));
offZ = X(3)/(2*X(5));
temp = X(6) + offX^2 + X(4)*offY^2 + X(5)*offZ^2;
scaleX = sqrt(temp);
scaleY = sqrt(temp / X(4));
scaleZ= sqrt(temp / X(5));
Um eine dynamische Achterkalibrierung durchzuführen, könnten Sie die Routine der kleinsten Quadrate bei jedem neuen Messwert ausführen und beenden, wenn sich die Offset- und Skalierungsfaktoren stabilisiert haben.
Das Magnetfeld der Erde
Beachten Sie, dass das Magnetfeld der Erde normalerweise nicht parallel zur Oberfläche verläuft und es möglicherweise eine große nach unten gerichtete Komponente gibt.
Kellenjb
geometrisch
Rick2047
Rick2047
Rick2047
Rick2047
Kellenjb
geometrisch
Chris Stratton
geometrisch
Rick2047
Kortuk
geometrisch
Rick2047
geometrisch
Rick2047
geometrisch
Rick2047
if (ProcessStarted==1 || ProcessStarted==2) { 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++; }
sollte funktionieren?