Forum: Compiler & IDEs LSM303DLH, Gyrosensor Messwerte unvollständig


von headnut (Gast)


Lesenswert?

Hallo zusammen,

kurz zum Projekt. Ich möchte über einen Gyrosensor + Magnetfeldsensor
die Horizontallage messen. Die Sensorkombination muss sein, da auf das
Projekt später Fliehkräfte einwirken und ich dann vom Gyro alleine keine 
sauberen Werte erwarten kann. Daher habe ich mir einen LSM303DLH 
(3-Achsen Beschleunigungssensor und 3-Achsen Magnetometer) bei den 
Kollegen
Spark Fun organisiert.

Hardware: - STK500
          - ATmega32 mit 16MHz Quarz
          - LSM303DLH (Kom. I2C)
          - Alles andere lasse ich mal außen vor
Software: - AVR Studio 6

Status, die Kommunikation funktioniert Grundsätzlich. Der Sensor gibt 
mir
auch Werte zurück:
X:-64.00     A.Y:-16.00   A.Z:4112.00
M.X:0.34     M.Y:0.04     M.Z:0.02

A.X:-96.00   A.Y:0.00   A.Z:4144.00
M.X:0.43     M.Y:0.28   M.Z:-0.10

A.X:-64.00   A.Y:0.00   A.Z:4112.00
M.X:0.44     M.Y:0.30   M.Z:-0.10

A.X:-80.00   A.Y:-16.00  A.Z:4112.00
M.X:0.42     M.Y:0.29    M.Z:-0.08<\r>

Problem: Der Gyrosensor Arbeitet gut, ich habe bereits die einzelen 
Achsen getestet und skaliert. Jedoch der Magnetfeld Sensor scheint 
irgendwie nich alles auszugeben. Als ob das High Byte fehlt, oder er 
garnicht arbeitet.

Ich wälze nun seid einigen Tagen die Datasheets, Application Notes, etc. 
Aber denen kann man Anscheinend nicht so recht trauen, da diverse 
Register und Parameter in verschiedenen Unterlagen/Beispielen 
unterschiedlich sind.
So bekomme ich z.B. vom Gyro nur Schrott zurück, wenn ich das Output 
register nach dem Datasheet auslese.

Folgendermaßen gehe ich vor:


//Initialisiere Beschleunigungsmesser
void init_Beschleunigung (void)
{
  i2c_start();
  i2c_write_byte(0x30);  // write acc
  i2c_write_byte(0x20);  // CTRL_REG1_A
  i2c_write_byte(0x27);  // normal power mode, 50 Hz data rate, all axes 
enabled
  i2c_stop();

  i2c_start();
  i2c_write_byte(0x30);  // write acc
  i2c_write_byte(0x23);  // CTRL_REG4_A
  i2c_write_byte(0x30);  //keep a full scale range ±8 gauss in 
continuous data update mode
  i2c_stop();
}

//Initialisiere Erdmagnetfeldmessung
void init_Magnetfeld (void)
{
  i2c_start();
  i2c_write_byte(0x3C); // write mag
  i2c_write_byte(0x02); // MR_REG_M
  i2c_write_byte(0x00); // continuous conversion mode
  i2c_stop();

  i2c_start();
  i2c_write_byte(0x3C); // write mag
  i2c_write_byte(0x01); // MR_REG_M
  i2c_write_byte(0x20); // full scale ±8 Gauss, Output range: -2048-2048
  i2c_stop();
}

// Lese einen ganzen Datensatz von beiden Messsensoren
void read_data_raw(vector *a, vector *m)
{
  // Lese Beschleunigungsmesser Daten
  i2c_start();
  i2c_write_byte(0x30);            // write acc
  i2c_write_byte(0xa8);            // OUT_X_L_A, MSB set to enable 
auto-increment
  i2c_start();                 // repeated start
  i2c_write_byte(0x31);            // read acc
  unsigned char axl = i2c_read_byte();    //acc/X-axis/low byte
  unsigned char axh = i2c_read_byte();    //acc/X-axis/high byte
  unsigned char ayl = i2c_read_byte();    //acc/Y-axis/low byte
  unsigned char ayh = i2c_read_byte();    //acc/Y-axis/high byte
  unsigned char azl = i2c_read_byte();    //acc/Z-axis/low byte
  unsigned char azh = i2c_read_last_byte();  //acc/Z-axis/high byte
  i2c_stop();

  // Lese Erdmagnetfeldmessung Daten
  i2c_start();
  i2c_write_byte(0x3C);            // write mag
  i2c_write_byte(0x03);            // OUTXH_M
  i2c_start();                 // repeated start
  i2c_write_byte(0x3D);            // read mag
  unsigned char mxh = i2c_read_byte();    //mag/X-Axis/high byte
  unsigned char mxl = i2c_read_byte();    //mag/X-Axis/low byte
  unsigned char myh = i2c_read_byte();    //mag/Y-Axis/high byte
  unsigned char myl = i2c_read_byte();    //mag/Y-Axis/low byte
  unsigned char mzh = i2c_read_byte();    //mag/Z-Axis/high byte
  unsigned char mzl = i2c_read_last_byte();  //mag/Z-Axis/low byte
  i2c_stop();

  //Verbinde Messdaten Low und High Byte zu einer Variable
  a->x = axh << 8 | axl;            //Schieben
  a->y = ayh << 8 | ayl;            //Schieben
  a->z = azh << 8 | azl;            //Schieben
  m->x = mxh << 8 | mxl;            //Schieben
  m->y = myh << 8 | myl;            //Schieben
  m->z = mzh << 8 | mzl;            //Schieben
}

Hat schon irgendjemand mit dem Sensor Erfahrungen sammeln dürfen oder 
einen Tipp für mich wie ich das Problem strukturiert bekämpfen kann?

von Michael S. (Gast)


Lesenswert?

Hallo,

wenn Du ein Python-Script lesen kannst, guckst Du hier:

http://www.mikrocontroller.net/attachment/189229/LSM303DLM_python_130828.zip

Soweit ich sehen, fehlt bei Dir die Kalibrierung ...

Michael S.

von headnut (Gast)


Lesenswert?

Guten Morgen,

danke für den Hinweis. Ich werd es mir Heute im Laufe des Tages nochmal
anschauen! Ich bin aber übers Wochenende schon ein Bissle weiter 
gekommen.

Ich hab diverse Application Notes etc. gelesen und mir ist aufgefallen
dass die Register Adressen aus der Doku nicht Stimmen! Ich verwende
nun folgende Werte:

Start Adresse zum Auslesen des Magnetfeldsensors:
0x03;  //OUT_X_H_M (Steht so auch in der Doku WAR SCHON SPÄT :-) )
Außerdem kommt erste das Low dann das High Byte, hatte ich verdreht

Start Adresse zum Auslesen des Beschleunigungssensors:
0xa8;  //OUT_X_L_A Laut Doku 0x28

Wichtig auch folgender Hinweis:
"When one or more of the output registers are read, new data cannot
be placed in any of the output data registers until all six data
output registers are read."

In allen Web Beispielen werden beide Sensoren gleichzeitig ausgelesen, 
der
Magnetfeldsensor steht default bei "Minimum data output rate (Hz)" auf 
0,75.
Wird nun zu schnell gelesen, kommt der Sensor nicht zum schreiben. Also
Status Byte nicht vergessen!!

SR_REG_M (09h) & STATUS_REG_A(27h)

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.