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.
> Dummerweise rettet der AVR das Statusregister nicht automatisch > während der Interruptroutine Kein Problem. Darum kümmert sich der Compiler
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...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.