2D Magnet-Sensor MMC2120MG/ Pollin HDMM01 Drucken
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