Forum: Mikrocontroller und Digitale Elektronik ADXL345 - Sensor defekt oder Programm fehlerhaft?


von Max M. (maxmicr)


Lesenswert?

Ich versuche seit Tagen einen ADXL345 Beschleunigungssensor auszulesen. 
Ich kommuniziere mit dem Modul über Software-SPI. Nachdem ich 
erfolgreich die DEVID ausgelesen hatte, kann ich soweit wohl behaupten, 
dass lesen und schreiben funktioniert.

Allerdings scheinen die Beschleunigungswerte der verschiedenen Axen 
nicht zu stimmen.
Z.B. Bekomme ich für den +-16-Modus mit Full-Res folgende Werte:
1
X: -370 Y:-400 Z:9564
 (in mG).

Ich rechne in mG da G Kommazahlen produzieren würde und die ja viel 
Rechenleistung brauchen ^^

Ich hätte erwartet, dass X und Y irgendwo so bei +-100 und Z bei 1000 
(mehr oder weniger) ist.

Da ich im 16g Modus mit Full-Res bin bedeutet das, dass ich den Messwert 
mit 4 malnehmen muss um den tatsächlichen Wert zu bekommen (4mG/LSB):
1
  //read X-Axis
2
  x0 = readRegister(0x80 | 0x32);
3
  x1 = readRegister(0x80 | 0x33);
4
  
5
  //read Y-Axis
6
  y0 = readRegister(0x80 | 0x34);
7
  y1 = readRegister(0x80 | 0x35);
8
  
9
  //read Z-Axis
10
  z0 = readRegister(0x80 | 0x36);
11
  z1 = readRegister(0x80 | 0x37);
12
  
13
  x = (int16_t)((x1 << 8) | x0);
14
  y = (int16_t)((y1 << 8) | y0);
15
  z = (int16_t)((z1 << 8) | z0);
16
  
17
  //+/- 16g mode & full-res: 4mg/LSB
18
  *x_val = x*4;
19
  *y_val = y*4;
20
  *z_val = z*4;

Das ist meine Initialisierung:
1
  write_command = ((0x00 | 0x31) << 8) | 0b01001011;//set SPI 3wire & 4g range & full-res
2
  writeCommand(write_command); 
3
  write_command = ((0x00 | 0x2D) << 8) | 0x08; //Enable measurements
4
  writeCommand(write_command);
5
  write_command = ((0x00 | 0x2C) << 8) | 0x0A; //100Hz data rate
6
  writeCommand(write_command);

Mache ich was falsch oder hab ich einen davon erwischt?

Beitrag "Defekte ADXL345 Beschleunigungssensoren aus der Bucht!"

: Bearbeitet durch User
von Wolfgang (Gast)


Lesenswert?

Jan H. schrieb im Beitrag #4563038:
> Wenn dein Sensor nicht absolut im Wasser montiert ist sind deine Werte
> gar nicht so schlecht.

Wie meinst du das mit dem Wasser?

von Jan H. (jan_m_h)


Lesenswert?

Wolfgang schrieb:
>> Wenn dein Sensor nicht absolut im Wasser montiert ist sind deine Werte
>> gar nicht so schlecht.
>
> Wie meinst du das mit dem Wasser?

„Im Wasser“ heißt waagrecht.

Ich hab mein Text gelöscht, weil da ein Denkfehler drin ist: der Sensor 
misst in g, nicht im m/s², damit sind natürlich meine erwarteten Werte 
falsch.

von Wolfgang (Gast)


Lesenswert?

Jan H. schrieb:
> „Im Wasser“ heißt waagrecht.

Selbst wenn der Sensor sauber ausgerichtet ist, wären die Werte ok. Laut 
Datenblatt sollen der Offset von x und y im Bereich -150..+150mg liegen.

von Max M. (maxmicr)


Lesenswert?

Danke für eure Antworten,

Wolfgang schrieb:
> Selbst wenn der Sensor sauber ausgerichtet ist, wären die Werte ok. Laut
> Datenblatt sollen der Offset von x und y im Bereich -150..+150mg liegen.

Der Sensor liegt waagerecht auf dem Tisch.
Möglicherweise hab ich das Datenblatt dann nicht verstanden aber wie 
kann ein Wert von 9000 mG (das wären 9G) okay sein? Da müsste doch nach 
meinem Verständnis nichts deutlich größeres als 1000 rauskommen?

: Bearbeitet durch User
von Wolfgang (Gast)


Lesenswert?

Max M. schrieb:
> write_command = ((0x00 | 0x31) << 8) | 0b01001011;//set SPI 3wire & 4g
> range & full-res

Hier setzt du bestimmt nicht de 4g Range (Datenblatt Tab.21)

von Max M. (maxmicr)


Lesenswert?

Wolfgang schrieb:
> Hier setzt du bestimmt nicht de 4g Range (Datenblatt Tab.21)

Ups, sorry. Hab vergessen den Kommentar zu ändern. Ich hab zum Testen 
diverse Modi durchprobiert. Trotzdem müsste meine Umrechnung des 
Messwertes in mG für den 16g-Modus in Ordnung sein, oder?

Ich verstehe immer noch nicht, wie ein Wert von 9000 für die Z-Axe in 
Ordnung sein kann.

von Wolfgang (Gast)


Lesenswert?

Max M. schrieb:
> Ich verstehe immer noch nicht, wie ein Wert von 9000 für die Z-Axe in
> Ordnung sein kann.

Erstmal willst du doch wissen, ob dein Sensor richtig läuft. Dafür 
kannst du einen der zahllosen Beispielcodes auf deinen µC laden und die 
Ergebnisse mit den bekannten Werten vergleichen, z.B.
https://learn.adafruit.com/adxl345-digital-accelerometer/programming

Wenn du dich der richtigen Funktion deines Sensors versichert hast, 
kannst du dich um deine Software und das Datenblattverständniss 
kümmern.

von Max M. (maxmicr)


Lesenswert?

Wolfgang schrieb:
> Erstmal willst du doch wissen, ob dein Sensor richtig läuft. Dafür
> kannst du einen der zahllosen Beispielcodes auf deinen µC laden und die
> Ergebnisse mit den bekannten Werten vergleichen, z.B.

Ich benutze aber keinen Arduino :(

von Wolfgang (Gast)


Lesenswert?

Max M. schrieb:
> Ich benutze aber keinen Arduino :(

Arduino ist ein Abstraktionslayer für die Software. An welchem Prozessor 
soll dein Sensor denn laufen?

von visitor (Gast)


Lesenswert?

Warum testest du dein Programm nicht mal mit vorberechneten Werten 
durch? Diese am besten mit einem zweiten UC via SPI deinem Programm 
zuführen. Danach wirst du schnell die Fehlerquelle lokalisren können. 
Das was hier passiert ist nur ein rumraten bzgl. Einer möglichen 
Ursache. Es selbst systematisch abzuklopfen sollte wesentlich schneller 
gehen.

von Max M. (maxmicr)


Lesenswert?

Wolfgang schrieb:
> An welchem Prozessor
> soll dein Sensor denn laufen?

STM8

visitor schrieb:
> Warum testest du dein Programm nicht mal mit vorberechneten Werten
> durch? Diese am besten mit einem zweiten UC via SPI deinem Programm
> zuführen.

Ja, okay. Das Probier ich mal.

von Wolfgang (Gast)


Lesenswert?

visitor schrieb:
> Warum testest du dein Programm nicht mal mit vorberechneten Werten
> durch?

Schon den Sensor mal um 45°, 90° und 180° auf verschiedenen Achsen zu 
kippen, könnte einen Hinweis liefern, ob er grundsätzlich richtig 
arbeitet. Wenn man erstmal auf die Rohdaten guckt, könnte man die 
Sensorfunktion unabhängig von der Auswertesoftware beurteilen.

von Max M. (maxmicr)


Lesenswert?

Wolfgang schrieb:
> Schon den Sensor mal um 45°, 90° und 180° auf verschiedenen Achsen zu
> kippen, könnte einen Hinweis liefern, ob er grundsätzlich richtig
> arbeitet.

Werte vor dem Drehen:
X: 376 Y: -396 Z: 9640

Nach 180° Drehung:
X: -380 Y: -240 Z: 7600

Nach 90° Drehung:
X: 888 Y:-380 Z: 8650

90° in die andere Richtung:
X: -1600 Y:-340 Z: 8600

Hm...?

: Bearbeitet durch User
von Wolfgang (Gast)


Lesenswert?

Max M. schrieb:
> Hm...?

Vielleicht solltest du den Sensor nicht immer auf dem Tisch liegen 
lassen, sondern auch mal senkrecht oder auf den Kopf stellen ;-)

von Max M. (maxmicr)


Lesenswert?

Wolfgang schrieb:
> Vielleicht solltest du den Sensor nicht immer auf dem Tisch liegen
> lassen, sondern auch mal senkrecht oder auf den Kopf stellen ;-)

Das hab ich doch gemacht? Inwiefern kann ich aus den Werten bei 90° und 
bei 180° rauslesen, ob die Sensor i.O. ist?

von Sven B. (scummos)


Lesenswert?

Um welche Achse drehst du denn? Leg den Sensor doch mal so hin dass die 
Chipseite die vorher nach unten zeigte jetzt nach oben zeigt ... wenn 
sich dann das Vorzeichen vom z-Wert nicht umdreht ist der Sensor kaputt 
oder was ganz arg falsch ...

Was du hier machst sieht von den Werten erstmal so aus als ob du den 
Sensor auf dem Tisch liegend um die Achse drehst die nach oben zeigt, 
das bewirkt natürlich nur einen sekundären Effekt wenn der Tisch schräg 
steht ...

: Bearbeitet durch User
von Max M. (maxmicr)


Lesenswert?

Sven B. schrieb:
> Was du hier machst sieht von den Werten erstmal so aus als ob du den
> Sensor auf dem Tisch liegend um die Achse drehst die nach oben zeigt,
> das bewirkt natürlich nur einen sekundären Effekt wenn der Tisch schräg
> steht ...

Hab ich aber nicht sonder das was du sagst:

Sven B. schrieb:
> Leg den Sensor doch mal so hin dass die
> Chipseite die vorher nach unten zeigte jetzt nach oben zeigt

Sven B. schrieb:
> wenn
> sich dann das Vorzeichen vom z-Wert nicht umdreht ist der Sensor kaputt
> oder was ganz arg falsch ...

:(

von Wolfgang (Gast)


Lesenswert?

Max M. schrieb:
> Werte vor dem Drehen:
> X: 376 Y: -396 Z: 9640
>
> Nach 180° Drehung:
> X: -380 Y: -240 Z: 7600

Wenn also "180° Drehung" bedeutet: Sensor-Chip liegt auf dem Kopf, dann 
misst dein Sensor als Z-Komponente einen Wert von 1020mg und die 
restlichen 8620 sind ein Offset. Das wäre doch erstmal nicht so abwegig.

Z_Offset = (Z_0° - Z_180°)/2

Mmh ... nicht schön, aber vielleicht kann man damit umgehen. Bestimme 
erstmal für alle Achsen den Offset, indem du die jeweilige Achse des 
Sensor einmal sauber nach unten und einmal nach oben richtest. Nach 
Offset-Korrektur müsste in 45° Stellung bezüglich der Vertikalen immer 
zwei Achsen den gleichen Wert produzieren.

von Max M. (maxmicr)


Lesenswert?

Wolfgang schrieb:
> dann
> misst dein Sensor als Z-Komponente einen Wert von 1020mg und die
> restlichen 8620 sind ein Offset.

Wie kommst du auf die 1020mg?

Das seltsame ist, wenn ich die Range auf +-2g stelle, ändert sich die 
Z-Komponente gar nicht mehr.

Edit:

Okay, ich hab mal einen kleinen Test für die Z-Werte gemacht:

2g-Range:
2044

4g-Range:
4092

8g-Range:
8188

16g-Range:
9632

Der Unterschied zwischen 2g und 4g beträgt 2048, der Unterschied 
zwischen 4g und 8g beträg 4096. Der Unterschied zwischen 8g und 16g 
beträg 1444.

Wenn ich dann diese Rechnung mache:
1
*z_val = (z*4) - (1444+4096+2048+1024)

Komme ich auf 1020mg, was ja halbwegs passen würde. Jetzt ändert sich 
auch das Vorzeichen wenn ich den Sensor umdrehe.

Ich ziehe also jedesmal 2^10, 2^11, 2^12 ab.

Die X- und Y-Achse zu kalibrieren ist aber irgendwie nicht ganz so 
offensichtlich.

Wenn ich um die Y-Achse drehe:

Position 1 (in Richtung der Y-Achse):
-1580

Position 2 (entgegen der Y-Achse):
884

Das gleiche mit der X-Achse:

Position 1 (in Richtung der X-Achse):
-1590

Position 2 (entgegen der X-Achse):
888

: Bearbeitet durch User
von Wolfgang (Gast)


Lesenswert?

Max M. schrieb:
> Wie kommst du auf die 1020mg?

Wenn
1
Z=9640 für Z_Offset + Erdbeschleunigung
und
1
Z=7600 für Z_Offset - Erdbeschleunigung
ist der Rest weniger als kleines Einmaleins.

Das würde sich auch gut mit den Z=8600 bzw. Z=8650 für (mehr oder 
weniger genau) auf der Seite liegenden Chip (90° ?) decken.

von Wolfgang (Gast)


Lesenswert?

Max M. schrieb:
> Das seltsame ist, wenn ich die Range auf +-2g stelle, ändert sich die
> Z-Komponente gar nicht mehr.

Wie auch. Bei gesetztem FULL_RES Bit hast du immer einen 
Skalierungsfaktor von 4 mg/LSB (s. Datenblatt Rev 3, S.27)

von Max M. (maxmicr)


Lesenswert?

Wolfgang schrieb:
> Bei gesetztem FULL_RES Bit hast du immer einen
> Skalierungsfaktor von 4 mg/LSB

Sorry, das verstehe ich nicht. Warum kann sich der Wert nicht mehr 
ändern nur weil der Skalierungsfaktor gleich bleibt? Und warum ändern 
sich X- und Y Wert weiterhin?

Edit:

Irgendwie klappt es nicht ganz, die X und Y Werte zu korrigieren.

Wenn ich annehme das in Position 1 ~-1000mg herrschen, dann müsste ich 
~580 zum Wert dazuzählen. Wenn ich das aber mache, habe ich in Position 
2 ~1400mg. Wie löse ich das Dilemma?

: Bearbeitet durch User
von Bernhard S. (b_spitzer)


Lesenswert?

Könnte es sein, dass deine SPI-Routine das oberste Bit schluckt? Stimmt 
der SPI-Mode?
Schau dir mal die Rohwerte byteweise an. Bei 4mg/Bit ist die 
Vektor-Summe sqrt(x^2+y^2+z^2) der 3 Beschleunigungen beim ruhenden 
Sensor etwa 250. Wenn eine der Komponenten negativ ist (Sensor gedreht 
oder kleiner Wert mit negativem Offset) müsste der Wert im 
2er-Komplement erscheinen, also High-Byte 0xff und Low-Byte entsprechend 
mit führenden 1en.
Eigentlich dürften in den oberen Bytes nie andere Werte als 0x00 und 
0xff stehen, solange man den Sensor nicht heftig bewegt.

von Max M. (maxmicr)


Lesenswert?

Bernhard S. schrieb:
> Eigentlich dürften in den oberen Bytes nie andere Werte als 0x00 und
> 0xff stehen, solange man den Sensor nicht heftig bewegt.

Beim Debuggen bekomme ich diese dezimalen Werte:

x0: 169
x1: 255

y0: 102
y1: 255

z0: 98
z1: 0

Müsste also laut deiner Aussage passen?

: Bearbeitet durch User
von Bernhard S. (b_spitzer)


Lesenswert?

Damit ist dein X-Wert -97. dein Y-Wert -154, der Z-Wert 98
Vektorsumme ist 206, also etwas zu wenig. Sollte 250 sein.

Damit scheint was mit deiner Umrechnung nicht zu stimmen. Welche 
Datentypen haben X0, X1 und X_Val?

von Max M. (maxmicr)


Lesenswert?

Danke für deine Hilfe!

Das sind meine Datentypen:
1
void readXYZ(int16_t *x_val, int16_t *y_val, int16_t *z_val){
2
  uint8_t x0 = 0;
3
  uint8_t x1 = 0;
4
  uint8_t y0 = 0;
5
  uint8_t y1 = 0;
6
  uint8_t z0 = 0;
7
  uint8_t z1 = 0;
8
  
9
  int16_t x = 0;
10
  int16_t y = 0;
11
  int16_t z = 0;
12
}

: Bearbeitet durch User
von Max M. (maxmicr)


Lesenswert?

Hm, hat noch jemand Ideen was ich falsch mache? Verzweifle mittlerweile 
fast daran :(

von Bernhard S. (b_spitzer)


Lesenswert?

Wenn der Rest deines Programms in der readXYZ-Funktion steht, sollte es 
eigentlich passen. Gehen deinem Controller die Register für die 
temporären Variablen aus? Anderes Memory-Model einstellen, oder mal 
x_val, y_val und z_val als globale Varaibeln anlegen und testen.

Ebenso mal die Werte von x, y und z im Debugger überprüfen.

Brauchst du wirklich die Pointer zum Auslesen der Werte? Rufst Du die 
Funktion readXYZ(a,b,c) auch mal mit readXYZ(e,f,g) auf?

von Max M. (maxmicr)


Lesenswert?

Ich grüße dich,

Bernhard S. schrieb:
> Gehen deinem Controller die Register für die
> temporären Variablen aus? Anderes Memory-Model einstellen

Öhm, gute Frage. Ich hoffe mal nicht, mit 1kb RAM sollte der schon 
einige Variablen abkönnen.

Bernhard S. schrieb:
> oder mal
> x_val, y_val und z_val als globale Varaibeln anlegen und testen.

Hab ich gemacht, ändert leider nichts an den Werten.

Bernhard S. schrieb:
> Brauchst du wirklich die Pointer zum Auslesen der Werte?

Bei globalen Variablen nicht, ich fand / finde es nur schwierig, Arrays 
in C zurückzugeben.

Bernhard S. schrieb:
> Rufst Du die
> Funktion readXYZ(a,b,c) auch mal mit readXYZ(e,f,g) auf?

Was genau  meinst du mit e, f, g?

Die Z-Achse lässt sich anscheinend ganz gut konfigurieren. Aber die 
anderen Achsen nicht. In der vertikalen Lage der X-Achse ist der Wert 
einmal bei ~ 880 und einmal bei ~ -1560. Wenn ich beim ersten Wert 
120 addiere, komme ich beim zweiten Wert noch lange nicht bei -1000 
(das sollte der Wert bei vertikaler Ausrichtung in der Achse ja haben).

: Bearbeitet durch User
von Max M. (maxmicr)


Angehängte Dateien:

Lesenswert?

So, ich hab nun eine Excel-Tabelle mit den raw-daten ohne und mit 
self-test enabled erstellt. Dabei kam heraus, dass die Self-test Offset 
Werte über bzw. unter den maximal bzw. minimal Werten des Datenblatts 
sind. Ich hab die Excel-Datei einmal angehängt. Was genau bedeutet das 
für den Sensor, kaputt? Laut Datenblatt:
1
If the self-test change is within the valid range, the test is considered successful. Generally, a part is considered to pass if the minimum magnitude of change is achieved. However, a part that changes by more than the maximum magnitude is not necessarily a failure.

Aber was genau das bedeutet steht da auch nicht? grr

: Bearbeitet durch User
von W.A. (Gast)


Lesenswert?

Max M. schrieb:
> Aber was genau das bedeutet steht da auch nicht? grr

Was verstehst du an "Generally, a part is considered to pass if the 
minimum magnitude of change is achieved. However, a part that changes by 
more than the maximum magnitude is not necessarily a failure." nicht?

von Werner M. (Gast)


Lesenswert?

Max M. schrieb:
> Aber was genau das bedeutet steht da auch nicht?

Stimmt, die Details stehen im Datenblatt auf S.22 im Abschnitt 
"SELF-TEST".

von Max M. (maxmicr)


Lesenswert?

W.A. schrieb:
> Was verstehst du an "Generally, a part is considered to pass if the
> minimum magnitude of change is achieved. However, a part that changes by
> more than the maximum magnitude is not necessarily a failure." nicht?

Ich kann nicht darauf schließen, dass der Sensor wegen Überschreiten der 
Grenzen fehlerhaft ist, warum gibt es sie dann?

Werner M. schrieb:
> Stimmt, die Details stehen im Datenblatt auf S.22 im Abschnitt
> "SELF-TEST".

Danke!

von Bernhard S. (b_spitzer)


Lesenswert?

Ich schätze mal, dass viele Sensoren die man als "Arduino"-Modul für ein 
paar Euro bekommt bei den Paramtern an der Kante der Spezifikation 
liegen. Sozusagen Ausschuß-Verwertung...

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.