2D Magnet-Sensor MMC2120MG/ Pollin HDMM01 PDF Drucken E-Mail
Geschrieben von: Malte   
Sonntag, den 11. September 2011 um 21:01 Uhr

Vielleicht weil das Beschleunigungssensor- Modul von ELV so ein Verkaufsschlager war, hat Pollin seit kurzem ein günstiges Magnetsensor-Modul namens HDMM01 im Angebot, das sich als elektronischer Kompass verwenden lässt. Auf dem Modul befindet sich ein MMC2120 von MEMSIC. Der Sensor misst in zwei Achsen mit einer Auflösung von 12 Bit zwischen ±2 Gauss und verfügt über eine I²C Schnittstelle, so dass er sich leicht an einen Microcontroller anbinden lässt. Natürlich hab ich mir gleich eins von den Modulen geordert und ein wenig damit rumgespielt.

Anschluss | Der Anschluss des Moduls an einen AVR ist - I²C sei Dank - kaum der Rede wert: zwei Pins des Moduls dienen der Stromversorgung (der Sensor mag lt. Datenblatt alles zwischen 2.7 und 5.25 V), die anderen beiden Pins sind SDA und SCL und werden dementsprechend direkt mit dem µC verbunden, I²C Pull-ups nicht vergessen.

I²C Kommunikation | Der Sensor hat fest eingestellt die Adresse &h60. Das LSB der Adresse gibt bei I²C bekanntlich an, ob geschrieben oder gelesen werden soll, dementsprechen ist die Schreibadresse &h60, die Leseadresse ist &h61. Das Initiieren einer Messung und das Auslesen des Ergebnisses geschieht folgendermaßen: man erzeugt eine Startbedingung (SDA geht auf low während SCL high ist) und adressiert den Sensor zum Schreiben (&h60). Der Sensor hat nur ein Register, das an der Adresse &h00 liegt, man schreibt also diese Adresse auf den Bus, um im nächsten Schritt das Register manipulieren zu können. Das Setzen des LSB in diesem Register löst eine Messung aus, man überträgt dementsprechend &h01 und erzeugt eine Stopp-Bedingung (SDA geht auf high während SCL high ist). Nun genehmigt man dem Sensor einige Millisekunden Pause um die eigentliche Messung durchzuführen. Um die Daten abzuholen, wird zunächst wieder eine Start-Bedingung auf dem Bus erzeugt, dann teilt man dem Sensor mit, welches Datenbyte man lesen will. Dazu wird die Schreibadresse übertragen (&h60) und dann der Index des Datenbytes. Hier sollen alle fünf Bytes (Kontrollregister und Daten),  also von Index 0 gelesen werden, man schreibt somit &h00 auf den Bus. Nach einer erneuten Startbedingung legt man die Leseadresse (&h61) auf den Bus und kann sich dann in Folge fünf Bytes abholen, deren ersten vier mit einen Acknowledge quittiert werden. Nach dem fünften Byte erzeugt man eine Stopp-Bedingung.

Datenauswertung | Der Sensor löst die Messung für die x- und y-Dimension jeweils mit zwölf Bit auf. Dementsprechend ist ein Messwert auf zwei Bytes verteilt. Das erste gelesene Byte ist das Kontrollregister, also beginnen die Messdaten ab dem zweiten Byte.  Das zweite gelesene Byte ist high-Byte des x-Wertes, das dritte gelesene Byte dessen low-Byte. Das vierte Byte ist high-Byte des y-Wertes und das fünfte Byte low-Byte des y-Wertes. Das ungenutzte obere Nibble der high-Bytes soll man laut Datenblatt maskieren (soweit ich sehe, ist es aber sowieso immer 0). Man braucht jetzt nur noch jeweils high- und low-Byte verrechnen, um an den entsprechenden Datenpunkt zu kommen.

Code | Folgend ein kleines Stückchen BASCOM-Code, der kontinuierlich das Messen initiiert, die Messwerte ausliest und per UART versendet - allerdings nicht in physikalsichen Einheiten, sondern so, wie der Sensor die Daten codiert.

' beispielprogramm zum auslesen des MMC2120MG
' malte ahlers 2011
' weitere infos auf malteahlers.de
'
'
'
' compiler steuerung
$regfile = "m8def.dat"
$crystal = 8000000
$framesize = 64
$swstack = 64
$hwstack = 64
$baud = 9600
$lib "i2c_twi.lbx"
'
' hardware konfigurieren
' - taster
Config Pinb.6 = Input
Portb.6 = 1
Config Pinb.7 = Input
Portb.7 = 1
Config Pind.5 = Input
Portd.5 = 1
Taster1 Alias Pinb.6
Taster2 Alias Pinb.7
Taster3 Alias Pind.5
' - leds
Config Portd.7 = Output
Config Portd.6 = Output
Config Portb.0 = Output
Led_gl Alias Portd.7
Led_rt Alias Portd.6
Led_gr Alias Portb.0
' - i2c
Config Twi = 400000
Config Scl = Portc.5
Config Sda = Portc.4
'
' konstanten
Const Cmp_w = &H60
Const Cmp_r = &H61
'
' variablen
Dim I As Byte
Dim Dat(5) As Byte
Dim X As Word
Dim Y As Word                                             
'
' hauptprog
I2cinit
'
Do
 '
 ' * set/ reset coil *
 I2cstart
 '
 ' sensor adressieren (schreiben)
 I2cwbyte Cmp_w
 '
 ' register adressieren
 I2cwbyte &H00
 '
 ' register manipulieren -> set coil
 I2cwbyte &B00000010
 '
 I2cstop
 '
 Waitms 1
 '
 I2cstart
 '
 ' sensor adressieren (schreiben)
 I2cwbyte Cmp_w
 ' register adressieren
 I2cwbyte &H00
 '
 ' register manipulieren -> reset coil
 I2cwbyte &B00000100
 '
 I2cstop
 '
 Waitms 5
 '
 ' * messung *
 I2cstart
 '
 ' sensor adressieren (schreiben)
 I2cwbyte Cmp_w
 '                                           
 ' register adressieren
 I2cwbyte &H00
 '
 ' register manipulieren -> messung
 I2cwbyte &H01
 '
 I2cstop
 '
 Waitms 5
 '
 I2cstart

 I2cwbyte Cmp_w
'
 ' leseindex setzen
 I2cwbyte &H00
 '
 I2cstart
 '
 ' sensor adressieren (lesen)
 I2cwbyte Cmp_r
 '
 For I = 1 To 4
 ' bytes 1-4 holen mit ack
 I2crbyte Dat(i) , Ack
 Next
 '
 ' byte 5 holen mit nack
 I2crbyte Dat(5) , Nack
 '
 I2cstop
 '
 ' oberes nibble im high bytes löschen
 Dat(2) = Dat(2) And &B0000_1111
 Dat(4) = Dat(4) And &B0000_1111
 '
 ' x-wert aus high- und lowbyte berechnen
 X = Dat(2) * 256
 X = X + Dat(3)
 '
 ' y-wert aus high- und lowbyte berechnen
 Y = Dat(4) * 256
 Y = Y + Dat(5)
 '
 Print X ; " " ; Y
 '
 Waitms 40
 '
 Toggle Led_rt
 '
Loop
End

Hier das BASCOM-File zum Download: mmc2120mg.bas

Messung | Hier ein Beispiel für die Rohdaten einer solchen Messnung auf Basis des obigen Codebeispiels. Ich habe meinen Testaufbau einfach auf meinen Schreibttischdrehstuhl gelegt und zwei Runden in eine Richtung gedreht, nach kurzer Pause dann drei Runden in Gegenrichtung. Dabei wurde bei ca. 20 Hz kontinuierlich gemessen und die Messdaten per serieller Schnittstelle vom AVR auf meinen PC überragen. Trägt man nun den x- und y-Wert gegen den Sampleindex (also im Prinzip die Zeit) auf, erhält man folgendes Diagramm:


Man erkennt, dass sich die gemessenen Felder entpsrechend der Drehung "sinusartig" mit der Zeit ändern, einmal läuft die x-Dimension der y-Dimesnion mit 90° voraus, nach der erkennbaren Pause (beide Werte bleiben konstant) kehrt sich das um - das entspricht den beiden Drehrichtungen meines Schreibtischstuhls. So ein Wertepaar stellt eine kartesische Koordinate dar, plottet man für die gleichen Daten den x- gegen den y-Wert, wird die kreisförmige Bewegung deutlich. Im linken Teil der folgenden Abbildung habe ich x gegen y gegen Sampleindex geplottet. Der Sampleindex stellt ja im Prinzip die Zeit dar, die Schraube, die sich hier in der Abbildung ergibt, beschreibt also meine gesamte Dreherei. Ungefähr in der Mitte erkennt man den Stillstand und die Umkehrung des Drehsinns.

Kollabiert man die Sample-Dimension, erhält man das rechte Diagramm der oberen Abbildung. Daran erkennt man, dass die Messwerte auch bei mehrmaliger Drehung recht stabil sind. Außerdem wird daran klar, wie man zu einem Kompass kommt, der den Drehwinkel der Kompassnadel angibt. Im Prinzip geht es dabei ja nur darum, den Winkel zwischen der Verbindungslinie von aktuellem Messpunkt (x- und y-Wert) zum Kreismittelpunkt und der Verbindungslinie eines beliebigen Bezugspunktes (dem Nordpol z. B.) und dem Kreismittelpunkt zu berechnen. Kreismittelpunkt, Bezugspunkt und aktueller Datenpunkt bilden ein rechtwinkeliges Dreieck, dessen Ankathete und Gegenkathete von Kreismittelpunkt und Bezugspunkt bzw. Kreismittelpunkt und aktuellem Datenpunkt definiert werden. Der Tangens des Winkels zwischen diesen beiden Seiten ist das Verhältnis der Seitenlängen zueinander, umgekehrt ergibt sich der Winkel somit aus dem Arkustangens des Seitenverhältnisses. Um einen eindeutigen Winkel über 360° zu erhalten, verwendet man den vier-Quadranten-Arkustangens (atan2). Die Berechnung des Winkels in dem o. g. Dreieck ist natürlich unabhängig von der Hypotenuse, die dem Radius des Kreises entspricht. Dadurch also, dass nur das Verhältnis zwischen Ankathete und Gegenkathete in die Berechnung einfließt, ist der ermittelte Winkel unabhängig von der gemessenen Feldstärke (so wie man eben auch von einem Kompass verlangt, dass er zwar über Richtung aber nicht Stärke des Erdmagnetfeldes informiert).

Hier ein Video von meinem Versuchsaufbau im Betrieb:

 

Zuletzt aktualisiert am Samstag, den 24. September 2011 um 11:44 Uhr
 

Kommentare  

 
#14 2013-03-29 15:32
Hallo!
Sie können den Quellcode oder ein Computerprogram m?
Vielen Dank im Voraus.
 
 
#13 2013-03-29 15:31
Здравствуйте!
Можно получить исходный код или программу для компьютера?
Заранее спасибо.
 
 
#12 2013-03-29 15:29
Hallo!
Sie können den Quellcode oder skompelirovannu yu Computerprogram m?
Vielen Dank im Voraus.
 
 
#11 2012-02-25 14:42
Hallo!

zitiere Rüdiger:
ist es möglich statt eines HDMM01 einen CMPS10 zu verwenden?


Ich kenne das CMPS10 Modul nicht, aber es wäre wirklich reiner Zufall, wenn die Kommunikation exakt gleich ablaufen würden. Ich hab auf die Schnelle aber auch keine Beschreibung des Protokolls gefunden...

zitiere Arno:
Kämpfe derzeit mit dem Problem der Offsets. Wenn ich meinen Bot um angenommen 10 Meter verschiebe ändert sich der Offset und ich habe keinen sauberen Null-Punkt mehr.

Ich habe mittlerweile öfters von diesem Problem gehört. Ich selbst habe den Sensor aktuell nicht in einer realen Anwednung im Einsatz, insofern kann es tatsächlich sein, dass mir dieser Effekt nicht aufgefallen ist. Werde mir das ggf. bei Zeiten auch nochmal ansehen. Wenn ich da irgendwas rausfinde, poste ich es hier!

Viele Grüße
Malte
 
 
#10 2012-02-24 20:08
Hallo Malte,
ist es möglich statt eines HDMM01 einen CMPS10 zu verwenden?
Beide kommunizieren per I2C. Der CMPS10 ist neigungskompens iert, nur was ich nicht weiß ist, ob Dein Programm dann noch verwendbar ist.
 
 
#9 2012-02-22 09:00
Hallo Malte, super Bericht!
Ich hab auch das HDMM01 Modul im Einsatz. Kämpfe derzeit mit dem Problem der Offsets. Wenn ich meinen Bot um angenommen 10 Meter verschiebe ändert sich der Offset und ich habe keinen sauberen Null-Punkt mehr. Um den Nullpunkt wieder zu justieren bräuchte ich ja immer x/y min/max oder?

Wie hast Du das Problem gelöst oder bleibst Du mit dem Kompass immer an der gleichen Stelle?

LG, Arno
 
 
#8 2011-12-16 12:47
Echt super beschrieben, ich habe mir gleich einen HDMM01 bestellt und werde es versuchen mit einem Attiny84 auszulesen. Mein Projekt ist, dass nur in einem bestimmten Richtung eine LED blinken soll, simpel, aber für einen Einstieg mal ein nettes projekt :-))
 
 
#7 2011-10-19 21:57
Hey...
Gute Projekte und Dokumentationen hast du hier...
Wäre es möglich, auch die PC Software als Code zu bekommen?
Was/Wie muss man genau ausrechnen...
 
 
#6 2011-10-12 21:21
Eine Tilt-Compensation ist beschrieben auf:
http://mbed.org/projects/cookbook/wiki/TiltCompCompass

Dort wird allerdings ein 3-Achsiges Magnetometer und ein Accelerometer verwendet.
Da aber sqrt(mx^2+my^2+ mz^2)=const. sollte man mz (bis auf Vorzeichen) aus (mx,my) ermitteln können.
 
 
#5 2011-09-19 00:39
Hallo Hermann!

zitiere Hermann:
X_achse = X - 2045.5 : Y_achse = Y -2064.5
Ja, so habe ich es auch gemacht - natürlich mit anderen konkreten Zahlen. Dessen Ergebnis geht dann in den atn2. Also an der Stelle gibt's keine weiteren Geheimnisse...

zitiere Hermann:
Der Mittelpunkt des Kreises verschiebt sich je nachdem wie groß die Feldstärke ist
Naja, 100%ig stabil war dieser Mittelpunkt auch bei meinen Messungen nicht, aber stabil genug um o.g. Verfahren (atn2) verwenden zu können. Der Mittelpunkt ist durch das Nullfeld definiert und müsste deswegen schon einigermaßen konstant bleiben. Ich ergänze den Punkt oben mal, wenn ich etwas Zeit habe. Vielleicht wird es dann noch etwas deutlicher. Gruß, Malte.
 
 

Suche

Benutzer

Wir haben 30 Gäste online

unterstützt von

batronix logo

spacer

rotacaster logo

spacer

spacer

spacer

Meine Tweets

Extern

youtube logo twitter logo email logo

spacer

spacer

spacer

Reklame