Forum: Compiler & IDEs Probleme bei der Frequenzauswertung


von cumi (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Zusammen

Um die Geschwindigkeit eines Modellautos zu messen arbeite ich mit einem 
Weg-Impuls-Geber.

Nun habe ich jedoch noch einige Probleme mit der Software. Das folgende 
Modul funktioniert ganz gut, muss jedoch irgendwo noch einen Bug haben, 
da es in zufälligen Abständen (zwischen wenigen hunder Millisekunden und 
einigen Minuten) zu Fehlauswertungen kommt. freqGet() liefert dann 
irgend einen komisch Wert, welcher am häufigsten 0 ist. Dabei wird die 
Frequenz zurzeit noch von einem Rechteckgenerator geliefert. An diesem 
sollte es also nicht liegen.

Damit man den Code schneller versteht hier ein paar grundsätzliche 
Dinge:

Das Signal liegt am Analogkomperator, welcher mit einem Kondensator noch 
einwenig geglättet wird. Getriggert wird bei 2.5V. Das Signal ist ein 
Rechteck von 0-5V.
Um zusätzlich noch entprellen zu können wird der Analog Comparator 
Interrupt beim auftreten eines Interrupts kurz deaktiviert und einwenig 
später vom Timer wieder aktiviert.
timGet() liefert ein DWord (32 Bit langer unsigned Typ). Dieses zählt 
auf dem Systemtakt hoch und überläuft nach ca. 9min einfach.


Ich komme bei diesem Problem schon seit geraumer Zeit nicht weiter. 
Finden vielleicht jemand von euch den Fehler?

Danke für eure Hilfe!

Gruss
cumi

von Christoph Kessler (db1uq) (Gast)


Lesenswert?

Dummerweise rettet der AVR das Statusregister nicht automatisch während 
der Interruptroutine. (Ich kenne das so vom 6502, der speicherte außer 
der Rücksprungadresse immer das Flagregister auf dem Stack)

Das könnte Abstürze provozieren, allerdings nur im Hauptprogramm, wenn 
die Interruptroutine zu unpassender Zeit ein Flag geändert hat.

von cumi (Gast)


Lesenswert?

Wann wird der Statusregister genau verwendet? Wann könnte dies in meinem 
zu Problemen führen?

Dass es irgendetwas mit den Interrupts zutun hat denke ich auch, denn 
fast nur so kriegt man so unberechnbare Fehler. Interrupts treten 
ziemlich viele auf.

Ich habe "nur" darauf geschaut, dass ich Variabeln, welche länger als 
ein Byte sind und im Hauptprogramm und in Interrupt-Routinen vorkommen, 
geschütz habe. Also immer wenn ich sie verwenden will deaktiviere ich 
global alle Interrupts, kopiere sie und aktiviere die Interrupts wieder. 
Das selbe beim schreiben.

von Karl H. (kbuchegg)


Lesenswert?

> Dummerweise rettet der AVR das Statusregister nicht automatisch
> während der Interruptroutine

Kein Problem.
Darum kümmert sich der Compiler

von cumi (Gast)


Lesenswert?

Aus dem Wiki:
"Variablen die sowohl in Interrupt-Routinen (ISR = Interrupt Service 
Routine(s)), als auch vom übrigen Programmcode geschrieben oder gelesen 
werden, müssen mit einem volatile deklariert werden. Damit wird dem 
Compiler mitgeteilt, dass der Inhalt der Variablen vor jedem Lesezugriff 
aus dem Speicher gelesen und nach jedem Schreibzugriff in den Speicher 
geschrieben wird. Ansonsten könnte der Compiler den Code so optimieren, 
dass der Wert der Variablen nur in Prozessorregistern 
zwischengespeichert wird, die "nichts von der Änderung woanders 
mitbekommen"."

Könnte genau das das Problem sein? Denn ich habe "tI1" nicht als 
volatile deklariert. Ich werde das natürlich ausprobieren sobald ich 
zuhause bin und einen Compiler habe.

von Rahul, der Trollige (Gast)


Lesenswert?

>mit einem Weg-Impuls-Geber

Wie heisst der?

(ist nur so von Interesse...)

Da du den Weg-Impuls-Geber ja sowieso entprellst, solltest du mal 
feststellen, wie groß die grösste Frequenz ist, die er in deinem Auto 
liefert. Dann könntest du ihn nämlich auch gleich per Timer-Interrupt 
pollen...

>Könnte genau das das Problem sein?
Ja. (Muß aber nicht. Sicher ist sicher...)

Wo ist "timGet()"?
Prinzipiell sollte es reichen, in der ADComp-ISR den Timer auszulesen.
Du solltest auf jeden Fall mal feststellen, wie groß die maximal 
erreichbare Frequenz deines Aufnehmers ist (im Zusammenhang mit dem 
Auto).
Damit könnte man den Timer besser konfigurieren.

von Rahul, der Trollige (Gast)


Lesenswert?

Noch besser wäre es die obere und untere Frrequenz zu wissen (Dass 0Hz 
auch vorkommen, ist mit klar. Die Frequenz, ab der der Zustand des Auto 
als "fahrend" bezeichnet werden kann, meine ich mit der unteren.)

von cumi (Gast)


Angehängte Dateien:

Lesenswert?

Vielen Dank, Rahul, für dein Antwort!

>>mit einem Weg-Impuls-Geber
>Wie heisst der?
Ja das ist ein Ding, welches nach einem gewissen Wegstück (häufig ein 
Radumfang oder ein Teil davon) einen Impuls gibt. Kann gut sein, dass 
das nicht so ein gebräuchlicher Name ist. Er stammt von einem Kollegen. 
Ich weiss nicht von wo er ihn hat :)

>>Könnte genau das das Problem sein?
>Ja. (Muß aber nicht. Sicher ist sicher...)
Also ich hab da noch das volatile hingesetzt. An dem liegt es nicht 
(nur).

Die Maximalen und minimalen Frequenzen kenne ich ganz gut. Die minimale 
Frequenz liegt theoretisch bei 0.1Hz. Denn das ist die Auflösung meiner 
Frequenz-Variabel. Jedoch ich alles was unter 5Hz ist unbedeutend (dann 
hat das Fahrzeug sowieso den zustand: stehend).
Aus der maximalen Frequenz berechne ich jeweils den Wert für den preload 
des Timers. Dieser wird von der Funktion 
"dataGetByte(DATATABLE_AC_TCNT0);" aus dem Eeprom gelesen.

Die Funktion timGet() ist im angehängten File implementiert. Liegt 
vielleicht dort der Fehler?

von Rahul, der Trollige (Gast)


Lesenswert?

>Ich weiss nicht von wo er ihn hat
Ein Bild sagt mehr als diverse Worte...

>Die Funktion timGet() ist im angehängten File implementiert. Liegt
>vielleicht dort der Fehler?

Könnte sein...
Momentan bin ich etwas zu müde, um mir den Code anzugucken...

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.