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
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.
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.
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.
>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.
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.)
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?
>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...