Uhr läuft ungenau

Gast #145474
Lesenswert?

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ß
Angehängte Dateien:
Gast #145479
Lesenswert?

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.
Gast #145481
Lesenswert?

"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
Gast #145482
Lesenswert?

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.
Gast #145484
Lesenswert?

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.
Gast #145487
Lesenswert?

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
Gast #145489
Lesenswert?

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
Gast #145490
Lesenswert?

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
Gast #145492
Lesenswert?

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 ?
Gast #145497
Lesenswert?

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.
Gast #145498
Lesenswert?

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.
Angehängte Dateien:
Gast #145500
Lesenswert?

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.
Gast #145502
Lesenswert?

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
Angehängte Dateien:
Gast #145503
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren