Forum: Mikrocontroller und Digitale Elektronik ESP32 mit Adafruit LIS3DH I2C. Register auslesen


von Markus P. (eoun46055)


Angehängte Dateien:

Lesenswert?

Hallo

Ich versuche gerade einen funktionierenden Code zu schreiben, welcher 
mir dem Daten vom LIS3DH ausgibt. Ich habe den Code mit diversen 
libaries probiert jedoch sind die zum Teil fehlerhaft oder es fehlen 
einstellungsmöglichkeiten. Ich würde gerne den High Res mode mit 
1,344kHz mit 2g verwenden.
Dafür setzte ich das CTRL_REG1 (151) und CTRL_REG4 (16).
Das funktionier so weit auch. Nun möchte ich aber die Daten auslesen. 
Und da ergibt sich mir das Problem. Wenn ich versuche me
hrere Register auf einmal auszulesen das kommt da nix vernünftiges raus.

Hier der Code:

#include <Wire.h>

int LIS3DH = 0x18;
float CTRL_REG1;
float CTRL_REG4;
float X_OUT, Y_OUT, Z_OUT;
uint8_t OUT_X_L, OUT_X_H, OUT_Y_L, OUT_Y_H, OUT_Z_L, OUT_Z_H;
uint16_t OUT_X, OUT_Y, OUT_Z;
1
void setup(void) {
2
  Serial.begin(115200);
3
  Wire.begin();
4
5
  // --- Set Configuration ---
6
  //CTRL_REG1 0x20: Data rate, Mode, Enable Axis
7
  Wire.beginTransmission(LIS3DH);
8
  Wire.write(0x20);
9
  Wire.write(151); //10010111
10
  Wire.endTransmission();
11
12
  //CTRL_REG4 0x23: Full-scale selection, High-resolution output mode
13
  Wire.beginTransmission(LIS3DH);
14
  Wire.write(0x23);
15
  Wire.write(8); //00001000
16
  Wire.endTransmission();
17
18
  delay(100);
19
  Wire.requestFrom(LIS3DH, 1);
20
  CTRL_REG4 = Wire.read();
21
  Serial.println(CTRL_REG4);
22
 
23
}
24
25
void loop() {
26
27
  //Set Pointer to beginn of data
28
  Wire.beginTransmission(LIS3DH);
29
  Wire.write(0x2C);
30
  Wire.endTransmission();
31
32
  //read Data
33
  Wire.requestFrom(LIS3DH, 2, true);
34
  OUT_Z_L = Wire.read();
35
  OUT_Z_H = Wire.read();
36
37
  Serial.println(OUT_Z_H);
38
39
  delay(1000);
40
41
}

Ich möchte mal nur den Z Wert auslesen. Daher lese ich OUT_Z_L und 
OUT_Z_H  aus. Wenn ich die aber gemeinsam auslese dann bekomme ich für 
OUT_Z_H ganz andere Werte als wenn ich nur OUT_Z_H alleine auslese. Wie 
kann das sein?

Hat da jemand eine Idee?

Danke

Edit:

Um das nochmals klar zu stellen. Wenn ich veruche das OUT_Z_H  register 
auszulesen bekomme ich was anders für :
1
  //Set Pointer to beginn of data
2
  Wire.beginTransmission(LIS3DH);
3
  Wire.write(0x2C);
4
  Wire.endTransmission();
5
6
  //read Data
7
  Wire.requestFrom(LIS3DH, 2, true);
8
  OUT_Z_L = Wire.read();
9
  OUT_Z_H = Wire.read();

als ich bei
1
 Wire.beginTransmission(LIS3DH);
2
  Wire.write(0x2D);
3
  Wire.endTransmission();
4
5
  //read Data
6
  Wire.requestFrom(LIS3DH, 1, true);
7
  OUT_Z_H = Wire.read();

bekomm. Obwohl meiner meinung nach das zweitere das richtige liefter

: Bearbeitet durch User
von Thomas W. (Gast)


Lesenswert?

Markus P. schrieb:
> Hallo
1
 
2
> float CTRL_REG4;

>
1
>   Wire.requestFrom(LIS3DH, 1);
2
>   CTRL_REG4 = Wire.read();
3
>   Serial.println(CTRL_REG4);
4
>

Ich kenne diesen speziellen Sensor nicht, aber ich glaube nicht dass
ein Sensor floats ausgibt. Meistens sind es 16 - 24 Bitwerte in 
Byte-Form.

Bei Deinem Codebeispiel bekommst Du genau ein Byte. Ich weiss natuerlich 
nicht wie das Konvertiert/gecastet wird, aber ist sicherlich flasch.

Gruesse

Th.

von Matthias T. (matthiasthiele)


Lesenswert?

Hast Du das hier im Datenblatt gesehen?

In order to read multiple bytes, it is necessary to assert the most 
significant bit of the sub-
address field. In other words, SUB(7) must be equal to 1 while SUB(6-0) 
represents the
address of first register to be read.

von Markus P. (eoun46055)


Lesenswert?

Danke für die Antwort.
Ja das war der richtige Hinweis.
Für die Nachwelt ich habe das nun wie folgt gelöst:
1
Wire.beginTransmission(LIS3DH);
2
  Wire.write(0xA8); // Start Adress 0x28 (OUT_X_L) + MSB = 1 (8bit) für auto increment => A8
3
  Wire.endTransmission();
4
  Wire.requestFrom(LIS3DH, 6, true);
5
  OUT_X_L = Wire.read();
6
  OUT_X_H = Wire.read();
7
  OUT_Y_L = Wire.read();
8
  OUT_Y_H = Wire.read();
9
  OUT_Z_L = Wire.read();
10
  OUT_Z_H = Wire.read();
Anschließend rechne ich um und gebe aus:
1
//Umrechnen (12bit, High Res Mode)
2
  OUT_Z = OUT_Z_H;
3
  OUT_Z <<= 8;
4
  OUT_Z |= OUT_Z_L;
5
  OUT_Z >>= 4;
6
7
  if(OUT_Z_old != OUT_Z)
8
  {
9
    Serial.print(micros());
10
    Serial.print(" ");
11
    Serial.println(OUT_Z);
12
    OUT_Z_old == OUT_Z;
13
  }
Ich lese das aktuel über USB aus. Ich habe abe auch eine SD Card adapter 
bestellt dann möchte ich die Daten auf die SD Carte schreiben. Nun 
ergibt sich mir aber eine weitere Frage.
Ich gebe auch die Micros aus. Ich habe die Register wie folgt gesetzt:
1
//CTRL_REG1 0x20: Data rate, Mode, Enable Axis
2
  Wire.beginTransmission(LIS3DH);
3
  Wire.write(0x20);
4
  Wire.write(151); //1001 0111 = Fast in normal or HP = 151 // 10011111 = 5,376kHz Low Power = 159
5
  Wire.endTransmission();
6
7
//CTRL_REG4 0x23: Full-scale selection, High-resolution output mode
8
  Wire.beginTransmission(LIS3DH);
9
  Wire.write(0x23);
10
  Wire.write(8); //0000 1000 = 2g, High Resulution = 8
11
  Wire.endTransmission();

Daher sollte ich im 12bit 1,344kHz mode sein. Die 12 bitte passen nur 
die 1,344khz schaffe ich nicht ganz. Ich bin so bei ca 1khz. Ich habe 
etwas probiert und es scheint mir so als würde es dir register nicht 
schnellgenug auslesen können. Daher wenn ich die nicht alle 6 Register 
sondern nur 1 oder 2 auslese dann bin ich deutlich schneller. Hat jemand 
eine Idee wie man das beschleunigen könnte. (ich habe mit 
Wire.setClock(400000 ) auch schon den „schnellen“ I2C Modus aktiviert. 
(mach aber nicht wirklich einen unterschied))

Edit:
1
 Wire.beginTransmission(LIS3DH);
2
  Wire.write(0xAC); // Start Adress 0x28 (OUT_X_L) + MSB = 1 (8bit) für auto increment => A8 // Start Adress 0x2C (OUT_Z_L) + MSB = 1 (8bit) für auto increment => AC
3
  Wire.endTransmission();
4
  Wire.requestFrom(LIS3DH, 2, true);
5
  OUT_Z_L = Wire.read();
6
  OUT_Z_H = Wire.read();
7
8
  OUT_Z = OUT_Z_H;
9
  OUT_Z <<= 8;
10
  OUT_Z |= OUT_Z_L;
11
  OUT_Z >>= 4;
12
13
  if(OUT_Z_old != OUT_Z)
14
  {
15
    Serial.print(micros());
16
    Serial.print(" ");
17
    Serial.println(OUT_Z);
18
    OUT_Z_old == OUT_Z;
19
  }

Damit erreiche ich eine Zeit zwischen den neuen Werten von runf 700us

: Bearbeitet durch User
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.