ESP32 mit Adafruit LIS3DH I2C. Register auslesen

OP #7400919
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

Angehängte Dateien:
Gast #7400966
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.

OP #7401613
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren