Der HMC5883L- was treibt er?

Hallöle.
Ich hab schon länger hier diesen “Billig-Kompass” herumschwirren und will den nun mal brauchbar ans laufen bekommen.

  1. Das Ding hängt am I2C und funktioniert-auf irgendeine, mir bisher magisch vorkommende, Art und Weise. :astonished:
  2. ausser der Wire-Bücherei benutze ich gar keine- sicher ist sicher. Das enthaltene Beispiel wirft nicht viel gescheites aus, jedenfalls nix, womit ich was anfangen kann.
  3. vorerst lese ich lediglich die Rohdaten aus, und die kommen schön angetuckert, sind aber verwirrend:

Je nachdem, welche Achse ich nach oben halte, ändern sich, wenn ich das Ding um diese drehe, meist gleich zwei Achsen, und zwar ernstzunehmend deutlich (kleinere Schwankungen ignorier ich erst mal).

Hat jemand einen Plan, was man mit diesen Rohdaten anfängt?
Die bekannten Tutorials offenbar nicht, dort wird immer auf (gar nicht, oder nicht besser funktionierende) Bibliotheken verwiesen, die dürfte ich alle durch haben, aber bessere Ergebnisse gabs nie).

Im Grunde möchte ich einfach erreichen, dass ich das Ding ähnlich nem gewöhnlichen Magnetkompass benutzen kann.

/*
An Arduino code example for interfacing with the HMC5883

by: Jordan McConnell
 SparkFun Electronics
 created on: 6/30/11
 license: OSHW 1.0, http://freedomdefined.org/OSHW

Analog input 4 I2C SDA
Analog input 5 I2C SCL
*/

#include <Wire.h> //I2C Arduino Library

#define address 0x1E //0011110b, I2C 7bit address of HMC5883

void setup(){
  //Initialize Serial and I2C communications
  Serial.begin(9600);
  Wire.begin();
  
  //Put the HMC5883 IC into the correct operating mode
  Wire.beginTransmission(address); //open communication with HMC5883
  Wire.write(0x02); //select mode register
  Wire.write(0x00); //continuous measurement mode
  Wire.endTransmission();
}

void loop(){
  
  int x,y,z; //triple axis data

  //Tell the HMC5883 where to begin reading data
  Wire.beginTransmission(address);
  Wire.write(0x03); //select register 3, X MSB register
  Wire.endTransmission();
  
 
 //Read data from each axis, 2 registers per axis
  Wire.requestFrom(address, 6);
  if(6<=Wire.available()){
    x = Wire.read()<<8; //X msb
    x |= Wire.read(); //X lsb
    z = Wire.read()<<8; //Z msb
    z |= Wire.read(); //Z lsb
    y = Wire.read()<<8; //Y msb
    y |= Wire.read(); //Y lsb
  }
  
  //Print out values of each axis
  Serial.print("x: ");
  Serial.print(x);
  Serial.print("  y: ");
  Serial.print(y);
  Serial.print("  z: ");
  Serial.println(z);
  
  delay(250);
}

Nachdem der Beitrag schon älter ist und zwar über 100 mal gelesen, aber nie beantwortet wurde, poste ich einfach mal einen einfachen “Kompass-Code” für diesen Sensor.

Wie bei einem Magnetkompass gilt: Den Sensor absolut waagerecht ausrichten und keine eisenhaltigen Metallteile oder starke Magnetfelder in der Nähe!

Dann ergibt sich die Kompassrichtung alleine aus den x- und y- Anteilen des Erdmagnetfelds.

#include <Wire.h>

#define Addr 0x1E               // 7-bit address of HMC5883 compass

void setup() {
  Serial.begin(9600);
  Serial.println();
  Wire.begin();
  
  // Set operating mode to continuous
  Wire.beginTransmission(Addr); 
  Wire.write(byte(0x02));
  Wire.write(byte(0x00));
  Wire.endTransmission();
}

void loop() {
  int x, y, z;

  // Initiate communications with compass
  Wire.beginTransmission(Addr);
  Wire.write(byte(0x03));       // Send request to X MSB register
  Wire.endTransmission();

  Wire.requestFrom(Addr, 6);    // Request 6 bytes; 2 bytes per axis
  if(Wire.available() <=6) {    // If 6 bytes available
    x = Wire.read() << 8 | Wire.read();
    z = Wire.read() << 8 | Wire.read();
    y = Wire.read() << 8 | Wire.read();
  }
  // If compass module lies flat on the ground with no tilt,
  // just x and y are needed for calculation
  float heading=atan2(-x, y)/0.0174532925;
  if(heading < 0) heading+=360; // N=0/360, E=90, S=180, W=270
  Serial.println(heading);  
  delay(500);
}

Hm- auf die vollen 360 Grad komme ich nur, wenn ich das Modul so neige, dass die y-Achse ca. 45 Grad nach unten zeigt...?
Umgedreht muss ich, um auf die 180 zu kommen, wiederum das Teil um 180Grad um die Z-Achse und um 90 Grad um X neigen.

Bin ich einfach zu doof oder ist da nen Fehler drin?

Rabenauge:
Hm- auf die vollen 360 Grad komme ich nur, wenn ich das Modul so neige, dass die y-Achse ca. 45 Grad nach unten zeigt…?
Umgedreht muss ich, um auf die 180 zu kommen, wiederum das Teil um 180Grad um die Z-Achse und um 90 Grad um X neigen.

Bin ich einfach zu doof oder ist da nen Fehler drin?

Den geposteten Code prüfe ich gleich nochmal, allerdings arbeitet der Code ohne “Kalibrierung” des Sensors und ohne Ausgleich der magnetischen Kompass-Mißweisung.

Die fehlende Kompensation der Kompaß-Mißweisung bewirkt in Deutschland ca. eine Fehlweisung von 2°.

Die fehlende Sensor-Kalibrierung macht vielleicht 8% Achsenwert aus, was zu einem Fehler von 8% auf 90° führen kann, also ca. 7°.

Macht zusammen vielleicht bis hoch zu 10° Richtungsfehler (bei manchen Richtungen). Wenn Du die Kompaßrichtung (Vollkreis= 360°) beim Drehen um die z-Achse (Hochachse) bei flach aufliegendem Sensor nicht auf +/-10° genau angezeigt bekommst, ist da irgendwas anderes faul. Ich tippe auf folgendes in Sensornähe:

  • stromdurchflossene Leiter mit Strömen > 10 mA
  • Magnetfelder (PC-Monitore, Lautsprecher etc.)
  • eisenhaltige Metallteile

Hast Du Deinen HMC5883L vielleicht auf ein Breadboard gesteckt?
Ein Breadboard besteht im Innern nur aus Blech-Kontakten (Eisen!), was jeden Kompass ablenkt!

Prüfe also bitte nochmal genau nach:

  • Wie weit sind stromdurchflossene Leiter entfernt, durch die mehr als 10mA Strom fließen?
  • Wie weit sind Magnetfelder aus PC-Monitoren und Lautsprechern entfernt?
  • Wie weit sind eisenhaltige Teile vom Sensor entfernt?
    Dabei auch “unsichtbares Eisen” berücksichtigen, wie die Blechkontakte im Breadboard!

Für diese drei Dinge gilt: Je weiter weg, desto genauer die Anzeige!
Außerdem muss der Sensor flach aufliegen, die z-Achse genau nach oben, x und y horizontal.

Bekommst Du dann beim Drehen keine Anzeige, die beim Drehen fortlaufend von 0° (Nord) über 90° (Ost), 180° (Süd), 270° (West) bis zu 360°/0° (Nord) hochläuft, also bei einen Richtungswechsel um 90° auch 90° Anzeigewertänderung mit meinem Sketch?

Edit/Nachtrag: Den von mir geposteten Code habe ich gerade nochmal getestet und konnte keine Fehler entdecken, der Code funktioniert bei mir einwandfrei. Um sicherzugehen, dass sich die Spannung am I2C-Bus ausreichend stabilisiert hat, nachdem die Wire-Library aktiviert wurde, kannst Du zur Sicherheit aber nochmal ein kleines delay von einigen Millisekunden nach wire.begin einfügen:

  Wire.begin();
  delay(10);

Hast Du auf Deiner Platine auch mal überprüft, ob Du wirklich den “L” Sensor hast? Der müßte dann auf der Gehäuseoberseite mit “883L” oder “L883” beschriftet sein, mit einer guten Lupe kann man die Chip-Markierung lesen.

Ja, es ist nen L883.

Hm-ich hatte ein Mini-Breadboard dran.
Eben hab ichs noch mal versucht, nur mit Stecker und 30cm Kabel an dem Ding-ringsum 30cm nichts- dann geht es. Rauscht aber schon enorm, bereits minimale Änderungen der Lage wirken sich gleich mal auf mehr als 90 Grad aus. Armabduhr? :wink:

Die nächsten Lautsprecher sind allerdings nur nen halben Meter weg…trotzdem extrem empfindlich…
Aber: im Prinzip funktionierts schonmal nun.

Rabenauge:
Hm-ich hatte ein Mini-Breadboard dran.
Eben hab ichs noch mal versucht, nur mit Stecker und 30cm Kabel an dem Ding-ringsum 30cm nichts- dann geht es. Rauscht aber schon enorm, bereits minimale Änderungen der Lage wirken sich gleich mal auf mehr als 90 Grad aus. Armabduhr? :wink:

Also wenn Du eine Rolex Submariner am Handgelenk hast, und diese dann in Stahl statt in Gold, würde ich die Uhr beim Hantieren mit einem Kompass ablegen.
:wink:

Ansonsten habe ich mir mal Gedanken gemacht, wie man einen eCompass kalibrieren kann und wie man korrekte Werte bekommt, trotz gleichbleibender Einflüsse aus der Montage mit Stahl-Headerstiften am Modul und ggf. auf einem Breadboard mit Stahlklammern im Innern.

Zuerst wollte ich das vermeintlich einfach machen, mit Ausrichtung des Moduls in ganz bestimmte Richtungen, messen von Werten und Errechnung simpler Korrekturwerte. Das ist alles Pustekuchen gewesen, damit bin ich überhaupt nicht auf einen grünen Zweig gekommen.

Jetzt habe die Freescale-Application-Note #AN4246 mit dem Titel “Calibrating an eCompass in the
Presence of Hard and Soft-Iron Interference” mal in einen Arduino-Sketch gegossen. Und das sieht eigentlich recht vielversprechend aus. Das Dokument ist hier im Internet nachzulesen:
http://www.freescale.com/files/sensors/doc/app_note/AN4246.pdf

Man muß mit dem eCompass einfach nur sechs verschiedene Messwerte messen, mit dem eCompass “in möglichst viele verschiedene Richtungen weisend”. Und dann wird die pure Mathematik in Form von Vektor- und Matrixrechnung auf diese sechs Punkte losgelassen. Am Ende kommen drei Korrekturwerte Vx, Vy, Vz für die Korrektur der x-, y-, z-Achse dabei heraus.

Mit diesem Sketch wird das Rechenbeispiel aus dem Freescale-Dokument nachgerechnet
Entgegen des Titels wird mit dem Rechenbeispiel aber nur die Hard-Iron Kalibrierung durchgeführt:

/*
Magnetometer calibration by 'jurs' for German Arduino Forum
Created after Freescale Application Note #4246
Calibrating an eCompass in the Presence of Hard and Soft-Iron Interference
by: Talat Ozyagcilar
http://freescale.com/files/sensors/doc/app_note/AN4246.pdf

This sketch does the "hard iron" calibration only.
*/

#include <MatrixMath.h>

// Use six different measurements of magnetometer for calibration
float matrix[6][4]={
  {167.4, -242.4, 91.7, 1},  // x1, y1, z1, 1
  {140.3, -221.9, 86.8, 1},  // x2, y2, z2, 1
  {152.4, -230.4, -0.6, 1},  // x3, y3, z3, 1
  {180.3, -270.6, 71.0, 1},  // x4, y4, z4, 1
  {190.9, -212.4, 62.7, 1},  // x5, y5, z5, 1
  {192.9, -242.4, 17.1, 1},  // x6, y6, z6, 1
};

float matrix_transposed[4][6];
float matrix_multiplied[4][4];
float matrix_inverted[4][4];
float matrix_multiplied2[4][6];
float y_vector[6][1];
float result_beta[4][1];
float vx,vy,vz;


void calibrate()
{
  Matrix.Print((float*)matrix,6,4,"matrix");
  Matrix.Transpose((float*)matrix,6,4,(float*)matrix_transposed);
  Matrix.Print((float*)matrix_transposed,4,6,"matrix_transposed");
  Matrix.Multiply((float*) matrix_transposed, (float*) matrix, 4,6,4, (float*)matrix_multiplied);
  Matrix.Print((float*)matrix_multiplied,4,4,"matrix_multiplied");
  Matrix.Copy((float*)matrix_multiplied,4,4,(float*)matrix_inverted);
  Matrix.Invert((float*)matrix_inverted,4);
  Matrix.Print((float*)matrix_inverted,4,4,"matrix_inverted");
  Matrix.Multiply((float*) matrix_inverted, (float*) matrix_transposed, 4,4,6, (float*)matrix_multiplied2);
  Matrix.Print((float*)matrix_multiplied2,4,6,"matrix_inverted x transposed");
  for (int i=0;i<6;i++)
  {
    y_vector[i][0]=0;
    for (int j=0;j<3;j++) y_vector[i][0]+=matrix[i][j]*matrix[i][j];
  }
  Matrix.Print((float*)y_vector,6,1,"y_vector");
  Matrix.Multiply((float*)matrix_multiplied2,(float*)y_vector,4,6,1,(float*)result_beta);  
  Matrix.Print((float*)result_beta,4,1,"result_beta");
  Serial.println();
  vx=result_beta[0][0]/2;
  vy=result_beta[1][0]/2;
  vz=result_beta[2][0]/2;
  Serial.print("Vx= ");Serial.println(vx);
  Serial.print("Vy= ");Serial.println(vy);
  Serial.print("Vz= ");Serial.println(vz);
  Serial.println();
  Serial.print("Geomagnetic field strength = ");
  Serial.print(sqrt(result_beta[3][0]+vx*vx+vy*vy+vz*vz));
}

void setup()
{
  Serial.begin(9600);
  Serial.println();
  Serial.println("Magnetometer calibration by 'jurs' for German Arduino Forum");
  Serial.println();
  calibrate();
}

void loop()
{
}

Die in meinem Sketch verwendete “MatrixMath” Library hänge ich als Dateianhang an dieses Posting dran.

Um selbst eine Kalibrierung für Deinen Hardwareaufbau zu ermitteln, einfach in “matrix” die Werte von sechs weitgehend beliebigen, aber möglichst verschiedenen eCompass-Messwerten eintragen.

Das müssen auch keine Werte in Mikrotesla sein, sondern Du kannst Du Datenrohwerte eines HMC5883L einsetzen.

Sechs Werte mögen insgesamt zwar ein bisschen wenig sein für eine vollständige Kalibrierung, aber für einen Kompass in der Ebene sollte es ganz gut hinhauen.

Für eine gut funktionierende Kalibrierung für einen flach liegenden Kompass zu erhalten wie folgt vorgehen:
Kompass mit dem Breadboard flach hinlegen und vier Werte ermitteln, indem jeweils um 90° in der Ebene gedreht wird. Den fünften und sechsten Wert dann durch Kippen um die eine oder andere Achse ermitteln. Und die Korrekturwerte dann in dem oben von mir geposteten Sketch zur Korrektur der ausgelesenen Rohdaten verwenden, bevor die Kompassrichtung ausgerechnet wird.

Und dran denken: Mein Sketch in Reply #1 ist KEIN Tilt-kompensierter Kompass, sondern der Code funktioniert nur bei flach liegendem Sensor! Und das gilt auch, wenn man die Rohdatenwerte vor dem Ausrechnen der Kompassrichtung noch um die Korrekturwerte Vx, Vy und Vz korrigiert! Und mit dem Sketch aus dieser Reply #5 wird auch nur die “Hard Iron” Kalibrierung durchgeführt, nicht jedoch die aufwändigere “Soft Iron” Kalibrierung.

Vielleicht kannst Du ja trotzdem etwas damit anfangen, probier’s mal aus!

MatrixMath.zip (3.4 KB)

Leider nicht.
Inzwischen fällt mir nix mehr ein-der Kompass gibt einfach volkommen unlogische Werte aus.
Ich habs nun wieder mit deinem Programm (weiter oben das) versucht: ich schaffs nicht, selbst mit grosszügigen Toleranzen mal nen Vollkreis von 0 über 90,180,270 hinzubekommen.

Das Ding gibt Werte aus, die auch erstmal recht sinnvoll erscheinen (er reagiert durchaus auf Drehungen),aber dann ists aus.
Das selbe passiert, wenn ich das Beispielprogramm (was die HMC5883L.h benutzt), dort bekomm ich in der seriellen Konsole zusätzlich die Meldung "Entered scale was not valid, valid gauss values are: 0.88, 1.3, 1.9, 2.5, 4.0, 4.7, 5.6, 8.1" .
Die ist auch nicht wegzubekommen. :frowning:
Frag mich, ob das Ding defekt sein kann?
Er reagiert ja auf Drehungen um jede Achse...

Das genannte Beispielprogramm ist da: ArduiKyo: HMC5883L Compass + Arduino + Processing

Rabenauge:
Leider nicht.
Inzwischen fällt mir nix mehr ein-der Kompass gibt einfach volkommen unlogische Werte aus.
Ich habs nun wieder mit deinem Programm (weiter oben das) versucht: ich schaffs nicht, selbst mit grosszügigen Toleranzen mal nen Vollkreis von 0 über 90,180,270 hinzubekommen.

Dass Du in meinem Kalibriersketch aus Reply #5 für

float matrix[6][4]={

nicht meine 6 Messwerte einsetzen mußt, sondern Deine eigenen, ist Dir aber schon klar?

Für die Kalibrierung eines Vollkreises in der Ebene würde ich vorschlagen:

  1. Messwert x-Achse Richtung (ungefähr) Norden
  2. Messwert x-Achse Richtung (ungefähr) Osten
  3. Messwert x-Achse Richtung (ungefähr) Süden
  4. Messwert x-Achse Richtung (ungefähr) Westen
  5. Messwert x-Achse Richtung (ungefähr) Oben
  6. Messwert x-Achse Richtung (ungefähr) Unten

Welche Werte setzt Du in meinem Kalibriersketch für "float matrix[6][4]" ein?
Und wie setzt Du diese Werte dann in Deinen Sketch nur Kalibrierung ein?

Wenn die Messwerte für den Vollkreis in der Ebene mit Berücksichtigung der Kalibrierwerte nicht drastisch besser werden, hast Du irgendwas falsch gemacht.

Rabenauge:
Das selbe passiert, wenn ich das Beispielprogramm (was die HMC5883L.h benutzt), dort bekomm ich in der seriellen Konsole zusätzlich die Meldung "Entered scale was not valid, valid gauss values are: 0.88, 1.3, 1.9, 2.5, 4.0, 4.7, 5.6, 8.1" .
Die ist auch nicht wegzubekommen. :frowning:
Frag mich, ob das Ding defekt sein kann?

Das ist garantiert nicht dasselbe, denn das ist ein Programmierfehler beim Versuch, die Sensorauflösung auf eine andere Auflösung umzustellen. Entweder ein Programmierfehler in Deiner Library (die vielleicht gar nicht für exakt denselben Sensor gemacht ist, den Du verwendest), oder ein Programmierfehler in Deinem Sketch.

Derselbe Fehler wie beim Verwenden meiner Sketche kann das schon deshalb nicht sein, weil in meinen Sketchen immer mit der Default-Sensorauflösung gearbeitet wird, und zwar sowohl im Richtungs-Sketch aus Reply #1 als auch im Kalibrierwert-Ermittlungs-Sketch aus Reply #5.

Wenn Du nur "volkommen unlogische Werte" herausbekommst, ziehst Du die Kalibrierwerte vielleicht zur falschen Seite ab?

Zeig mal vor was Du hast:

  • Welche Werte Du in den Kalibriersketch für float matrix[6][4] einsetzt
  • Welche Kalibrierwerte Du daraus bekommst
  • Und wie Du diese erhaltenen Kalibrierwerte im Sketch zur Richtungsermittlung dann berücksichtigst

Jurs, du hast mich missverstanden (oder ich mich unklar ausgedrückt).
Schon dein allererstes Beispiel funktioniert nicht brauchbar mit meinem Sensor.

Also selbst ohne Kalibrierung kriegt ich praktisch nie nen Vollkreis zusammen-nicht mal sowas ähnliches. Drehe ich das Ding, steigen die Werte bis auf irgendwas über 200, und nehmen dann einfach wieder ab. Teils auch völlig unpassend (da kommt plötzlich mal ne 10, obwohl ich um die 170 schwirre oder so).
Zumindest das aber sollte ja so halbwegs gehen oder?

Rabenauge:
Jurs, du hast mich missverstanden (oder ich mich unklar ausgedrückt).
Schon dein allererstes Beispiel funktioniert nicht brauchbar mit meinem Sensor.

Das erste Beispiel ist vollkommen ohne jegliche Eisenkalibrierung.

Da sollte überhaupt kein Eisen in der Nähe des Sensors sein und auch überhaupt keine von nennenswert Strom durchflossene Leitung. Insbesondere sollten für dieses Beispiel keine Pin-Stifte aus Stahl an der Sensorplatine angelötet sein, und schon gar nicht die Platine mit Stahl-Pins auf ein Breadboard gesteckt werden, das im Innern voll ist von Stahlklammern.

Aber auch mit diesem Beispiel und selbst wenn Eisen oder stromdurchflossene Leitungen in der Nähe sind, sollten die Messwerte stetig sein: Wenn der Sensor in der Lage festliegt, sollten nachfolgende Messungen immer ungefähr dieselben Messwerte ergeben. Und wenn der Sensor langsam gedreht wird, sollten sich die Messwerte langsam ändern. Langsam ansteigend bis zu einem Maximalwert, langsam abfallend bis zu einem Minimalwert.

Außer Eisen sind auch stromdurchflossene Leitungen zu berücksichtigen: Die Lage von stromdurchflossenen Leitungen relativ zum Sensor darf sich während der Messung nicht ändern, genau so wie der Strom in den Leitungen sich nicht ändern sollte. Also wenn Du in 1cm Entfernung vom Sensor eine Leitung hast, durch die 10mA Strom fließen, dann darf diese Leitung nicht mal so und mal so zum Sensor verlaufen. Oder mal 20 mA und mal 0mA Strom führen. Das verändert die Messwerte.

Rabenauge:
Also selbst ohne Kalibrierung kriegt ich praktisch nie nen Vollkreis zusammen-nicht mal sowas ähnliches. Drehe ich das Ding, steigen die Werte bis auf irgendwas über 200, und nehmen dann einfach wieder ab. Teils auch völlig unpassend (da kommt plötzlich mal ne 10, obwohl ich um die 170 schwirre oder so).
Zumindest das aber sollte ja so halbwegs gehen oder?

Ja, die Messwerte sollten sich nicht sprunghaft ändern, wenn sich weder

  • die Lage zu Eisenteilen in der Nähe sprunghaft ändert
  • die Lage zu stromdurchflossenen Leitungen in der Nähe sprunghaft ändert
  • der Strom in stromdurchflossenen Leitungen in der Nähe sprunghaft ändert

Die Änderungen der Messwerte sollten gleichmäßig sein: Wenn Du Eisenteile au den Sensor hinzu oder davon weg bewegst. Wenn Du stromdurchflossene Leitungen zum Sensor hin und davon weg bewegst. Oder wenn Du den Strom in stromdurchflossenen Leitern erhöhst oder verringerst.

Du hast nicht zufällig eine Stromleitung für eine per PWM angesteuerte LED an Deinem Kompasssensor vorbeilaufen?

Das Erdmagnetfeld ist nicht paralell zur Erdoberfläche. In Deutschland hat es einen Winkel (Inklination) von ca 60 Grad siehe Erdmagnetfeld – Wikipedia.
Der Sensor mißt die vektorielle Projektion des Magnetfelds in alle 3 Achsen und nicht in 2 Achsen paralell zur Erdoberfläche wie ein Kompass.

Du mußt die Magnetwerte der 3 Achsen auf ein Koordinatensystem umrechenen das waagerecht gegenüber der Erdoberfläche ausgerichtet ist. Es ist nicht die Größe des Vektors wichtig sondern seine Richtung.

Grüße Uwe

@Jurs: an dem Ding sind die vier Anschlussstifte dran (waren sie schon immer, hab den so bekommen) und sonst nix.
Er hängt momentan (ich hatts ja auch schon mit längerer Leitung versucht, um mehr Abstand zu bekommen) nur an nem ca. 10cm Kabelchen am nackten Arduino (an dem auch nix weiter hängt ausser USB).
Momentan hab ich noch nen anderes Programm laufen (Wiring and Test | Adafruit HMC5883L Breakout - Triple-Axis Magnetometer Compass Sensor | Adafruit Learning System)- jetzt, wo der Sensor einfach vom Tsich baumelt, gibts auch konstante Werte.

Mit dem Beispiel dort erreiche ich übrigens auch wirklich die 360 Grad, aber wenn ich dann den Sensor um etwa 180 Grad drehe, kommen Werte im Bereich um die 250 raus.
Bei den 360 Grad, die das Programm ausspuckt, zeigt die X-Achse übrigens wirklich so halbwegs in Nord-Südrichtung (jedenfalls dem Aufdruck des Moduls nach).

Eben hab ich ne Gegenprobe mit deinem Programm (ich meine das allererste was du hier gepostet hast) gemacht:
Da hab ich bei der 360Grad-Ausrichtung vom Adafruit-Programm (gleicher Aufbau, nur anderes Programm) Werte um die 220, in der Gegenrichtung (um die Hochachse 180 Grad gedreht) so rund 160.

Rabenauge:
Momentan hab ich noch nen anderes Programm laufen (Wiring and Test | Adafruit HMC5883L Breakout - Triple-Axis Magnetometer Compass Sensor | Adafruit Learning System)- jetzt, wo der Sensor einfach vom Tsich baumelt, gibts auch konstante Werte.

Mit dem Beispiel dort erreiche ich übrigens auch wirklich die 360 Grad, aber wenn ich dann den Sensor um etwa 180 Grad drehe, kommen Werte im Bereich um die 250 raus.

Eine interessante Sensorplatzierung wird auf der Seite gezeigt!
Den Sensor genau mittig auf ein Breadboard gesetzt, in der Hoffnung, dass sich dann die Eisenfehler durch die Metallklammern im Innern des Breadboards zumindest bei Messungen in der Ebene aufheben und man so Kompassrichtungen mit einem sehr simplen Sketch und vollkommen ohne Kalibrierung ermitteln kann, trotz erheblicher Eiseneinwirkungen auf die Messung. Na ja.

In die Adafruit-Library habe ich mal reingeschaut und danach muss ich sagen, dass entweder der Adafruit-Programmierer oder ich das Datenblatt falsch verstanden hat. Ich habe es nämlich so verstanden, dass nur bei der eingebauten "Selbsttest" Funktion unterschiedliche Verstärkungen auf den verschiedenen Achsen gelten (insbesondere auf der Z-Achse ein anderer Faktor als auf der X- und Y-Achse), aber der Adafruit-Programmierer scheint davon auszugehen, dass auch im Normalbetrieb ein unterschiedlicher Verstärkungsfaktor gilt.

Bei Messungen in der X-Y-Ebene sollte sich dadurch allerdings kein Unterschied bei der Ermittlung von Himmelsrichtungen ergeben. Wohl aber bei Messungen in der X-Z- oder Y-Z-Ebene.

Das müßte ich nochmal anhand von Datenblatt und Sensormessungen nachvollziehen, ob ich mich da tatsächlich so verlesen habe.

Rabenauge:
Bei den 360 Grad, die das Programm ausspuckt, zeigt die X-Achse übrigens wirklich so halbwegs in Nord-Südrichtung (jedenfalls dem Aufdruck des Moduls nach).

Messungen, die strikt in der X-Y-Ebene des Sensors stattfinden, müßten mit dem Adafruit-Beispielprogramm und meinem Programm aus Reply #1 ungefähr dasselbe ergeben. Der wesentliche Unterschied ist ja nur, dass mit der Adafruit-Library Gleitkommawerte in Gauss/Tesla verarbeitet werden und mein Programm Rohdaten als Integer verarbeitet.

Falls der Sensor nicht flach aufliegt, müßte mein Programm andere Werte ergeben. Aber für nicht flach aufliegende Sensoren ist weder das Adafruit-Beispielprogramm noch mein Sketch aus Reply #1 gemacht.

Rabenauge:
Eben hab ich ne Gegenprobe mit deinem Programm (ich meine das allererste was du hier gepostet hast) gemacht:
Da hab ich bei der 360Grad-Ausrichtung vom Adafruit-Programm (gleicher Aufbau, nur anderes Programm) Werte um die 220, in der Gegenrichtung (um die Hochachse 180 Grad gedreht) so rund 160.

Das finde ich merkwürdig, falls Du das originale Adafruit-Beispielprogramm mit Auswertung der X-Y-Werte (bei senkrecht zeigender Z-Achse) verwendest. Das wäre aber wegen der Diskrepanz bei der Auswertung der Z-Achse normal, wenn Du den Sensor senkrecht betreiben würdest, also mit Auswertung der X-Z- oder Y-Z-Achse.

Ob die Adafruit-Programmierer mit dem abweichenden Verstärkungsfaktor auf der Z-Achse im Normalbetrieb tatsächlich Recht haben, müßte ich irgendwann nochmal genau austesten. Ich konnte das aus dem Datenblatt jedenfalls so nicht herauslesen und habe nur gesehen, dass im "Selbsttest" Modus ein abweichender Faktor für die Z-Achse gilt.

Um zu sehen, ob Deine Messungen sauber reinkommen, müßte man einen Test-Sketch machen, vielleicht sogar mit meiner "Normalauslesung" und der "Adafruitauslesung" parallel, und feststellen, ob Sprünge auftreten.

Also wenn man beispielsweise vorgibt, dass man den Sensor nicht mehr als 90° pro Sekunde dreht, dann würde das bei vier Messungen pro Sekunde einer maximalen Winkeländerung von 90/4= 22,5° entsprechen oder bei 10 Messungne pro Sekunde von 90/10=9° zwischen zwei Messungen. Und sich dann einfach mal ausgeben lassen, ob dann bei der Verarbeitung doch Sprünge von mehr als 22,5° oder 9° zwischen zwei Einzelmessungen in der Richtung auftreten Das würde dann in der Tat darauf hindeuten, dass Dein Sensor entweder defekt ist oder fehlerhaft ausgelesen wird.

Alle anderen Missweisungen, die von Sketchen sonst angezeigt werden, treten durch Abweichungen aufgrund von Eisen in der Nähe, aufgrund von stromdurchflossenen Leitern in der Nähe und aufgrund von Kippen gegen die Waagerechte auf. Und diese muss man nur entsprechend kalibrieren, herausrechnen oder vermeiden, um auf korrekte Richtungswerte zu kommen.

Ich hab noch einen: http://hobbylogs.me.pn/?p=17

Damit hab ichs auch probiert- vergleichbare Ergebnisse (nicht die selben Werte, aber nen ähnliches Gesamtresultat)*grrrr

Die Idee, deine Methode, und die von Ada mal zugleich zu benutzen, gefällt mir.
Das werd ich mal ausprobieren, so schwer isses nich, das beides zusammen in ein Programm zu packen.

Mal sehn, was dabei herauskommen wird.
Man-hätt ich gewusst, dass das soo nen Zirkus mit dem Ding gibt, hätt ich gleich nen 9DoF gekauft damals, aber nun ist das Teil hier und ich hätte ne nützliche Verwendung für (im autonomen Buggy, der braucht zwingend irgendeinen Richtungsdetektor)- also muss die Nuss geknackt werden.
Scheint aber nicht nur mir so zu gehn, das Teil wird alleine scheinbar eher selten benutzt.

Ich bastele jetzt mal dein erstes Testprogramm und das von Ada zusammen.

Rabenauge:
Ich bastele jetzt mal dein erstes Testprogramm und das von Ada zusammen.

Am besten aber gleich eine Version mit hard-iron calibration.

Mit Berücksichtung der Kalibrierungswerte sähe mein Sketch aus Reply #1 so aus, hier erstmal alle Kalibrierwerte auf 0 gesetzt:

#include <Wire.h>

#define Addr 0x1E               // 7-bit address of HMC5883 compass

void setup() {
  Serial.begin(9600);
  Serial.println();
  Wire.begin();
  
  // Set operating mode to continuous
  Wire.beginTransmission(Addr); 
  Wire.write(byte(0x02));
  Wire.write(byte(0x00));
  Wire.endTransmission();
}

void loop() {
  int x, y, z;
  int Vx=0; // Offset from hard-iron calibration
  int Vy=0; // Offset from hard-iron calibration
  int Vz=0; // Offset from hard-iron calibration

  // Initiate communications with compass
  Wire.beginTransmission(Addr);
  Wire.write(byte(0x03));       // Send request to X MSB register
  Wire.endTransmission();

  Wire.requestFrom(Addr, 6);    // Request 6 bytes; 2 bytes per axis
  if(Wire.available() <=6) {    // If 6 bytes available
    x = Wire.read() << 8 | Wire.read();
    x -= Vx;
    z = Wire.read() << 8 | Wire.read();
    z -= Vz;
    y = Wire.read() << 8 | Wire.read();
    y -= Vy;
  }
  // If compass module lies flat on the ground with no tilt,
  // just x and y are needed for calculation
  float heading=atan2(-x, y)/0.0174532925;
  if(heading < 0) heading+=360; // N=0/360, E=90, S=180, W=270
  Serial.println(heading);  
  delay(500);
}

Und die Kalibrierwerte Vx, Vy und Vz bekommst Du aus dem Sketch in Reply #5, falls Du etwas in Punkto Kalibrierung machen möchtest, angepaßt auf Deinen Sensor, mit Stahlstiften an der Platine, auf Breadboard gesteckt oder wie immer Du ihn auch betreibst, mit welchen Eisenmagnetfeldern in der näheren Umgebung.

Und zur Kalibrierung mit dem Kalibriersketch für einen möglichst gut in der Ebene funktionierenden Kompass diese ungefähren Richtungen als Kalibrierpunkte nehmen (Vorschlag):

  1. Messwert x-Achse Richtung (ungefähr) Norden
  2. Messwert x-Achse Richtung (ungefähr) Osten
  3. Messwert x-Achse Richtung (ungefähr) Süden
  4. Messwert x-Achse Richtung (ungefähr) Westen
  5. Messwert x-Achse Richtung (ungefähr) Oben
  6. Messwert x-Achse Richtung (ungefähr) Unten

Sooo sieht das Ganze viel besser aus!

Hab Adafruit noch nicht zusammengeschmissen mit deinem (kam grad natürlich mal wieder was zwischen), aber deines mal "provisorisch" kalibriert:
Die Werte sind nicht übermässig genau, aber da ich den Sensor beim testen nur in der Hand halte, leuchtet das ein.
Zumindest erreiche ich Werte, die nunmehr glaubwürdig sind, also bei ner viertel Drehung um die Hochachse bewegt sich die Winkelangabe ungefähr um 90Grad.
Selbst Norden kommt so in etwa hin-die Y-Achse markiert Nord/Südrichtung, jedenfalls ists so aufgedruckt auf der Platine.

Ich gebs offen zu: für mich ist das "grosser Zauber", nichts desto trotz kann ich nun was mit dem Ding anfangen.
Wie exakt der nun nach Norden zeigt, ob auf den magnetischen Nordpol, auf den russischen oder von mir aus irgendeinen dazwischen ist für mich ohnehin nicht relevant, es genügt, wenn der AutoDuino zu Anfang gucken kann, in welche Richtung er guckt, und die später jederzeit wiederfindet, bzw. raufindet, wieviel Grad Kuve er eben gefahren ist.

Genau wird das Ding sowieso nicht, da es unmöglich ist, nen nicht-neigungskompensierten Kompass an nem Fahrzeug so aufzuhängen, dass er genau funktioniert.
Vielleicht spiele ich da später mal noch nen 6DoF (liegt noch einer rum) dran, dann geht auch das-ist aber eigentlich für das kleine Spassauto schon übertrieben.

Rabenauge:
Sooo sieht das Ganze viel besser aus!

Aha.

Sind das recht hohe Kalibrierwerte bei Dir? Über 100?

Und woran liegt es, dass es nun mit den Kalibrierwerten aus dem Sketch von Reply #5 funktioniert und vorher nicht?

An dem von mir heute geposteten Sketch, wo die Kalibrierwerte vom Messwert abgezogen werden und Du hast damit vorher was anderes gemacht?

Ausgestanden ist es noch nicht.
Eben hab ich den Sensor ins Auto eingebaut (mir dessen bewusst, dass ich die Kalbirierung dann neu machen muss) und-wieder kommt Murks raus.
Im allgemeinen nen Wert von 270, ungefähr, auch wenn ichd as Ding drehe.
Vermutlich liegts an den Rohdaten, die ich mit dem HMC5883l_Example ermittle- das läuft, ohne Nachbessern, sowieso nicht.
Es kommen exorbitante Werte (-4096) raus auf der X-Achse-und das gleich in mehreren Stellungen. Da haut irgendwas nicht hin.
Ich probiere jetzt mal ein bisschen rum....

Hm-nen anders Beispiel versucht, um die Rohdaten zu benutzen-annähernd das Gleiche, nur schwankt am Ende die Ausgabe nicht um die 170 Grad, sondern um 60 Grad herum, egal wie ich die Kiste drehe.
Da stimmt irgendwas nicht.
Da es vorhin funktionierte (so, wie auch das allererste Beispiel von dir hier im Tread ja mal halbwegs klappte) tippe ich auf ein Hardwareproblem.
Bei den Messreihen fällt auf, dass die X-Achse recht auffällig, in verschiedenen Lagen den gleichen Wert liefert.

 {-166.73, 40.00, -35.31, 1},  // x1, y1, z1, 1
  {-372.36, 48.64 , -34.69, 1},  // x2, y2, z2, 1
  {-372.36, 44.82, -35.71, 1},  // x3, y3, z3, 1
  {-178.27, 32.09, -38.16, 1},  // x4, y4, z4, 1
  {-147.09, 54.73, 13.27, 1},  // x5, y5, z5, 1
  {-178.64, 101.45, 15.71, 1},  // x6, y6, z6, 1

das sind die aktuellen Werte, ermittelt mit dem Programm von Adafruit.

Rabenauge:
Ausgestanden ist es noch nicht.
Eben hab ich den Sensor ins Auto eingebaut (mir dessen bewusst, dass ich die Kalbirierung dann neu machen muss) und-

... und ein Auto ist ein Faradayscher Käfig, wenn es aus Blech ist.
Du baust das Teil doch hoffentlich nicht irgendwo ein, wo es vor Eisen nur so wimmelt!?

Rabenauge:
Es kommen exorbitante Werte (-4096) raus auf der X-Achse-und das gleich in mehreren Stellungen. Da haut irgendwas nicht hin.

-4096 ist ein Error-Wert und kein Rohdatenwert.

Siehe Datenblatt:
In the event the ADC reading overflows or underflows for the given channel, or if there is a math overflow during the bias measurement, this data register will contain the value -4096. This register value will clear when after the next valid
measurement is made.

Wenn Du die standardmäßige Empfindlichkeit des Sensors nicht anders einstellst, arbeitet der im Default-Range von ± 1.3 Gauss.

Die normale Stärke des Erdmagnetfelds in unseren Breitengraden beträgt ca. 0,5 Gauss.
Und das ist der normale Maximalwert, den Du auf einer Achse Deines Sensors messen kannst, wenn diese Achse genau in Richtung des Erdmagnetfelds zeigt. Wenn Du selbst im 1.3 Gauss Messbereich einen Messbereichs-Overflow erzeugen kannst, dann hast Du Eisenstörungen oder Störungen durch stromgenerierte Magnetfelder, die mindestens doppelt so stark sind wie das Erdmagnetfeld.

Wenn die Störungen doppelt so groß sind wie der Wert, den Du eigentlich messen möchtest, wundern mich Deine Probleme nicht.

Rabenauge:
Bei den Messreihen fällt auf, dass die X-Achse recht auffällig, in verschiedenen Lagen den gleichen Wert liefert.

 {-166.73, 40.00, -35.31, 1},  // x1, y1, z1, 1

{-372.36, 48.64 , -34.69, 1},  // x2, y2, z2, 1
 {-372.36, 44.82, -35.71, 1},  // x3, y3, z3, 1
 {-178.27, 32.09, -38.16, 1},  // x4, y4, z4, 1
 {-147.09, 54.73, 13.27, 1},  // x5, y5, z5, 1
 {-178.64, 101.45, 15.71, 1},  // x6, y6, z6, 1

Wenn Du den Sensor in der Ebene drehst gibt es nur eine Variation beim x-Wert von -372 bis -166?
Und beim y-Wert sogar nur von +32 bis +101?

Das sieht für mich nach einem Einbau in einem Faradayschen Käfig aus, aber nicht nach einem normalen Erdmagnetfeld.

P.S.: Auch wenn ich mich da mit Deiner Matrix etwas vertan habe, die Matrixwerte sind bei Dir ja nicht "Units" (Rohdaten) sondern irgendwie "Mikrotesla" von Deiner Library. Aber trotzdem: Dass die Werte auf einer 360 Grad Drehung ihr Vorzeichen behalten und nicht wechseln, heißt überhaupt nichts Gutes für die vorhandenen Magnetfelder in der Umgebung.

Nein-es ist kein Blechauto. :wink:
So doof bin ich auch wieder nich.... :smiley:

Das Ding besteht zu 90% aus feinstem chinesischen Plastik.
ABÄR: Natürlich nicht nur. Etwa 10cm entfernt vom Sensor sitzt der Fahrmotor.
Der Grund: ohne Motor fährts nich...und wo anders kann ich den Sensor nicht so wirklich einbauen, da vorne der Lenkmotor (selbe Grösse) sitzt und ich dann automatisch näher an den käme.

Was nutzt ein elektronischer Sensor, der in der Nähe irgendwelcher Elektrik oder Elektronik nich funktioniert?
Weiter weg von einem der Motoren, als er monentan ist, gehts einfach nicht-dann müsste ich nen Anhänger bauen für den Kompass.

Und: das sind ja nun auch keine Riesenmotoren, sowas 300er Baugrösse, klar haben die ein Magnetfeld aber das muss doch irgendwie zu umgehn sein?
Sonst wären diese Sensoren ja wirklich ziemlich nutzlos..

Hm-allerdings: es gehn quasi wirklich ein paar Leitungen "ringsherum"- teils Masse, teils 5 bzw. 7.2V.
Ich könnte den Sensor unter den Heckspoiler packen, das wäre vom Fahrmotor nich weiter weg (vom Akku auch nicht), aber zumindest wär er nicht mehr von Kabeln umgeben. und hoch über dem ganzen anderen Kram.
Meinst, das reicht?
Oder hast du nen besseren Tip dazu?