Guten Tag! Ich bin gerade dabei mit dem AT90S8535 eine Uhr zu realisieren. Ich verwende da den 16Bit Timer1. Den Timer1 habe ich auf 100ms eingestellt. Jetzt läuft meine Uhr nicht genau. Wie kann ich softwaretechnisch das so lösen, dass meine Uhr genau läuft? Im Forum habe ich schon ein paar Anregungen gelesen. Das alles bringt mich nicht weiter. Für Unterstützung bin sehr dankbar. Gruß
"Im Forum habe ich schon ein paar Anregungen gelesen. Das alles bringt mich nicht weiter." Wie soll man Dir dann noch helfen?
Vergleiche doch einfach mit einer Funkuhr, wie ungenau deine Uhr läuft. Läuft sie pro Tag 2 Sekunden vor/nach, dann wirkst du per Software dem entgegen. Gruß, Daniel
Hallo Daniel! Eine andere Möglichkeit gibt es nicht, um festzustellen wie weit die Uhr wegläuft?
Doch, Du könntest Messen wie ungenau Deine Quarzfrequenz ist und dann rechnen... Glaub der Weg mit der Funkuhr ist aber um einiges leichter.
Aber natürlich geht's auch anders: hinreichend genauen Frequenzzähler besorgen ;-) und an einem separaten Takt-Ausgang die Frequenz messen (am Quarz natürlich nicht, verfälscht die Messung). Genauer wird's übrigens auch dann, wenn der Timer nicht in der Interrupt-Routine neu gesetzt wird, sondern der CTC-Modus genutzt wird, in dem sich der Timer selbst bei erreichen des Limits neu setzt. Ansonsten ist die u.U. recht variable Interrupt-Latency mit in der Kalkulation drin. Ich weiss freilich grad nicht, ob der AT90S8535 den CTC-Mode kennt.
Hmmm...danke für die zahlreichen Infos. Was wäre jetzt am besten zu realisieren? Auf jedenfall will ich den Timer1 nutzen und ohne externe Bauteile.
"Jetzt läuft meine Uhr nicht genau. Wie kann ich softwaretechnisch das so lösen, dass meine Uhr genau läuft?" Das ist Wischiwaschi ! "Genau" ist keine Zahlenangabe ! Sag doch einfach: Die Abweichung beträgt > xx Sek./Tag. Ich benötige aber < yy Sek./Tag. Dann erst kann man auch was dazu sagen. Peter
und was heisst "ohne externe Bauteile"? Du meinst doch nicht etwa den internen RC-Osz als Zeitbasis? Dann vergiss es direkt. Deutlich besser bist du da mit der Netzfrequenz bedient, die Langzeitstabilität ist ziemlich gut.
Die Differenz zwischen Funkuhr und eigene Uhr beträgt 20 Sekunden bei einer Läufzeit von 1 Stunde. Meine Uhr läuft 20 Sekunden vor.
Und als Taktquelle benutzt Du ... den internen RC-Oszillator? Der ist ungenau. Soll's genauer sein, wirst Du um einen temperaturkompensierten Quarzoszillator ("Quarzofen") kaum herumkommen. Oder Du vergisst die Idee und implementierst statt dessen eine Funkuhr.
Sorry ich hab mich da vertan. Ich habe einen 8Mhz Resonator am Controller hängen.
Hi! Du hast hier folgendes: if (zehntelsek < 9) ++zehntelsek; else { zehntelsek = 0; if (sekunden < 59) ++sekunden; else { sekunden = 0; if (minuten < 59) ++minuten; else { minuten = 0; if (stunden < 23) ++stunden; else { stunden = 0; } } } } Solte das nicht besser so sein um jede Sekunde, Minute und Stunde wirklich voll zu kriegen? if (zehntelsek < 10) ++zehntelsek; else { zehntelsek = 0; if (sekunden < 60) ++sekunden; else { sekunden = 0; if (minuten < 60) ++minuten; else { minuten = 0; if (stunden < 23) ++stunden; else { stunden = 0; } } } } 1 Sekunde sind ja 10 Zehntel Sekunden und nicht 9 Zehntel, 1 Minute/Stunde 60 Sekunden/Minuten und nicht 59. So ne krasse Abweichung liegt glaube ich nicht an dem externen Quarz oder an einem um 1 zu geringen Timer-Wert. Ansonsten schadet es nicht, das setzen des Timers am Anfang der ISR zu schreiben. Für 1 Zehntel Sekunde brauchst Du dann 8000000/64/10 = 12500. Für die Timerregister dann 65536 - 12500 = 53036 (CF2C). Gruß Andi
Du hast da if(zehntelsek < 10) ++zehntelsek; hiess das nicht wenn zehntelsek kleiner 10 ist?? wieso machst du das nicht so: if(zehntelsek == 9) { zehntelsek = 0; ++sekunden; } if(sekunden == 59) { sekunden = 0; ++minuten; } irgendwo hatet ich mal gelesen, dass man vermeiden soll sehr tiefe verschachtelungen zu programmieren.. wie setzt du denn zehnztelsekunden mit einem timer?? Gruss Jens
Wieso nur bis 9, 59 oder 23 Zählen? Eine ganze Sekunde hat 10 1/10-Sekunden, eine ganze Minute/Stunde hat 60 Sekunden/Minuten und ein Tag 24 Stunden. Also muß bis 10, 60, 60 und 24 hochgezählt werden. Beispiel: 10 mal die 1/10-Sekunden um eins erhöhen: Ausganswert 0 + 1 1/10 = 1 ( 1. mal) ZehntelSek < 10 + 1 1/10 = 2 ( 2. mal) ZehntelSek < 10 + 1 1/10 = 3 ( 3. mal) ZehntelSek < 10 + 1 1/10 = 4 ( 4. mal) ZehntelSek < 10 + 1 1/10 = 5 ( 5. mal) ZehntelSek < 10 + 1 1/10 = 6 ( 6. mal) ZehntelSek < 10 + 1 1/10 = 7 ( 7. mal) ZehntelSek < 10 + 1 1/10 = 8 ( 8. mal) ZehntelSek < 10 + 1 1/10 = 9 ( 9. mal) ZehntelSek < 10 + 1 1/10 = 10 (10. mal) ZehntelSek NICHT < 10 also auf 0 setzen und Sekunden auf die gleiche Art mit 60 bearbeiten. Gruß Andi
@ Andi, mit 9,59 und 23 ist das okay, weil bei 0 mit dem Zählen angefangen wird. MW
Ein großer Fehler ist das Nachladen des Timers. Du weißt nie genau, wann die Interruptroutine gestartet wird, daher müsstest du das Timerregister auslesen, schauen wieviel Zeit seit dem eigentlichen Interruptauslösenden Zeitpunkt vergangen ist und den neuen Wert dementsprechend verringern. Ich habe mich mit den Timern des AVR noch nie so wirklich genau beschäftigt, aber hat der Timer keine Autoreload Funkion so wie der Timer beim 8051 ?
Als erstes könntest Du Dir ja mal die verschiedenen Antworten in genau diesem Thread hier durchlesen - Stephan hat Dir beispielsweise eine von Dir unbeantwortete Frage gestellt.
@Benedikt: ob nun bei den AT90 weiss ich grad nicht, aber mindestens die neueren Version haben einen Modus für automatischen Reload, den CTC-Mode den ich oben schon erwähnte.
Für eine Uhr ist die Toleranz mE zu hoch. +/- 10s/h oder 4min/d Mit Abgleich wird eine Abweichung von vielleicht 1s/h möglich sein. Nimm lieber einen Quarz, oder besser Quarzofen. Für die 20 Sekunden Abweichung muß es aber wohl noch nen anderen Grund geben.
Hallo Stephan! Was meinst du zu meinem Quellcode. Ist der Compare Mode Interrupt besser geeignet oder ist der Overflow Interrupt ausreichend? Kann man sonst noch bei meinem Quellcode was verbessern? Im Forum habe ich einene Beitrag von peter dannerger gelesen. Da beschreibt er wie er seine Uhr programmiert hat. (siehe Quellcode) Leider verstehe ich da nicht was er da macht.
Ich habe immer am Anfang der Timerinterrupts den aktuellen Timerwert aus dem Register ausgelesen und diesen Wert mit dem "Neuladen"-Wert kombiniert. Weil bis das Programm in die Interruptroutine kommt vergeht eine ungewisse (?) Zeit. Und diese kann man im Timerregister auslesen und somit kompensieren.
ich hatte sowas mal in asm geschrieben (mein erstes programm) dabei hatte ich einen IOclock von 8MHz (interner RC Oszilator) und einen externen quarz 32.irgendwas kHz (Uhrenquarz) an TOSc1 / 2. ich hatte diese Uhr 2 Tage laufen lassen und konnte keine ungenauigkeit erkennen.. zum testen hatte ich das ganze mal mit uart aufgebaut und immer dann, denn der int handler aktiv wurde ein zeichen an den PC gesendet mit dem Terminalprogramm bon Br@y (grosser lob) enpfanngen und mir die Zeiten angeschaut, in den ndie Daten kahmen war sehr genau.. im Anhang ist das Grundprogramm mit den Timersettings etc in ASM!! Gruss Jens
Wie oft denn noch? Die Idee mit dem Quarzofen ist zwar naheliegend, aber absolut unnötig. Wie oft denn noch? Die Idee mit dem Quarzofen ist zwar naheliegend, aber absolut unnötig. Messe die Temperatur des Quarzes/Resonators und nimm aus einer LookUp-Tabelle den passenden Teilfaktor. So könntest Du sogar mit dem Resonator ausreichend genau werden. Zum Timerproblem gibt es mehrere Möglichkeiten: 1. freilaufender Timer (ohne explizitem Nachladen) mit AutoReload 2. freilaufender Timer ohne jeglichem Reload, bei dem der Compare-Wert aus dem vorhergehenden mittels ADD-Befehl berechnet wird. Wenn Dir die Dekodierung des DCF77-Signals zu kompliziert ist, kannst Du auch dessen hochstabilen 77,5kHz-Träger teilen oder nur die Sekundenimpulse zählen (es werden aber nur 59 Sekundenimpulse pro Minute gesendet, den einen fehlenden (zum Minutenwechsel) musst Du selbst generieren). Jeder bessere Uhrmacher hat eine "Quarzwaage", die akustisch oder induktiv den Sekundenimpuls der Uhr aufnimmt und die Abweichung sofort anzeigt (eigentlich ein hochauflösender Frequenzzähler).
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.