HMC5883L-Kompass funktioniert nicht

Wenn du diesen QMC5883L 'A' version hast (DA 5883), dann ist es noetig die Linie zu entfernen, wo das "Data Ready" bit im Statusregister getestet ist und anstatt ein millis() timer verwenden:

timeMillis = millis();                                      // Update the current time
if (timeMillis - sampleTime >= QMC5833L_CONVERSION_TIME)    // Read the QMC5883L's data every 14 milliseconds
{
  // Read the QMC5883L data registers here...
  
  sampleTime = timeMillis;                                  // Update the sample time
}

Hier ist ein Beispiel Sketch, dass mit dem QMC5883L version 'A' funktioniert:

#include <Wire.h>

#define QMC5833L_ADDR 0x1E                    // QMC5883L version A I2C address          
#define QMC5883L_CTRLA_REGISTER       0x00    // QMC5883L control A register sub-address
#define QMC5883L_CTRLB_REGISTER       0x01    // QMC5883L control B register sub-address
#define QMC5883L_MODE_REGISTER        0x02    // QMC5883L mode register sub-address
#define QMC5883L_DATA_X_MSB_REGISTER  0x03    // QMC5883L data output X axis MSB sub-address
#define QMC5833L_CONVERSION_TIME      14      // QMC5883L conversion time in milliseconds

int16_t x, y, z;                              // QMC5883L data variables
uint32_t timeMillis, sampleTime;              // Sample time variables                      

void setup() {
  Serial.begin(115200);                       // Open serial communications at 115200 bps  
  Wire.begin();                               // Start the wire library
  Wire.setClock(400000);                      // Set the I2C to fast mode at 400kHz

  // Put the QMC5833L IC into the correct operating mode:
  Wire.beginTransmission(QMC5833L_ADDR);      // Select the QMC5883L version A device
  Wire.write(QMC5883L_MODE_REGISTER);         // Select the mode register
  Wire.write(0x00);                           // Continuous measurement mode
  Wire.endTransmission();                     // Transmit
  
  Wire.beginTransmission(QMC5833L_ADDR);      // Select the QMC5883L version A device
  Wire.write(QMC5883L_CTRLA_REGISTER);        // Select control register A
  Wire.write(0x98);                           // Select 75Hz sample rate and temperature compensation
  Wire.endTransmission();                     // Transmit
  
  Wire.beginTransmission(QMC5833L_ADDR);      // Select the QMC5883L version A device
  Wire.write(QMC5883L_CTRLA_REGISTER);        // Select control register B
  Wire.write(0x20);                           // Select +-1.3 Gauss
  Wire.endTransmission();                     // Transmit
}

void loop() {
  timeMillis = millis();                                      // Update the current time
  if (timeMillis - sampleTime >= QMC5833L_CONVERSION_TIME)    // Read the QMC5883L's data every 14 milliseconds
  {
    // Tell the QMC5833L where to begin reading data          
    Wire.beginTransmission(QMC5833L_ADDR);                    // Select the QMC5883L version A device
    Wire.write(QMC5883L_DATA_X_MSB_REGISTER);                 // Select register X MSB data register
    Wire.endTransmission(false);                              // Transmit and keep the connection alive with false
    
    // Read data from each axis, 2 registers per axis
    Wire.requestFrom(QMC5833L_ADDR, 6);                       // Request the 6 data bytes, 2 bytes per axis
    if (Wire.available() >= 6)                                // Receive the data
    {
      x = Wire.read() << 8 | Wire.read();                     // Read the X axis data
      z = Wire.read() << 8 | Wire.read();                     // Read the Z axis data
      y = Wire.read() << 8 | Wire.read();                     // Read the Y axis data
    }
    sampleTime = timeMillis;                                  // Update the sample time
    Serial.print(x);                                          // Output the results to the console
    Serial.print(F("   "));
    Serial.print(y);
    Serial.print(F("   "));
    Serial.println(z);
  }
}

MartinL:
Wenn du diesen QMC5883L 'A' version hast (DA 5883), dann ist es noetig die Linie zu entfernen, wo das "Data Ready" bit im Statusregister getestet ist und anstatt ein millis() timer verwenden:

Ich habe aber wie's aussieht die B, da nur die ja die 0x0D-Adresse hat. Nicht die A

Ich habe aber wie's aussieht die B, da nur die ja die 0x0D-Adresse hat. Nicht die A

Dann gibt es ein QMC5883L Library hier: GitHub - dthain/QMC5883L: Driver for QMC5883L chip found in many GY-271 boards.. Es sollte mit der 'B' Version funktionert.

Okay, mit dieser Library läuft's. Danke!

Also bei mir funkioniert die folgende Funktion als Bestandteil eines größeren Projektes, ich verwende die Lib "SoftwareI2C" von Seedstudio.com. Dabei werte ich 5 solcher Sensoren an den Anschlüssen A0-A4 (Daten) aus, A5 ist der Takt für alle. Auszug:

#include <SoftwareI2C.h>
#include <SPI.h>

int  hmc_adr = 0x1E;
byte hmc_mode = 0x02;
byte hmc_cont = 0x00;
byte hmc_regb = 0x01;
byte hmc_gain = 0xE0;
byte hmc_out = 0x03;





int get_mag(int pin)
{
  int x,y,z; // 3 Achsen
  SoftwareI2C s;
  s.begin(pin,A5);
  s.beginTransmission(hmc_adr); // Verbindung öffnen mit dem HMC5883
  s.write(hmc_mode); // Mode Register
  s.write(hmc_cont);   // Kontinuierliche Messung
  s.endTransmission();

  s.beginTransmission(hmc_adr); // Verbindung öffnen mit dem HMC5883
  s.write(hmc_regb); // Mode Register
  s.write(hmc_gain);   // Empfindlichkeit reduzieren (Neodym-Magnet-Drehung messen)
  s.endTransmission();
  
  s.beginTransmission(hmc_adr);
  s.write(hmc_out); // Register 3, X MSB Register
  s.endTransmission(); //Messung auslesen

  s.requestFrom(hmc_adr, 6);
  x = s.read()<<8;  x |= s.read();
  z = s.read()<<8;  z |= s.read();
  y = s.read()<<8;  y |= s.read();
  s.endTransmission();
  float w = atan2(-y , x) / M_PI * 180.0;
  if(w < 0){w = w + 360.0;}
  return w; 
}

Das da ist doch genau für die Variante, die ich nicht brauche, oder?

Sensor an 3,3V
Der Uno macht 5V.

Und das ohne Levelschifter?

Sind die vorhandenen Pullup ausreichend?

Mein Sensor braucht laut ebay-Seite einen Strom von 3.3-5.5 V. Scheint wohl 'nen Wandler mit dran zu haben.

HTML-Fan:
Mein Sensor braucht laut ebay-Seite einen Strom von 3.3-5.5 V. Scheint wohl 'nen Wandler mit dran zu haben.

Merke!
Spannung ist Spannung. (in Volt)
Strom ist Strom. (in Ampere)
Und wenn beides gleichzeitig existiert, "entsteht" Leistung. (in Watt)

Du hast den Sensor laut Bild an 3,3V
Dein I2C Master läuft mit 5V.

Und das hat nichts damit zu tun, ob da ein "Wandler"drauf ist, oder nicht.

Es klappt doch alles! Was wollt ihr denn noch von mir?

Hallo,

HTML-Fan:
Es klappt doch alles! Was wollt ihr denn noch von mir???

nichts wollen wir von Dir. Ist doch Deine Hardware, die evtl. wegen Pegelfehlern oder Überlastung von Komponeten unzuverlässig laufen könnte oder irgendwann einfach abraucht.

Einen Elektronikschutzverein gibt es ja bisher noch nicht, der sich beschweren könnte.

Gruß aus Berlin
Michael

HTML-Fan:
Es klappt doch alles! Was wollt ihr denn noch von mir???

Wer so arrogant daher kommt, braucht zukünftig nicht mehr auf Hilfe hoffen.

Hallo HTML-Fan,

Mein Sensor braucht laut ebay-Seite einen Strom von 3.3-5.5 V. Scheint wohl 'nen Wandler mit dran zu haben.

Ja das ist richtig, es hat alles mit dem Wandler zu tun.

Obwohl es nicht absolut notwendig ist, es ist vielleicht besser um einen I2C-Levelshifter zu betreiben. Zum Beispiel Adafruit's I2C-Levelshifter: 4-channel I2C-safe Bi-directional Logic Level Converter [BSS138] : ID 757 : $3.95 : Adafruit Industries, Unique & fun DIY electronics and kits.

Der Schaltung normalerweise ohne einen I2C-Levelshifter klappt, weil...

Obwohl das Wire Library sein Mikrocontroller 5V pullup-Widerstaende aktiviert sind, sie sind zu schwach gegen die staerker 3,3V, 4k7 Ohm Widerstaende an der Kompassleitenplatte. Diese Widerstandspaar erstellen eine I2C Spannung ungefaehr von 3,45V bis 3,6V.

Der Mikrocontroller I2C "Input High Voltage" minimum ist: 0,7 * Vcc = 0,7 * 5V = 3,5V. Diese Wert liegt an der Grenze, aber haeufig funktioniert.