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ß
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
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.
"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.
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.
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
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).