ADXL380 mit SPI auslesen

#7915091
Lesenswert?

Hallo zusammen, wir versuchen gerade im Rahmen einer Studienarbeit den ADXL380-1BCCZ-RL7 via SPI auszulesen und die Beschleunigungsdaten zu protokolieren. Der ADXL380 wurde gemäß dem Datenblatt auf Seite 23 (siehe Bild) angeschlossen und wird mit dem ESP32-C3-Mini von Espressif betrieben. Der Stromverbrauch im Standby-Mode beträgt etwa 7uA und im High Performance-Mode messen wir etwa 250uA. Der ESP32 wird mit der Arduino IDE 2.3.6 programmiert und in der PDF ist der Leseprozess, den wir mit dem Oszilloskop beobachtete haben dokumentiert. Wir versuchen zurzeit nur die Beschleunigungsdaten der X-Achse (Register: 0x15 und 0x16) zu lesen und bekommen nur eine 0 als Ergebnis. Die Device_ID lässt sich allerdings, so wie auch einige andere Register problemlos auslesen. Die Ergebnisse wurden mit 2 ADXL380 getestet.

Unser Code:

1
#include <SPI.h>
2

3
const int CS_PIN = 10;
4

5
void setup() {
6
  Serial.begin(115200);
7

8
  pinMode(CS_PIN, OUTPUT);
9
  digitalWrite(CS_PIN, HIGH);
10

11
  SPI.begin(6, 2, 7, 10);
12
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0)); 
13

14

15
  //Soft-Reset
16
  writeRegister(0x2A, 0b00000010);
17
  uint16_t softReset = readRegister(0x26);
18
  Serial.print("Soft-Reset: ");
19
  Serial.println(softReset);
20

21
  //Modus-Wahl
22
  writeRegister(0x26, 0b00000000); //Standby-Mode
23
  uint16_t mode1 = readRegister(0x26);
24
  Serial.print("Mode_1: ");
25
  Serial.println(mode1);
26

27
  writeRegister(0x27, 0b11100000);
28
  uint16_t dig_En = readRegister(0x27);
29
  Serial.print("Dig_En: ");
30
  Serial.println(dig_En);
31

32
  writeRegister(0x26, 0b00001100);
33
  uint16_t mode2 = readRegister(0x26);
34
  Serial.print("Mode_2: ");
35
  Serial.println(mode2);
36

37
  //Status
38
  uint16_t status0 = readRegister(0x11);
39
  uint16_t status1 = readRegister(0x12);
40
  uint16_t status2 = readRegister(0x13);
41
  uint16_t status3 = readRegister(0x14);
42

43
  //Status
44
  Serial.print("Status0: ");
45
  Serial.println(status0);
46
  Serial.print("Status1: ");
47
  Serial.println(status1);
48
  Serial.print("Status2: ");
49
  Serial.println(status2);
50
  Serial.print("Status3: ");
51
  Serial.println(status3);
52
}
53

54
void loop() {
55
  //x-Achse lesen
56
  uint16_t ID = readRegister(0x00);
57
  uint16_t xH_Data = readRegister(0x15);
58
  uint16_t xL_Data = readRegister(0x16);
59
  
60
  Serial.print("ID: ");
61
  Serial.println(ID,HEX);
62
  Serial.print("xL_Data: ");
63
  Serial.println(xL_Data);
64
  Serial.print("xH_Data: ");
65
  Serial.println(xH_Data);
66
  delay(400);
67
}
68

69
//Register write
70
void writeRegister(uint8_t registerAddress, uint8_t value) {
71
  uint16_t command = ((registerAddress << 9) | value); // R/W-Bit = 0
72

73
  digitalWrite(CS_PIN, LOW);
74
  
75
  SPI.transfer16(command);
76

77
  digitalWrite(CS_PIN, HIGH);
78
}
79

80
//Register read
81
uint16_t readRegister(uint8_t registerAddress){
82
    
83
    digitalWrite(CS_PIN, LOW);
84

85
    uint16_t data = SPI.transfer16((registerAddress<<9) | (0x01<<8));
86

87
    digitalWrite(CS_PIN, HIGH);
88

89
    return data;
90
}

Die Ausgabe auf dem Seriellen Monitor:

1
-> Ausgabe im Setup:
2
Soft-Reset:   12
3
Mode_1:   65280
4
Dig_En:   65504
5
Mode_2:   12
6
Status0:   65280
7
Status1:   65424
8
Status2:   65436
9
Status3:   1 
10

11
-> Ausgabe beim lesen:
12
ID:   AD
13
xL_Data:   0
14
xH_Data:   0

Zusätzlich zu dem vorliegenden Code haben wir ebenfalls versucht die anderen Achsen und die Temperatur auszulesen und haben ebenfalls nur 0 als Ausgabe bekommen. Vielleicht hat jemand eine Idee oder ein paar Tipps. LG OLLI

#7915173
Lesenswert?

Danke für deine schnelle Antwort,

ich habe mal das Datenblatt beigefügt, auf Seite 49 wird dort das schreiben und lesen per SPI erklärt. Ich habe das Datenblatt so gedeutet, dass die Adresse insgesamt 7 Bit lang ist und in die Bits 9-15 geschrieben wird, weswegen ich in meiner Funktion auch die Adresse um 9 Bit shifte (von Bit 0 auf Bit 9) und der Read/Write Befehl liegt auf Bit 8, weswegen ich das dann um 8 shifte. Vielleicht habe ich da auch einen Denkfehler. Könntest du mir deinen Ansatz etwas genauer erläutern. LG Olli

Angehängte Dateien:
Moderator (Firma: Titel) Persönliche Seite #7915200
Lesenswert?

Probiers mal so:

1
  :
2
void writeRegister(uint8_t registerAddress, uint8_t value) {
3
  uint16_t command = (((uint16_t)registerAddress << 9) | value); 
4
  :
5
uint16_t readRegister(uint8_t registerAddress){
6
  uint16_t data = SPI.transfer16(((uint16_t)registerAddress<<9) | (0x01<<8));
7
  :

Das sollte der Compiler zwar von sich aus tun, aber hey, wer weiß. Das Oszi wäre hier wieder super, um zu sehen, ob auf dem Bus auch das unterwegs ist, was du erwartest.

Noch Tipp: die Bits 15..8 im empfangenen 16-Bit-Wort sind "undriven". Die solltest du also sinnigerweise spätestens bei der Anzeige ausblenden. Oder einfach nur 8 Bits zurückgeben:

1
uint8_t readRegister(uint8_t registerAddress){
2
:
3
    uint8_t data = SPI.transfer16((registerAddress<<9) | (0x01<<8));
4
:
5
    return data;

Interessant wäre hier auch, dass die Clockphase sicher zum Datenblatt passt. Denn sonst schreibst du evtl. die Adresse um 1 Bit versetzt.

Beitrag #7915207 wurde von einem Moderator gelöscht.
#7915610
Lesenswert?

Das ist jetzt unser aktueller Code. Die Ausgabe ist jetzt etwas formatiert und ich habe die Verbesserung mit uint8_t bei readRegister() übernommen. Die Datentypkonvertierung mit (uint16_t) ist eine gute Idee gewesen, aber leider hat das auch keine Verbesserung ergeben. Wir erhalten weiterhin bei allen Achsen 0 als Ausgabe und lesen derzeit alle 4 ID´s aus, wobei eine ID vom Datenblatt abweicht. Die ID unter der Adresse 0x03 sollte den Wert 0xC2 widergeben und wir erhalten eine 0xC1. Allerdings ist in dem Applications Examples (GitHub) in der ADXL38x.h auf der Analog Devices Seite zum ADXL380 auch als Rückgabewert 0xC1 beschrieben. Des weiteren haben wir den Status 0-3 weiter ausgewertet und haben "EFUSE-Fehler" lesen können:

Erweiterter Reset + NVM Control

1
writeRegister(0x2A, 0x52); //Seite 69
2
3
delay(10);
4
//NVM Control
5
writeRegister(0x29, 0b11000000);
6
delay(10);

Ausgabe:

1
Soft-Reset:     0x2  0b10
2
Mode_1:          0x0  0b0
3
Dig_En:          0xE0  0b11100000
4
Mode_2:          0xC  0b1100
5
Status0:  0x40  0b1000000
6
Status1:  0x80  0b10000000
7
Status2:  0x9C  0b10011100
8
Status3:  0x1  0b1

Erweiterter Reset

1
writeRegister(0x2A, 0x52); //Seite 69
2
3
delay(10);

Ausgabe:

1
Soft-Reset:     0x2  0b10
2
Mode_1:          0x0  0b0
3
Dig_En:          0xE0  0b11100000
4
Mode_2:     0xC  0b1100
5
Status0:  0x40  0b1000000
6
Status1:  0x80  0b10000000
7
Status2:  0x9C  0b10011100
8
Status3:  0x0  0b0

Erweiterter Reset mit Startdelay

1
delay(10);
2
writeRegister(0x2A, 0x52); 
3
4
delay(10);

Ausgabe:

1
Soft-Reset:     0x2  0b10
2
Mode_1:          0x0  0b0
3
Dig_En:          0xE0  0b11100000
4
Mode_2:          0xC  0b1100
5
Status0:  0x40  0b1000000
6
Status1:  0x80  0b10000000
7
Status2:  0x9C  0b10011100
8
Status3:  0x0  0b0

Soft-Reset

1
writeRegister(0x2A, 0b00000010); 
2
3
delay(10);

Ausgabe:

1
Soft-Reset:     0x0  0b10
2
Mode_1:          0x0  0b0
3
Dig_En:          0xE0  0b11100000
4
Mode_2:          0xC  0b1100
5
Status0:  0x0  0b0
6
Status1:  0x80  0b10000000
7
Status2:  0x9C  0b10011100
8
Status3:  0x1  0b1

Bei dem "erweiterte" Reset schreiben wir in das Reset-Register die 0x52, was einen sofortigen Reset zur Folge hat (S.69 im Datenblatt). Zu erkennen ist, dass wir ohne "erweiterten" Reset NVM_Done (Bit 6) in Status 0 nicht gesetzt wird. Ansonsten haben wir das Problem bei alle Versuchen das Status 1 einen Error mit Bit 7 zum EFUSE Controller ausgibt und Status 2 mit Bit 3 einen EFUSE CRC Error ausgibt. Vielleicht haben wir auch eine Denkfehler, aber ich sehe gerade keine anderen Problem mehr und verstehe die EFUSE-Errors nur bedingt. Ich werde noch einmal den SPI-Bus mit dem Oszilloskop untersuchen und mich dann nochmal melden.

Angehängte Dateien:
#7915791
Lesenswert?

Oliver M. schrieb:

Ich werde noch einmal den SPI-Bus mit dem Oszilloskop untersuchen

Je nach dem, was du für ein Oszilloskp hast, kann das möglicherweise als Logikanalysator das SPI-Signal selbst dekodieren. In dem Analyse-Dokument ist es wegen der geringen Zeitauflösung und der Überlagerung von Clock und Daten arg mühselig, irgendwelche Details bzgl. des Timings abzulesen.

#7916088
Lesenswert?

Moin, ich kenne diesen Chip nicht, aber für die SPI Kommunikation ist kein eigenes Frame Format angegeben. Bei anderen Chips heisst das, das exakt das I2C Frame Format benutzt werden muss. Also Byte1 Devadr+r/w, Byte2 regadr, byte2 Data. Du machst nur 16bit transfers. Und die Device Adresse sollte ja fix sein, je nachdem wie ASEL0/1 stehen. Könnte es daran liegen?

#7916178
Lesenswert?

Thomas R. schrieb:

Also Byte1 Devadr+r/w, Byte2 regadr, byte2 Data.

SPI braucht keine DeviceAddress. Das R/W-Bit wird an das Command-Byte (obere sieben Bit) als LSB angehängt. Kapitel "Serial Communicatiom" im Datenblatt (https://www.analog.com/media/en/technical-documentation/data-sheets/adxl380.pdf - Seite 49) Ob der Baustein ein Adress-Autoinkrement unterstützt, habe ich auf die Schnelle nicht gefunden. Normalerweise / von anderen Bausteinen wird sowas ja unterstützt.

#7916953
Lesenswert?

Der ADXL380-1BCCZ-RL7 ist nur mit einer SPI-Kommunikation ausgestattet (siehe S.103) und diese ist auch leider Vorgabe. Wir haben jetzt versucht mit einem anderen Mikrocontroller (Arduino Nano) den ADXL380 auszulesen, haben aber weiterhin nur die Device ID bekommen. Zusätzlich dazu haben wir die SPI-Kommunikation mit einem ADXL345 geteste und direkt plausible Beschleunigungsdaten erhalten. Den SPI-Modus (0 oder 3), sowie eine Veränderung der Frequenz haben wir auch am ADXL380 probiert ohne Erfolg, wobei das mehr eine Akt der Verzweiflung war ^^.

Die Bilder von dem Oszilloskop sahen soweit genauso aus, wie wir es erwarten würden. Alldering sind die Daten nicht so leicht zu sehen, wegen des schlechten Kontrastes. Grün = Daten Gelb = Clock Zu sehen ist einmal MISO und MOSI von dem High-Byte der x-Achse und von der ID4, da wir dort eine Abweichung hatten. Zusätzlich schicke ich noch ein Bild zu dem kompletten MISO-Datensatz, was wahrscheinlich wegen dem HighZ (vergleiche Seite 49) in den nicht relevanten Bits 1 oder 0 ist.

Angehängte Dateien:

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