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:-370Y:-400Z: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
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?
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.
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.
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?
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)
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.
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.
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 :(
Max M. schrieb:> Ich benutze aber keinen Arduino :(
Arduino ist ein Abstraktionslayer für die Software. An welchem Prozessor
soll dein Sensor denn laufen?
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.
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.
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.
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...?
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 ;-)
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?
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 ...
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 zeigtSven B. schrieb:> wenn> sich dann das Vorzeichen vom z-Wert nicht umdreht ist der Sensor kaputt> oder was ganz arg falsch ...
:(
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.
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
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.
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)
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?
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.
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?
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?
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?
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).
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
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?
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!
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...