Forum: Mikrocontroller und Digitale Elektronik Interrupt + Timer + LCD


von Florian K. (f-kae)


Angehängte Dateien:

Lesenswert?

Hallo,

Hintergrundidee:
Ich möchte gerne Daten von einem Sensor(L3G4200D) mit einem AVR(ATMega16 
mit 8MHz) über SPI(125kHz) auslesen und diese auf einem LCD anzeigen. 
Speziell geht es darum, dass ich den Sensor um 360 Grad nach links um 
die z-Achse drehe und dann um 360 Grad zurück. Die Gradanzeige soll auf 
dem LCD angezeigt werden und demnach am Ende wieder auf Null stehen.

TECHNISCH funktionsfähige Methode:
EIN Timer = 10µs: Alle 10µs wird ein Interrupt ausgeführt und innerhalb 
der ISR werden die Daten vom Sensor geholt und diese auf dem LCD 
ausgegeben. Problem hierbei, nach hin und rück drehen bekomme ich 
zwischen (+/-)10-50 Grad anstatt 0 raus.

Vermutete Problemlösung:
Die Anzege auf dem LCD verzögert den Ablauf und verhindert somit das 
wirklich alle 10µs ein neuer Wert eingelesen wird. Um genauere Werte zu 
bekommen muss der Sensor also enen separaten Timer vom LCD bekommen.

Lösungsansatz:
Timer1 = alle 10ms ISR(Daten auf LCD ausgeben) ausführen
Timer2 = alle 10µs ISR(Sensordaten auslesen) ausführen

Leider schaffe ich es auf diesem Weg nicht, da immer nur die kürzere ISR 
ausgeführt wird. Das Display zeigt also nichts an.

Wenn ich die Zeilen:
1
  Refresh_LCD_Data_X(X, X_add);
2
  Refresh_LCD_Data_Y(Y, Y_add);
3
  Refresh_LCD_Data_Z(Z, Z_add);
in die ISR(TIMER2_COMP_vect) rein schiebe funktioniert beides.

Frage:
Erkennt jemand das Problem hierbei, dass die ISR(TIMER1_COMPA_vect) 
nicht ausgeführt wird?

von xfr (Gast)


Lesenswert?

10 us?? Wozu das denn? Willst Du 100.000 verschiedene Werte pro Sekunde 
anzeigen? Wie soll man das denn ablesen können. Mal ganz abgesehen 
davon, dass Du dafür bei 8 MHz nur 80 Prozessortakte zur Verfügung hast 
...

Wenn Du das Display nur alle 10 ms aktualisierst (was auch schon zu 
schnell ist), brauchst Du doch auch nur alle 10 ms einen neuen Wert.

von Florian K. (f-kae)


Lesenswert?

Die Werte werden ja aufaddiert und nur die Summe angezeigt.

Meine Vermutung der Ungenauigkeit war, das nicht oft genug Werte vom 
Sensor gespeichert werden und somit nicht die ganze Bewegung 
wahrgenommen wird und schliesslich die Summe halt nicht stimmt am Ende.

von Peter D. (peda)


Lesenswert?

Die LCD-Ausgabe gehört ins Main.
Und nur die Variablenübergabe erfolgt atomar.

Die 10µs kannste voll vergessen.
1 Byte SPI, 125kHz dauert ja schon 64µs.


Peter

von xfr (Gast)


Lesenswert?

Habe mir jetzt den Code mal angeschaut. Die Interrupt-Routine wird 
einfach zu lange brauchen, so dass ständig die Timer2-ISR ausgeführt 
wird und nichts anderes mehr.

Die aus den integrierten Gyro-Werten ermittelte Position wird vermutlich 
nicht viel besser werden, unabhängig von der LCD-Ausgabe. Je schneller 
Du die Werte integrierst, desto mehr Rauschen kommt dazu. Wenn Du 
langsamer integrierst, verpasst Du Bewegungen ...

von Florian K. (f-kae)


Angehängte Dateien:

Lesenswert?

OK ich habe SPI nun auf 1MHz gestellt daher bekomme ich ein Byte in 8µs 
übertragen.
Dann habe ich die LCD-Anzeige in die Main verlagert und
Timer 1 LCD auf 65ms vergrößert und
Timer 2 L3G auf 100µs vergrößert.

Mich wundert es, dass ich nun aber keine Anzeige mehr auf dem Display 
bekomme. Wenn ich die Interrupts richtig verstanden habe wird doch 
sobald ein Event für ein Interrupt eintritt dieses ausgeführt und der 
andere Programmablauf "pausiert" und während einer ISR kann auch nichts 
anderes geschehen.
Was passiert denn mit einem Interrupt der während einer ISR auftritt???

von xfr (Gast)


Lesenswert?

Und wie viele Bytes werden in Refresh_Gyro_Data_X() übertragen? Das 
musst Du mal drei nehmen, dazu der ganze Overhead in der Funktion und 
die Addition. Ich tippe mal, dass die 100 us immer noch nicht reichen. 
Probier es doch erstmal langsamer, mit 10 ms oder so. Schneller kann man 
es immer noch machen.

Wenn Deine ISR zu lange braucht wird noch während sie läuft ihr 
Interrupt-Flag wieder gesetzt und sofort nachdem sie zu Ende ist wieder 
angesprungen. Eventuell wird dazwischen noch ein Maschinenbefehl in der 
Hauptschleife ausgeführt, aber im Prinzip ist das dann eine 
Endlosschleife.

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.