Forum: Mikrocontroller und Digitale Elektronik Problem mit Magnetsensor HMC5883L vs. QMC5883L


von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Ich habe in Projekt, bei dem mittels 4 HMC5883L die Drehposition von 
Objekten durch einen kleinen untergeklebten Magneten erfasst wird. Das 
funktioniert auch hervorragend.

Nun soll das Projekt auf einen 5. Sensor erweitert werden, ich habe also 
einen Sensor bestellt und musste zu meinem Ärger feststellen, dass es 
sich diesmal nicht um einen HMCxxx, sondern um den QMCxxx handelt.

Reklamieren und neu bestrellen geht aber nicht, weil die Zeit extrem 
knapp ist, dauert mindestens 3 Tage (Lieferung in die anhaltinische 
Provinz).

Nun habe ich im Web diverse Codebeispiele gefunden, die alle nicht 
funktionieren. Entweder kommen immer nur kostante Werte oder quasi 
Zufallszahlen (ich benötige nur den horizontalen Winkelwert). Ausser der 
Adesse (0x0D statt 0xE1) ist da noch wesentlich mehr anders ...

Hat jemand ein kleines Stückchen (Arduino-) Code für mich, der mit dem 
Mistding (QMCxxx!) halbwegs stabile Werte liefert? Wenn möglich als 
reine I2C-Aufruf-Abfolge, nicht "versteckt" in irgend einer Compass-Lib 
(die alle nicht funktionieren) ...

Hier ist mein Code für den HMC5883L, der tut, was er soll. Ich benutze 
der Reihe nach die Anschlüsse A0-A3 für SDA und immer A5 für SCL ...
1
int get_maga(int pin)
2
{
3
  int x,y,z; // 3 Achsen
4
  SoftwareI2C s;
5
  s.begin(pin,A5);
6
  s.beginTransmission(hmc_adr); // Verbindung öffnen mit dem HMC5883
7
  s.write(hmc_mode); // Mode Register
8
  s.write(hmc_cont);   // Kontinuierliche Messung
9
  s.endTransmission();
10
11
  s.beginTransmission(hmc_adr); // Verbindung öffnen mit dem HMC5883
12
  s.write(hmc_regb); // Mode Register
13
  s.write(hmc_gain);   // Empfindlichkeit auf 8 Gauss
14
  s.endTransmission();
15
  
16
  s.beginTransmission(hmc_adr);
17
  s.write(hmc_out); // Register 3, X MSB Register, Lesemodus
18
  s.endTransmission();
19
 
20
  s.requestFrom(hmc_adr, 6);
21
  x = s.read()<<8;  x |= s.read();
22
  z = s.read()<<8;  z |= s.read();
23
  y = s.read()<<8;  y |= s.read();
24
  s.endTransmission();
25
  float w = atan2(-y , x) / M_PI * 180.0;
26
  if(w < 0){w = w + 360.0;}
27
  return w; 
28
}

: Bearbeitet durch User
von Stefan (Gast)


Lesenswert?

Hallo,

schau dir das Datenblatt des QMC5883L genau an und nimm Rücksicht auf 
die veränderten Addressen der Register und deren Inhalte 
(Initalisierung) !

Dann gehts auch mit dem IC.

Gruss

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Stefan schrieb:
> Hallo,
>
> schau dir das Datenblatt des QMC5883L genau an und nimm Rücksicht auf
> die veränderten Addressen der Register und deren Inhalte
> (Initalisierung) !
>
> Dann gehts auch mit dem IC.
>
> Gruss

ja, geht jetzt! :-)

Der "dickste" Fehler war, dass (gegenüber dem HMCxxx) beim QMCxxx 
Low/High-Byte in den Resultat-Registern vertauscht sind, was jede kleine 
Änderung wie einen Zufallsgenerator aussehen ließ ...

von Wolfgang (Gast)


Lesenswert?

Frank E. schrieb:
> ja, geht jetzt! :-)

Und wie sieht der Korrekte Code für den QMC5883L jetzt aus?

Sonst geht es dem nächsten, der auf diesen Thread stößt, genauso :-(

Frank E. schrieb:
> Nun habe ich im Web diverse Codebeispiele gefunden, die alle nicht
> funktionieren.

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Hier ist jetzt mein Code, der die SoftwareI2C-Lib von Seedstudio.com 
voraussetzt. Damit kann ich mehrere der Chips abfragen, obwohl sie alle 
die gleiche Adresse haben: A5 ist immer SCL, A4...A0 dann jeweils SDA. 
Hier folgen zwei Funktionen, die erste für den HMC, die zweite für den 
QMC
1
int get_hmc(int pin)
2
{
3
4
  int  hmc_addr = 0x1E;
5
  byte hmc_mode = 0x02;
6
  byte hmc_cont = 0x00;
7
  byte hmc_regb = 0x01;
8
  byte hmc_gain = 0xE0;
9
  byte hmc_out =  0x03; 
10
  
11
  int x,y,z; // 3 Achsen
12
  SoftwareI2C s;
13
  s.begin(pin,A5);
14
  s.beginTransmission(hmc_addr); // Verbindung öffnen mit dem HMC5883
15
  s.write(hmc_mode); // Mode Register
16
  s.write(hmc_cont);   // Kontinuierliche Messung
17
  s.endTransmission();
18
19
  s.beginTransmission(hmc_addr); // Verbindung öffnen mit dem HMC5883
20
  s.write(hmc_regb); // Mode Register
21
  s.write(hmc_gain);   // Empfindlichkeit auf 8 Gauss
22
  s.endTransmission();
23
  
24
  s.beginTransmission(hmc_addr);
25
  s.write(hmc_out); // Register 3, X MSB Register, Lesemodus
26
  s.endTransmission();
27
  
28
  s.requestFrom(hmc_addr, 6);
29
  x = s.read()<<8;  x |= s.read();
30
  z = s.read()<<8;  z |= s.read();
31
  y = s.read()<<8;  y |= s.read();
32
  s.endTransmission();
33
  
34
  float w = atan2(-y , x) / M_PI * 180.0; if(w < 0){w = w + 360.0;}
35
  return w; 
36
}
37
38
39
int get_qmc(int pin) //nur für Sensor C (Mitte)!
40
{
41
  int  qmc_addr = 0x0D;
42
  byte qmc_mode = 0x0B;
43
  byte qmc_cont = 0x00;
44
  byte qmc_conf = 0x09;
45
  byte qmc_set =  0x1D;
46
  byte qmc_out =  0x00;
47
  int x,y,z;
48
49
  SoftwareI2C s;
50
  s.begin(pin,A5);
51
    
52
  s.beginTransmission(qmc_addr);             
53
  s.write(qmc_mode);                         
54
  s.write(qmc_cont);                         
55
  s.endTransmission();
56
  
57
  s.beginTransmission(qmc_addr); 
58
  s.write(qmc_conf); 
59
  s.write(qmc_set);   
60
  s.endTransmission();
61
  
62
  s.beginTransmission(qmc_addr);
63
  s.write(qmc_out);
64
  s.endTransmission();
65
  
66
  s.requestFrom(0x0D, 6);  
67
  x = s.read();  x |= s.read()<<8;
68
  y = s.read();  y |= s.read()<<8;
69
  z = s.read();  z |= s.read()<<8;
70
  //s.endTransmission();
71
72
  float w = atan2(-y , x) /M_PI * 180.0; if(w < 0){w = w + 360.0;}
73
  return w;
74
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.