Forum: Mikrocontroller und Digitale Elektronik Beschleunigungssensor


von doug (Gast)


Lesenswert?

Hallo zusammen,

ich habe ein Programm für folgenden Beschleunigungssensor geschrieben,
http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/APPLICATION_NOTE/CD00229883.pdf
welches Sensordaten einfach nur per UART ausgibt.
Dieses Programm wollte ich jetzt mit einem anderen Sensor laufen lassen
http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00250937.pdf
und erhalte falsche Sensorwerte.

Obwohl der Sensor auf dem Tisch liegt, gibt er nicht das erwartete 1g 
auf der z-Achse aus und außerdem ändern sich die Werte ständig.
Eigentlich kann das nicht sein, da die Sensorposition sich auch nicht 
ändert.

Ich habe für den neuen Sensor einfach nur die Register etwas 
umgeschrieben, da sie sich etwas vom Aufbau unterscheiden.

Grundsätzlich müsste es doch richtig sein das Status Register zu pollen 
um zu sehen ob neue Daten vorhanden sind.
Danach pollen ob Daten überschrieben wurden und dann eben die Output 
Register einfach auslesen.

Wär echt klasse, wenn mir das jemand bestätigen würde oder mir einen 
Fehler in meinem Modell aufzeigt.

von Mr Tannnoy (Gast)


Lesenswert?

Also, wenn er nur so auf dem Tisch liegt, wird er ja also auch nicht 
bewegt. Da sollte man für alle Achsen 0,0 messen.

von Karl H. (kbuchegg)


Lesenswert?

doug schrieb:

> Obwohl der Sensor auf dem Tisch liegt, gibt er nicht das erwartete 1g
> auf der z-Achse aus und außerdem ändern sich die Werte ständig.
> Eigentlich kann das nicht sein, da die Sensorposition sich auch nicht
> ändert.

Entweder du hast einen Programmfehler.
Oder aber: Willkommen in der wunderbaren Welt der Realität, in der 
Sensoren schon auch mal rauschen und so manches scheinbar ganz einfache 
Prinzip der physikalischen Theorie für die Praxis unbrauchbar machen.

von Karl H. (kbuchegg)


Lesenswert?

Mr Tannnoy schrieb:
> Also, wenn er nur so auf dem Tisch liegt, wird er ja also auch nicht
> bewegt. Da sollte man für alle Achsen 0,0 messen.

Nö.
in allen Achsen 0 misst man nur im freien Fall.

von Mr Tannnoy (Gast)


Lesenswert?

0,0 G im freien Fall???

Ich tippe da eher auf 1G.

Schau mal in ein Physikbuch...

1G=9,81m/s²

Beschleunigung bedeutet die Geschwindigkeit ändern!

von Karl H. (kbuchegg)


Lesenswert?

Mr Tannnoy schrieb:
> 0,0 G im freien Fall???
>
> Ich tippe da eher auf 1G.
>
> Schau mal in ein Physikbuch...

Genau.
Schau da mal rein.

> Beschleunigung bedeutet die Geschwindigkeit ändern!

Aber du kannst sie mit dem Sensor nicht messen.
PS: Der Sonsor misst nicht wirklich die Beschleunigung direkt. Das geht 
nämlich ohne externen Bezugspunkt nicht. Was er misst, ist die Kraft, 
die auf ihn (genauer: einen Teil von ihm) wirkt. Und im freien Fall ist 
er in sich kräftefrei. Erst wenn er auf dem Tisch liegt, kann er wieder 
die Kraft feststellen, die die Tischplatte auf ihn ausübt um ihn am 
Fallen zu hindern.

von asfdsadfsadf (Gast)


Lesenswert?

Mr Tannnoy schrieb:
> Also, wenn er nur so auf dem Tisch liegt, wird er ja also auch nicht
> bewegt. Da sollte man für alle Achsen 0,0 messen.

nö. Gibt ja auch die Erdbeschleunigung.

von doug (Gast)


Lesenswert?

In Ruhelage auf dem Tisch misst er x=0g y=0g z=1g.
Das steht auch so im Datenblatt.

Mit dieser Erkenntnis ist aber mein Problem nicht gelöst.
Die Sache mit dem möglichen Rauschen werd ich mir mal näher ansehn.

von Karl H. (kbuchegg)


Lesenswert?

doug schrieb:
> In Ruhelage auf dem Tisch misst er x=0g y=0g z=1g.
> Das steht auch so im Datenblatt.

Logisch. Geht auch mit einem reinen Beschleunigungssensor nicht anders. 
Woher soll der denn auch wissen, wo 'unten' ist.
>
> Mit dieser Erkenntnis ist aber mein Problem nicht gelöst.
> Die Sache mit dem möglichen Rauschen werd ich mir mal näher ansehn.

Fangen wir mal so an.
In welcher Größenordnung bewegen sich denn deine Werte?
Dann kann man schon mal abschätzen, ob es sich um Messrauschen handelt, 
oder ob eine Programmfehler wahrscheinlicher ist. Exakt 0.0/0.0/1.0 
wirst du nicht kriegen. Aber wenn die Werte +-2.0 rumspringen, dann ist 
das auch kein Rauschen mehr.

von doug (Gast)


Lesenswert?

Die Werte liegen zwischen 0 und ca. 2,5g.
Es ist heftig, dass sie immer variieren.

von Karl H. (kbuchegg)


Lesenswert?

doug schrieb:
> Die Werte liegen zwischen 0 und ca. 2,5g.

Ist zuviel für Rauschen.
Da hast du noch irgendwo einen Programmfehler

von doug (Gast)


Lesenswert?

Es ist halt so, dass das Programm mit dem LIS331DL welcher nur +-8g, 
400Hz, 8bit Datenregister hat funktioniert.

Der neue Sensor kann +-24g, 1kHz, High + Low Byte als Datenregister, 
also 16bit.

Das sind eigentlich nur die Unterschiede und deshalb versteh ich nicht, 
warum es auf dem Alten, aber nicht auf dem neuen läuft.

von Tom (Gast)


Lesenswert?

Hallo,
Was häufig falsch gemacht wird, ist die Reihenfolge der Bytes, wenn der 
Messwert größer als 8bit ist. Das Rauschen im letzten Bit wird dann 
schnell zu einem heftigen Signalwackeln.

Beste Grüße, Tom

von doug (Gast)


Lesenswert?

Tom schrieb:
> Hallo,
> Was häufig falsch gemacht wird, ist die Reihenfolge der Bytes, wenn der
> Messwert größer als 8bit ist. Das Rauschen im letzten Bit wird dann
> schnell zu einem heftigen Signalwackeln.


Habe auch schon beide Bytes gedreht. Macht leider keinen Unterschied.
Ich schaue mir das Low und High Byte über ein Terminalprogramm an.

Auffällig ist aber, dass alle Sensorwerte durch 8 teilbar sind, also 
Vielfache von 8 sind.

Das find ich ziemlich seltsam.

von Peter II (Gast)


Lesenswert?

doug schrieb:
> Habe auch schon beide Bytes gedreht. Macht leider keinen Unterschied.

dann stimmt aber auf jeden Fall etwas nicht, wenn sich da nichts ändert.

von doug (Gast)


Lesenswert?

0 ist der Kleinste Wert der selten Auftritt und 240 der Maximale.

von doug (Gast)


Lesenswert?

Peter II schrieb:
> doug schrieb:
>> Habe auch schon beide Bytes gedreht. Macht leider keinen Unterschied.
>
> dann stimmt aber auf jeden Fall etwas nicht, wenn sich da nichts ändert.


Ne Idee?

von Michael H. (michael_h45)


Lesenswert?

doug schrieb:
> Ne Idee?
ja.
der fehler liegt im code.

von doug (Gast)


Angehängte Dateien:

Lesenswert?

Michael H. schrieb:

> ja.
> der fehler liegt im code.

Hi Michael,

hier mal das Programm.
Kann den Fehler einfach nicht finden.

von Udo S. (urschmitt)


Lesenswert?

doug schrieb:
> Kann den Fehler einfach nicht finden.

Wir auch nicht, weil wir weder deine Hardware haben, noch dein Programm 
und vor allem nicht die Messwerte sehen.
Wie wäre es wenn du dir etwas mehr Mühe gibst und vieleicht mal das 
komplette compilierbare Programm anhängst, und mal eine Tabelle von 
echten Messwerten hier reinstellst.

von Timmo H. (masterfx)


Lesenswert?

Du musst folgendes beachten.
Der ST hat nur ein 16 Bit output und nicht Auflösung. In dem 16 Bit Wert 
steht nur ein 12 Bit wert im zweierkomplement um 4 Bits nach links 
geshiftet drin.
Du musst also sowas machen wie
1
int16_t acc_x;
2
3
...
4
acc_x = SPI_MasterRead(OUTZ_H)<<8;  
5
acc_x |= (SPI_MasterRead(OUTZ_L))&0xFF;  
6
7
acc_x >>= 4; //um 4 Bits nach rechts
Dann hast du den realen Wert, den du dann noch entsprechend deiner 
"Range" skalieren musst.

von Stephan (Gast)


Lesenswert?

doug schrieb:
> Danach pollen ob Daten überschrieben wurden und dann eben die Output
> Register einfach auslesen.

Welchen Sinn soll das eigentlich haben?
In Deinem Programm wartest du dann und sorgst so dafür, dass noch mehr 
Werte überschrieben werden.
Normal ists sch**egal wenn ein Wert verloren geht, das müsste schon ein 
heftiger Ruck (oder langsamme Abfragefrequenz) sein wenn 2 
aufeinanderfolgende Werte deutlich voneinander abweichen.


Stephan

von doug (Gast)


Angehängte Dateien:

Lesenswert?

Sorry Udo, kein Problem.

Hier ist das komplette Programm mit den Messwerten.
Habe die Messwerte mit HTerm dargestellt.

von doug (Gast)


Lesenswert?

Man sieht also high Byte und low byte immer im Wechsel, beginnend mit 
high byte.
Das high byte hat einen Offset von 4.

von Timmo H. (masterfx)


Lesenswert?

Dann shift das doch  mal so wie ich es gesagt habe... und spar dir 
erstmal das abziehen des Offsets (wie kommt du überhaupt auf -3 von 
HighByte)? Den Offset verwende ich um eine minimale Schräglage 
auszugleichen, also wenn dann nur im Low-Byte. "-3" im Highbyte 
entspricht ja schon 9,2g im +-24g bereich.
Willst du die Erdbeschleunigung abziehen? Wenn du die Lage damit 
bestimmen willst dann würde ich das nicht machen, und dann würde ich 
auch nicht den "großen" Messbereich nehmen.

Was genau willst du denn mit den Beschleunigungswerten machen?

von Udo S. (urschmitt)


Lesenswert?

doug schrieb:
> Das high byte hat einen Offset von 4.

Genau das ist dein Fehler, du hast keinen Offset von 3 oder 4 nur im 
High Byte. Wie Timmo gesagt hat, alle Werte der Low Bytes sind durch 16 
teilbar, das weist genau darauf hin, daß die 4 LSB Bits des Messwerts im 
high Nibble des Low Bytes stecken.
Also mal so addieren und shiften wie Timmo gesagt hat, und schon stimmen 
die Werte und du siehst nur noch normales Rauschen.
Wenn du dir solche Werte binär oder Hexadezimal aufschreibst oder 
printest dann siehst du sowas deutlich schneller.

von doug (Gast)


Lesenswert?

Danke euch beiden.
Hatte dummerweise angenommen, dass es sich um 16bit Zweierkomplement 
Daten handelt.

von Timmo H. (masterfx)


Lesenswert?

doug schrieb:
> Danke euch beiden.
> Hatte dummerweise angenommen, dass es sich um 16bit Zweierkomplement
> Daten handelt.
Ist ja auch ein 16 Bit Wert im Zweierkomplement nur repräsentiert das 
nur den 12 Bit Wert, wie ja auch im Datenblatt auf Seite 9 in der 
Tabelle steht. ST aligned das halt immer ganz links um damit das 
Vorzeichen im int16 passt. Bei Freescale muss man z.B. oftmals das 12. 
Bit zur Vorzeichenerkennung verwenden und dann selbst den Rest mit "1" 
auffüllen. Oder man shiftet es erst 4 nach links und dann wieder beide 
Bytes um 4 nach rechts. Hat beides vor und Nachteile. Bei manchen 
Sensoren kann man das auch selbst bestimmen ob nun rechts oder links 
ausgerichtet. Am besten ist es natürlich wenn die Auflösung gleich 16 
Bit ist und nicht nur 12 oder 14 Bit, aber das kostet dann halt wieder 
Geld (z.B Invensense MPU6050)
ST verzichtet oftmals halt gerne darauf das nochmals etwas zu 
verdeutlichen (bzw. wenn findest man das nur in Appnotes und nicht im 
Datenblatt)

von doug (Gast)


Lesenswert?

Timmo H. schrieb:

> ST verzichtet oftmals halt gerne darauf das nochmals etwas zu
> verdeutlichen (bzw. wenn findest man das nur in Appnotes und nicht im
> Datenblatt)

Bin leider darauf reingefallen.
Leider konnte ich zum LIS331HH keine Application note finden.

von Timmo H. (masterfx)


Lesenswert?

Ja Appnotes gibts nicht für alles. Wenn man öfter mit ST arbeitet dann 
kennt man irgendwann die Fallstricke.

von Udo S. (urschmitt)


Lesenswert?

Ist doch oft bei A/D Wandlern genauso. Damit musst du nicht shiften wenn 
dich nur ein 8 Bit Wert interessiert, dann kannst du einfach die unteren 
Bits weglassen.

von Timmo H. (masterfx)


Lesenswert?

Ja stimmt. Das ist auch wohl der Hintergedanke beim left align.
Man braucht dann nur halt 3 Bytes auslesen (für alle Achsen) anstatt 6 
welche dann geshiftet werden müssten um dann wieder nur 8 Bit zu nutzen.
Dann hat man auch auch gleich das Rauschen weg wenn man die untersten 4 
Bit nicht benutzt :D

von doug (Gast)


Angehängte Dateien:

Lesenswert?

Jetzt wollte ich mal die sleep to wake Funktion ausprobieren und wundere 
mich darüber warum am INT1 oder auch INT2 pin ich keinen Auschlag 
erhalte, wenn ich den Sensor anrege.

Hab hier die Scope Bilder.

Auf dem einen Bild sieht man den INT1pin Rauschen wenn ich den Sensor 
ohne sleep Mode configuriere. Das Rauschen ist mir egal, da ich ja das 
Signal nicht weiterverwende, in diesem Fall.

Wenn ich jetzt den Sensor im sleep Mode aktiviere sehe ich, dass das 
Rauschen annähernd verschwindet. Leider erhalte ich aber keinen 
Auschlag, wenn ich den Sensor anrege.

Der Sensor befindet sich im sleep mode, aber der INT1pin ändert sich 
nicht bei Anregung des Sensors.

Hier ist der Code.

Hat jemand ne Idee?

von doug (Gast)


Lesenswert?

Hat sich schon erledigt.

Der Sensor bei 24g ist erheblich träger als mein alter Sensor mit 8g und 
deshalb hatte ich mehr Emfpindlichkeit erwartet.

Es funktioniert jetzt. Bei stärkerer Anregung.

von doug (Gast)


Angehängte Dateien:

Lesenswert?

Habe jetzt versucht 3 Sensoren hintereinander zum laufen zu bringen und 
versteh nicht, warum es nicht geht.

Eigentlich müsste es........

Es ist so, dass die Daten nur langsam rauskommen, was daran liegt, dass 
Daten überschrieben werden.

D.h. Er landet jeden Durchlauf in der if( status_reg & 0x40) und dort 
steht dann in der delay, die mir anzeigt, dass Daten überschrieben 
werden.

Bin ziemlich verzweifelt weil es nicht klappt.

Wäre echt super wenn sich das einer von Euch nochmal anschauen würde.

Super verzweifelt.

von doug (Gast)


Lesenswert?

Kurzfassung:

Die Sensoren werden 1,2,3,1,2,3... ausgelesen.
Dummerweise kommt es jedesmal (bei jedem Auslesen) zu einem overwrite 
der Daten und ich kann es mir nicht erklären.
------------------------------------------------------------------------ 
-
Mit meinem 1 Sensor-Programm kann ich problemlos ca. 1000Werte/Sekunde 
auslesen und es kommt nie zu einem overwrite im STATUS_REG.

Der einzige Unterschied bei meinem neuen Programm zum alten ist, dass 
ich jetzt 3 CS mache anstatt nur einen und jedesmal eine if-Abfrage 
mache, um zu sehen, um welchen Sensor es sich handelt.

Diese Erneuerungen können doch nicht soviel Zeit fressen um einen 
Overwrite zu verursachen.

Kann mir bitte jemand weiterhelfen?

von Stephan (Gast)


Lesenswert?

doug schrieb:
> D.h. Er landet jeden Durchlauf in der if( status_reg & 0x40) und dort
> steht dann in der delay, die mir anzeigt, dass Daten überschrieben
> werden.

Dann lass die Wartezeit halt weg!
Oder für was soll die gut sein, ausser das Zeitverhalten zu verhunzen 
und die Diagnose zu erschweren?

von doug (Gast)


Lesenswert?

Stephan schrieb:

> Dann lass die Wartezeit halt weg!
> Oder für was soll die gut sein, ausser das Zeitverhalten zu verhunzen
> und die Diagnose zu erschweren?

Eigentlich soll es mir die Diagnose erleichtern.
Ich habe das Programm länger laufen lassen und am Terminal Programm 
gesehn, dass jeder Wert 1000ms verzögert rauskommt.

Das bedeutet ich habe jeden Durchgang einen overwrite.

Ohne die delay-Zeit könnte ich doch niemals den overwrite erkennen.
Das wäre mit einem Oszi vielleicht möglich,aber viel zu aufwendig.
So ist es doch angenehmer.

Durch das Auskommentieren der delay-Zeit erhalte ich jetzt ca 
5600Werte/sec von 3 Sensoren.

D.h. ca. 1867Werte/sec von einem Sensor aber eben immer nur mit 
overwrite, was uns ja die delay, auch wenn sie jetzt auskommentiert ist 
gezeigt hat.

Ich muss die Ursache für den overwrite finden.

von Stephan (Gast)


Lesenswert?

doug schrieb:
> Durch das Auskommentieren der delay-Zeit erhalte ich jetzt ca
> 5600Werte/sec von 3 Sensoren.

Da ist doch schon der Hinweis...
5600 16-Bit-Werte / s nehme ich an.

Diw Werte kommen viel zu schnell für 3x1kHz und auuffällig nahe an dem 
was über den UART bei 115.2kBaud maximal geht.
> Deine Statusabfrage ist unwirksam. Wenn da einmal Bit 4 gesetzt ist wird nie 
mehr abgefragt. Und wenn da Bit 7 auch gesetzt war ...
> abgefragten Statuswert zurücksetzen

Außerdem

5600 * 1/s  2  (8+2) = 112kBaud und dein Programm wartet solange bis 
der UART wieder frei ist. Bleiben am Ende 22k Takte/Sekunde oder knapp 
40 Takte pro Schleifendurchlauf übrig:
Während das 1. Byte gesendet wird steht das Programm quasi.
Während das 2. Byte gesendet wird läuft die Haupschleife weiter, SPI 
wird abgefragt und dann steht das Programm wieder weil das 2. Byte aus 
dem vorherigen Durchgang noch nicht fertig gesendet wurde.
Die 40 Takte gehen für 2* Funktionsaufruf UART_send und 2* Nachladen 
innerhalb von UART_send drauf.

Für sowas nimmt man Interrupts und nen Sendepuffer.
Momentan läuft dein Programm noch schön gleichmäßig, vom UART 
eingetaktet. Sobald du aber noch alle paar Durchläufe Mittelwerte oder 
ähnliches ausgeben willst werden die Zeitscheiben ungleichmäßig.

Außerdem #2

Hast du wirklich 8MHz CPU-Frequenz? Da dürfte bei 115.2kBaud ziemlicher 
Datenmüll ankommen.


Stephan

von ... (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Logisch. Geht auch mit einem reinen Beschleunigungssensor nicht anders.
> Woher soll der denn auch wissen, wo 'unten' ist.

'Unten' ist natürlich auf der Seite, wo der Tisch. Sonst läge der Sensor 
schließlich nicht auf dem Tisch.

von doug (Gast)


Lesenswert?

Stephan schrieb:

> Diw Werte kommen viel zu schnell für 3x1kHz und auuffällig nahe an dem
> was über den UART bei 115.2kBaud maximal geht.
>> Deine Statusabfrage ist unwirksam. Wenn da einmal Bit 4 gesetzt ist wird nie
> mehr abgefragt. Und wenn da Bit 7 auch gesetzt war ...
>> abgefragten Statuswert zurücksetzen

> Für sowas nimmt man Interrupts und nen Sendepuffer.

Habe jetzt eine FIFO gepufferte ISR(USART_UDRE_vect), lösche meine
status_reg Variable am Ende der UART Übertragung, sprich am Ende der 
while(1).

Habe ich Dich mit dem status_reg so richtig verstanden?

Leider tritt immer noch das selbe Problem auf mit der Verzögerung.

Laut ATMEL lohnen sich bei SPI nur Interrupts, ab einem SPI Clock-Teiler 
von 64, gegenüber Polling.

Ich verstehe nicht, wieso sogar schon beim allerersten 
Schleifendurchlauf der overrun bzw. overwrite auftritt.

von doug (Gast)


Lesenswert?

Habe jetzt mit dem sleep-Mode des Mikrocontrollers rumgespielt und es 
tritt das selbe Phänomen auf.

Wenn er aufwacht werden die Daten auch verzögert ausgegeben.
Die Fehlerquelle muss also die gleiche sein.

Aber welche bloß?

von doug (Gast)


Lesenswert?

Der einzige Unterschied der jetzt entstanden ist, ist das die Werte 
falsch sind. In Ruhelage bekomme ich jetzt den Wert 255dec für Lowbyte.

Es muss doch ein Zusammenhang bestehen.

von Michael H. (michael_h45)


Lesenswert?

doug schrieb:
> Ich muss die Ursache für den overwrite finden.
warum? frag dich das doch mal...

von Stephan (Gast)


Lesenswert?

doug schrieb:
> Habe jetzt eine FIFO gepufferte ISR(USART_UDRE_vect), lösche meine
> status_reg Variable am Ende der UART Übertragung, sprich am Ende der
> while(1).
>
> Habe ich Dich mit dem status_reg so richtig verstanden?
>
> Leider tritt immer noch das selbe Problem auf mit der Verzögerung.

Ähem. Das ist ja ne do-while-Schleife. Kannst dir das Rücksetzen am Ende 
sparen (hab Mist erzäht).

doug schrieb:
> Laut ATMEL lohnen sich bei SPI nur Interrupts, ab einem SPI Clock-Teiler
> von 64, gegenüber Polling.
Die brauchen hier jedenfalls kaum Zeit.

doug schrieb:
> Ich verstehe nicht, wieso sogar schon beim allerersten
> Schleifendurchlauf der overrun bzw. overwrite auftritt.

Klär lieber mal warum "new data" scheinbar ohne Funktion ist (die zu 
hohe Ausleserate).
Evtl. weil du ZYXDA abprüfst, X und Y aktiv sind aber nie ausgelesen 
werden.

Außerdem die Sache mit der CPU-Frequenz und der Baudrate. 
115.2kBaud@8MHz geht eigentlich nicht.

Stephan

von doug (Gast)


Lesenswert?

Michael H. schrieb:
> doug schrieb:
>> Ich muss die Ursache für den overwrite finden.
> warum? frag dich das doch mal...

Da ich ein annähernd 100% funktionierendes Messsytem haben möchte.
Ich hatte mit 3 ähnlichen Sensoren bei annähernd gleichem Quellcode 
(Sensor Register etwas anders angeordnet) keine Probleme mit overwrite.
Hatte das STATUS_REG genauso abgefragt.

Deshalb interessiere ich mich dafür. Das ist für mich der Beweis, dass 
es geht, bzw. gehen kann. Es sei denn diese Methode sei bei 16bit Daten 
nicht möglich. Mein vorheriger Sensor hatte nur 8bit Output Daten.



Stephan schrieb:

> Klär lieber mal warum "new data" scheinbar ohne Funktion ist (die zu
> hohe Ausleserate).
> Evtl. weil du ZYXDA abprüfst, X und Y aktiv sind aber nie ausgelesen
> werden.
>
> Außerdem die Sache mit der CPU-Frequenz und der Baudrate.
> 115.2kBaud@8MHz geht eigentlich nicht.
>
> Stephan

Die X und Y-Achse waren immer disabled. Hatte versehentlich ZYXDA 
geprüft anstatt ZDA. Habe dies geändert aber immer noch keine 
Veränderung zu sehen.
Ausserdem habe ich jetzt F_CPU auf 7,3728MHz abgeändert.
Die UART Werte sind immer noch die gleichen in Ruhelage.
Sie liegen leicht unter 1g z-Achse durch Rauschen, genauso wie vorher.

Muss dazu sagen, dass ich den internen RC-Oszillator verwende, da egal 
bei welcher externen Quarz Fuse Einstellung es immer Probleme mit den 
UART Werten gab.

von doug (Gast)


Lesenswert?

Stephan schrieb:

> Klär lieber mal warum "new data" scheinbar ohne Funktion ist (die zu
> hohe Ausleserate).

Habe jetzt noch ausprobiert, ob sich durch ein langsameres Auslesen 
etwas verändert.
Leider ohne Erfolg.

von Uwe (Gast)


Lesenswert?

> internen RC-Oszillator
und
> Ausserdem habe ich jetzt F_CPU auf 7,3728MHz abgeändert.
Du scheinst gar nicht zu wissen was du machst !
Grundlagen lernen !

Bei internem RC geht UART eh nicht.
Aber bei SPI sollte es keine probleme geben da Takt mitgeliefert wird.

von doug (Gast)


Lesenswert?

Uwe schrieb:
>> internen RC-Oszillator
> und
>> Ausserdem habe ich jetzt F_CPU auf 7,3728MHz abgeändert.
> Du scheinst gar nicht zu wissen was du machst !
> Grundlagen lernen !
>
> Bei internem RC geht UART eh nicht.
> Aber bei SPI sollte es keine probleme geben da Takt mitgeliefert wird.

Moment.
Programmiere erst seit 5 Monaten.
Kannst du das bitte genauer erklären was du meinst?
Wieso geht UART bei Internem RC-Oszillator eh nicht?

von Stephan (Gast)


Lesenswert?

doug schrieb:
> Wieso geht UART bei Internem RC-Oszillator eh nicht?

Zu ungenau, bzw. zu große Temperaturabhängigkeit / Drift. Außerdem passt 
die Frequenz nicht sonderlich gut.
Damit kommt häufig nur Datenmüll raus.

Idealerweise nimmt man für schnelle Übertragungen (115.2kBaud ist 
schnell) Baudratenquarze. z.B. 7,3728MHz. "Gerade" Frequenzen (wie 
1-2-4-8MHz) funktionieren nur für niedrige Übertragungsraten.
Hier kannst mal ausrechnen: 
http://www.gjlay.de/helferlein/avr-uart-rechner.html
Toleranz sollte unter 1% liegen.

Stephan

von J.-u. G. (juwe)


Lesenswert?

doug schrieb:
> Wieso geht UART bei Internem RC-Oszillator eh nicht?

AVR Checkliste für UART:
http://www.mikrocontroller.net/articles/AVR_Checkliste#UART.2FUSART

von doug (Gast)


Lesenswert?

Stephan schrieb:
> doug schrieb:
>> Wieso geht UART bei Internem RC-Oszillator eh nicht?
>
> Zu ungenau, bzw. zu große Temperaturabhängigkeit / Drift. Außerdem passt
> die Frequenz nicht sonderlich gut.
> Damit kommt häufig nur Datenmüll raus.
>
> Idealerweise nimmt man für schnelle Übertragungen (115.2kBaud ist
> schnell) Baudratenquarze. z.B. 7,3728MHz. "Gerade" Frequenzen (wie
> 1-2-4-8MHz) funktionieren nur für niedrige Übertragungsraten.
> Hier kannst mal ausrechnen:
> http://www.gjlay.de/helferlein/avr-uart-rechner.html
> Toleranz sollte unter 1% liegen.
>
> Stephan


Heisst das man kann keinen 8MHz Quarz mit #define 7372800UL verwenden?
Wirklich nur den Quarz(wert) passend?

von spess53 (Gast)


Lesenswert?

Hi

>Heisst das man kann keinen 8MHz Quarz mit #define 7372800UL verwenden?
>Wirklich nur den Quarz(wert) passend?

Nein.
Ja.

MfG Spess

von Stephan (Gast)


Lesenswert?

doug schrieb:
> Heisst das man kann keinen 8MHz Quarz mit #define 7372800UL verwenden?
> Wirklich nur den Quarz(wert) passend?

Genau richtig.
Der Wert wird in Makros verwendet um z.B. Timer-Einstellungen, Teiler 
für UART, etc. auszurechnen. Wenn Du den falschen Wert reinschreibst 
werden die Einstellungen falsch gewählt.

Und nein. Die Angabe stellt nicht den internen Oszillator oder einen 
externen Quarz auf die Frequenz ein. Da hat genau die in der Hardware 
festgelegte Frequenz zu stehen.

Stephan

von Udo S. (urschmitt)


Lesenswert?

doug schrieb:
> Ausserdem habe ich jetzt F_CPU auf 7,3728MHz abgeändert.
> ...
> Muss dazu sagen, dass ich den internen RC-Oszillator verwende,

Und du glaubst nur weil du eine Definition in deinem Programm abänderst 
ändert sich der Takt mit dem dein µC getaktet wird?
Les mal hier das Tutorial bzgl Takterzeugung durch und schau dir mal ein 
Datenblatt genau an.

von doug (Gast)


Lesenswert?

Habe schon öfter gesehn, dass Leute z.B.

#define F_CPU 16000000UL zu beginn des Codes schreiben.

Heisst das, dass man ganzzahlige Vielfache verwenden kann?
Welchen Sinn macht das?

von doug (Gast)


Lesenswert?

Oder sagt man damit dem Compiler einfach nur, dass man einen 16MHz Quarz 
verwendet, also nix mit Teilern oder Vielfachen?

von spess53 (Gast)


Lesenswert?

Hi

>Habe schon öfter gesehn, dass Leute z.B.

>#define F_CPU 16000000UL zu beginn des Codes schreiben.

>Heisst das, dass man ganzzahlige Vielfache verwenden kann?
>Welchen Sinn macht das?

Nein. Die verwenden mit Sicherheit einen 16MHz-Quarz.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

doug

Wenn du mit dem Auto mit 130 km/h auf der Autobahn fährst, kannst du 
natürlich die Skala deines Tachos umzeichnen, so dass die Zahl bei der 
Nadel 185 lautet.
Du kannst das machen, ja. Ändert aber nichts daran, dass deine Auto 
trotzdem immer noch mit 130 fährt. Und wenn du Zeitberechnungen mit den 
am Tacho angezeigten 185 machst, dann wird da eben nicht das richtige 
rauskommen. Um 160 Kilometer zurückzulegen errechnest du mit den 185 
zwar 51 Minuten, brauchen wirst du aber trotzdem 1 Stunde 23 Minuten. 
Selbst wenn auf deinem Tacho 185 angezeigt wird.

So einfach ist das.
F_CPU ist die Information für den Compiler, wie schnell der µC getaktet 
wird. Und diese Information sollte tunlichst mit der Realität 
übereinstimmen. Weil sonst darauf basierende Berechnungen einfach nicht 
stimmen werden.

von doug (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> doug
>
> Wenn du mit dem Auto mit 130 km/h auf der Autobahn fährst, kannst du
> natürlich die Skala deines Tachos umzeichnen, so dass die Zahl bei der
> Nadel 185 lautet.
> Du kannst das machen, ja. Ändert aber nichts daran, dass deine Auto
> trotzdem immer noch mit 130 fährt. Und wenn du Zeitberechnungen mit den
> am Tacho angezeigten 185 machst, dann wird da eben nicht das richtige
> rauskommen. Um 160 Kilometer zurückzulegen errechnest du mit den 185
> zwar 51 Minuten, brauchen wirst du aber trotzdem 1 Stunde 23 Minuten.
> Selbst wenn auf deinem Tacho 185 angezeigt wird.
>
> So einfach ist das.
> F_CPU ist die Information für den Compiler, wie schnell der µC getaktet
> wird. Und diese Information sollte tunlichst mit der Realität
> übereinstimmen. Weil sonst darauf basierende Berechnungen einfach nicht
> stimmen werden.


Alles klar.

von doug (Gast)


Lesenswert?

Es war zwar wichtig, aber wir sind ganz schön vom Thema abgekommen.

Aktueller Stand:

Alle Hinweise befolgt, Problem leider noch nicht gelöst.


doug schrieb:
> Ich verstehe nicht, wieso sogar schon beim allerersten
> Schleifendurchlauf der overrun bzw. overwrite auftritt.

von doug (Gast)


Lesenswert?

Hab grad einen anderen Fehler entdeckt.
Mein High Byte hat immer den Wert 0x00, egal wie ich meinen Sensor 
anrege.

Hier der Codeausschnitt um den es geht:

    outZ_high = SPI_MasterRead(OUTZ_H, i);
    outZ_low = SPI_MasterRead(OUTZ_L, i);

    outZ =  outZ_high<<8;
    outZ |= outZ_low & 0xFF;
    outZ >>= 4;

    //UART zuerst high byte, dann low byte senden
    UART_send(outZ & 0xFF00);

    UART_send( outZ & 0x00FF);


Das müsste doch eigentlich richtig sein....

von J.-u. G. (juwe)


Lesenswert?

doug schrieb:
> //UART zuerst high byte, dann low byte senden
>     UART_send(outZ & 0xFF00);
>
>     UART_send( outZ & 0x00FF);
>
>
> Das müsste doch eigentlich richtig sein....

Nein. "outZ" ist bei Dir doch eine 16-Bit-Variable (besteht also aus 2 
Byte). Vor dem Senden musst Du "outZ" in zwei 8-Bit-Werte zerlegen. Eine 
einfache Maskierung einer 16-Bit-Varialble mit einer 16-Bit-Maske reicht 
hierfür nicht.

von Ziegenpeter (Gast)


Lesenswert?

Guck dir mal deine chip_Select und chip_UnSelect funktionen genauer an, 
und überleg, ob die tatsächlich das machen, was die machen sollten 
(evtl. PORTC auf UART ausgeben lassen).

von doug (Gast)


Lesenswert?

Ziegenpeter schrieb:
> Guck dir mal deine chip_Select und chip_UnSelect funktionen genauer an,
> und überleg, ob die tatsächlich das machen, was die machen sollten
> (evtl. PORTC auf UART ausgeben lassen).

Habe es vorsichtshalber nochmal durchgesteppt mit dem debugger.
Das CS funktioniert einwandfrei.

von Karl H. (kbuchegg)


Lesenswert?

doug schrieb:

>
>     //UART zuerst high byte, dann low byte senden
>     UART_send(outZ & 0xFF00);
>
>     UART_send( outZ & 0x00FF);
>
>
> Das müsste doch eigentlich richtig sein....

Tu dir selbst einen Gefallen und schreib dir für derartige 
Standard-Aufgaben kleine Hilfsfunktionen.
1
void UART_int( uint16_t value )
2
{
3
  UART_send( value >> 8 );
4
  UART_send( value );
5
}

Hat doch keinen Sinn, quer übers Programm verstreut immer wieder die 
gleichen Fehler zu machen, nur weil man zu stolz ist, sich ein für alle 
mal ein paar kleine Helfer zuzulegen, die man ganz einfach an den 
bewussten Stellen benutzen kann ohne jedesmal wieder neu überlegen zu 
müssen. In der Zeit, in der du die beiden falschen Zeilen an bewusster 
Aufrufstelle eingebaut hast, hast du auch schon besagte Funktion 
geschrieben. Nur das du besagte Funktion in nächster Zeit noch ein paar 
zig-mal brauchen können wirst. Ausgabefunktionen für alle möglichen 
Datentypen auf allen möglichen verschiedenen Ausgabegeräten braucht man 
immer wieder mal. Und sei es nur, weil man zu Debugzwecken sich 
irgendwelche Werte ansehen will.

von doug (Gast)


Lesenswert?

J.-u. G. schrieb:
> Nein. "outZ" ist bei Dir doch eine 16-Bit-Variable (besteht also aus 2
> Byte). Vor dem Senden musst Du "outZ" in zwei 8-Bit-Werte zerlegen. Eine
> einfache Maskierung einer 16-Bit-Varialble mit einer 16-Bit-Maske reicht
> hierfür nicht.


Mist. Habe ich voll übersehn. Grad abgeändert. Funktioniert.

Karl Heinz Buchegger schrieb:
> doug schrieb:
>
>>
>>     //UART zuerst high byte, dann low byte senden
>>     UART_send(outZ & 0xFF00);
>>
>>     UART_send( outZ & 0x00FF);
>>
>>
>> Das müsste doch eigentlich richtig sein....
>
> Tu dir selbst einen Gefallen und schreib dir für derartige
> Standard-Aufgaben kleine Hilfsfunktionen.
> void UART_int( uint16_t value )
> {
>   UART_send( value >> 8 );
>   UART_send( value );
> }
>
> Hat doch keinen Sinn, quer übers Programm verstreut immer wieder die
> gleichen Fehler zu machen, nur weil man zu stolz ist, sich ein für alle
> mal ein paar kleine Helfer zuzulegen, die man ganz einfach an den
> bewussten Stellen benutzen kann ohne jedesmal wieder neu überlegen zu
> müssen. In der Zeit, in der du die beiden falschen Zeilen an bewusster
> Aufrufstelle eingebaut hast, hast du auch schon besagte Funktion
> geschrieben. Nur das du besagte Funktion in nächster Zeit noch ein paar
> zig-mal brauchen können wirst. Ausgabefunktionen für alle möglichen
> Datentypen auf allen möglichen verschiedenen Ausgabegeräten braucht man
> immer wieder mal. Und sei es nur, weil man zu Debugzwecken sich
> irgendwelche Werte ansehen will.


Macht Sinn.
Bin gar nicht auf die Idee gekommen eine Funktion zu schreiben.

von Karl H. (kbuchegg)


Lesenswert?

doug schrieb:
> Stephan schrieb:
>
>> Dann lass die Wartezeit halt weg!
>> Oder für was soll die gut sein, ausser das Zeitverhalten zu verhunzen
>> und die Diagnose zu erschweren?
>
> Eigentlich soll es mir die Diagnose erleichtern.

Wenn du dir dir Diagnose erleichtern willst, dann gib einfach die Werte 
aus, die du bekommst. Zb. das Status-Register!

Dazu hast du ja jetzt eine UART aktiviert, damit du dir Dinge ausgeben 
kannst! Und du solltest darüber nachdenken, dir die Dinge im Klartext 
ausgeben zu lassen und nicht als Hex-Bytes. Wenn du sowieso dein 
Programm mit _delay_ms spickst, dann kannst du genausogut diese Zeit 
auch nutzen lassen, um dir die Werte vernünftig lesbar ausgeben zu 
lassen.

> Das bedeutet ich habe jeden Durchgang einen overwrite.

Und du denkst ernsthaft, das wird besser, wenn du den µC zwischendurch 
möglichst lange warten lässt, so dass der Sensor beim nächsten mal schon 
wieder melden muss, dass er Daten produziert hat, die keiner abgeholt 
hat, weil der µC ja in der Zwischenzeit Däumchen drehen musste?

> Ohne die delay-Zeit könnte ich doch niemals den overwrite erkennen.

:-)
Du hast eine UART! Wenn du was wissen willst, dann lass es dir 
hinschreiben! (Oder schalte eine LED ein, oder sonstirgendwas anderes 
schnelles, wenn die UART Ausgabe zu lange dauert.)

Dein konkretes Problem ist, das der erste Overwrite durch die Wartezeit 
den nächsten Overwrite triggert. Das kann natürlich bei einer UART 
Ausgabe auch passieren. Das ist die Krux beim Debuggen - durch Debuggen 
verändert sich das Zeitverhalten des Programms.

von Karl H. (kbuchegg)


Lesenswert?

1
void UART_send(uint8_t data)
2
{    
3
  while(!(UCSR0A & (1<<UDRE0)));    //warten bis abgeschlossen
4
  UDR0 = data;            // senden     
5
} 
6
7
void UART_string(const char* txt)
8
{
9
  while( *txt )
10
    UART_send( *txt++ );
11
}
12
13
void UART_int(uint16_t value)
14
{
15
  char buff[6];
16
  utoa( value, buff, 16 );
17
  UART_string( buff );
18
}
19
20
void UART_byte(uint8_t value)
21
{
22
  char buff[4];
23
  utoa( value, buff, 16 );
24
  UART_String( buff );
25
}
26
27
void UART_dbg_byte( const char* label, uint8_t value )
28
{
29
  UART_string( label );
30
  UART_string( ": 0x" );
31
  UART_byte( value );
32
  UART_string( "\n" );
33
}
34
35
void UART_dbg_int( const char* label, uint16_t value )
36
{
37
  UART_string( label );
38
  UART_string( ": 0x" );
39
  UART_int( value );
40
  UART_string( "\n" );
41
}
42
43
void main(void) 
44
{      
45
  uint8_t  status_reg = 0;
46
  uint8_t  outZ_low = 0;
47
  uint8_t  outZ_high = 0;
48
  uint16_t outZ = 0;
49
50
  DDRC = (1<<DDC1); // PC1 als CS
51
      
52
  SPI_MasterInit();  //SPI init
53
  
54
  UART_init();    //UART Init
55
  
56
  sei();          //enable global interrupt  
57
    
58
  //9.1 Startup sequence          
59
  SPI_MasterWrite(CTRL_REG1, 0x3C);  //enable device, normal mode, z-axis enable
60
  
61
  SPI_MasterWrite(CTRL_REG2, 0x00);    
62
  
63
  SPI_MasterWrite(CTRL_REG4, 0x30);   //full scale +-24g, data LSB@lower adress  
64
65
    
66
  while(1)
67
  {  
68
    //1. and 2.    
69
    do  //warten solange keine neuen Daten             
70
    {
71
      status_reg = SPI_MasterRead(STATUS_REG);
72
    }while( !(status_reg & 0x08) )  ;
73
74
75
    UART_dbg_byte( "Stat", status_reg );
76
          
77
    //6. high und low byte auslesen    
78
    outZ_high = SPI_MasterRead(OUTZ_H);  
79
    outZ_low  = SPI_MasterRead(OUTZ_L);
80
81
    outZ = outZ_high << 8 + outZ_low;
82
83
    UART_dbg_int( "Z", outZ );      
84
  }  
85
}

von doug (Gast)


Lesenswert?

Habe deinen Rat befolgt und jetzt festgestellt, dass ich 12 overruns/sec 
hab.
Das ist sehr viel und ich versteh einfach nicht vorher das kommt.

Das Status_Reg zeigt mir dann immer 0xCC.
D.h. Overrun Z-Achse und new Data available Z-Achse.

von Karl H. (kbuchegg)


Lesenswert?

doug schrieb:
> Habe deinen Rat befolgt und jetzt festgestellt, dass ich 12 overruns/sec
> hab.

Na ja. was sagt denn ein Overrun aus?

Ein Overrun besagt, dass das Programm die Werte nicht schnell genug 
abgeholt hat (siehe Datenblatt). Ein neuer Messwert wurde vom Sensor 
produziert und in die Abhol-Register geschrieben, noch ehe der vorher 
gemessene Wert ausgelesen wurde.

Mit einer UART, die ja vergleichsweise langsam ist, ist das auch nicht 
weiter verwunderlich. Das kann schon sein. Der Sensor produziert nun mal 
schneller als der µC die Werte per SPI holen und per UART auf dein 
Terminal bringen kann.


Du hast wahrscheinlich an einen Werte-Overflow gedacht. Aber das ist 
nicht die Bedeutung dieser Bits.

von doug (Gast)


Angehängte Dateien:

Lesenswert?

Karl Heinz Buchegger schrieb:
> doug schrieb:
>> Habe deinen Rat befolgt und jetzt festgestellt, dass ich 12 overruns/sec
>> hab.
>
> Na ja. was sagt denn ein Overrun aus?
>
> Ein Overrun besagt, dass das Programm die Werte nicht schnell genug
> abgeholt hat (siehe Datenblatt). Ein neuer Messwert wurde vom Sensor
> produziert und in die Abhol-Register geschrieben, noch ehe der vorher
> gemessene Wert ausgelesen wurde.
>
> Mit einer UART, die ja vergleichsweise langsam ist, ist das auch nicht
> weiter verwunderlich. Das kann schon sein.


Vielleicht ist auch meine Pufferung schlecht?
Ich lade mal meinen aktuellen Code hoch.

von Karl H. (kbuchegg)


Lesenswert?

doug schrieb:

> Vielleicht ist auch meine Pufferung schlecht?

da hilft dir auch ein Puffer nichts.

Wenn eine Maschine alle 50 Sekunden ein Bauteil produziert und der 
Maschinenbetreuer alle 60 Sekunden 1 Bauteil von der Maschine 
fortbringt, dann werden sich die Bauteile irgendwann bei der Maschine 
stapeln. Egal wie groß die Kiste ist, in die die Maschine die Bauteile 
reinwirft.

Brauchst du zum Bearbeiten einer Akte 1 Stunde und legt dir dein Chef 
alle 30 Minuten einen neuen Akt auf den Schreibtisch, dann wird dein 
Schreibtisch irgendwann überquellen.

Können durch einen Tunnel in der Stunde 500 Autos fahren, kommen aber 
pro Stunde 800 AUtos zum Tunnel, dann hast du Stau. Und wenn die 800 
Autos Stunde für Stunde nicht weniger werden, dann wird der Stau wachsen 
und wachsen und wachsen.


Das ganz hat nichts mit Puffer oder dergleichen zu tun, sondern damit, 
dass ein Mechanismus insgesamt zu langsam ist um das Aufkommen zu 
bewältigen. µC sind zwar schnell, aber zaubern können sie auch nicht. 
Irgendwann ist jede FIFO voll, wenn ständig mehr reingeht als 
rausgenommen wird.

Im Endeffekt wirst du ja die UART nicht mehr haben, d.h. da fällt eine 
enorme Verzögerung der Hauptschleife sowieso weg.

von Michael H. (michael_h45)


Lesenswert?

doug schrieb:
> Vielleicht ist auch meine Pufferung schlecht?
woah, NEIN. das gibts doch nicht mehr langsam...

schau doch mal ins datenblatt von deinem sensor und schau, wie schnell 
der daten in sein register anliefert.
und dann schaust du, wie lang deine uart-übertragung dauert.

kleiner vorkauen als karl-heinz kann mans doch gar nicht mehr...

von Karl H. (kbuchegg)


Lesenswert?

> Im Endeffekt wirst du ja die UART nicht mehr haben, d.h. da fällt eine
> enorme Verzögerung der Hauptschleife sowieso weg.


Also:
Jetzt einfach mal nicht ins Hemd machen und damit leben, dass du nicht 
jeden einzelnen Messwert mitkriegst, sondern auch mal ein paar fehlen 
werden.

von doug (Gast)


Lesenswert?

Danke, habe jetzt durch eine kleinere SPI Geschwindigkeit eine geringere 
Fehlerquote.

von Michael H. (michael_h45)


Lesenswert?

wahnsinn...

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.