Forum: Mikrocontroller und Digitale Elektronik Uhr läuft ungenau


von Michael (Gast)


Angehängte Dateien:

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ß

von Rufus T. Firefly (Gast)


Lesenswert?

"Im Forum habe ich schon ein paar Anregungen gelesen. Das alles bringt
mich nicht weiter."

Wie soll man Dir dann noch helfen?

von Daniel Nöthen (Gast)


Lesenswert?

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

von Michael (Gast)


Lesenswert?

Hallo Daniel!

Eine andere Möglichkeit gibt es nicht, um festzustellen wie weit die
Uhr wegläuft?

von Daniel Nöthen (Gast)


Lesenswert?

Doch, Du könntest Messen wie ungenau Deine Quarzfrequenz ist und dann
rechnen...
Glaub der Weg mit der Funkuhr ist aber um einiges leichter.

von A.K. (Gast)


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.

von Michael (Gast)


Lesenswert?

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.

von peter dannegger (Gast)


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

von crazy horse (Gast)


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.

von Michael (Gast)


Lesenswert?

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.

von Rufus T. Firefly (Gast)


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.

von Michael (Gast)


Lesenswert?

Sorry ich hab mich da vertan. Ich habe einen 8Mhz Resonator am
Controller hängen.

von Stephan Hochberger (Gast)


Lesenswert?

Und welche Toleranz und Stabilität hat wohl der Resonator so???

von Andi (Gast)


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

von Andi (Gast)


Lesenswert?

Hab da was vergessen:

           if (stunden < 24) ++stunden;

Gruß
Andi

von Jens123 (Gast)


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

von Andi (Gast)


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

von Michael Wilhelm (Gast)


Lesenswert?

@ Andi,

mit 9,59 und 23 ist das okay, weil bei 0 mit dem Zählen angefangen
wird.
MW

von Benedikt (Gast)


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 ?

von Michael (Gast)


Lesenswert?

Hat jemand einen Vorschlag wie ich meine Uhr jetzt genauer hinbekomme?

von Rufus T. Firefly (Gast)


Lesenswert?

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.

von A.K. (Gast)


Lesenswert?

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

von Michael (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Stephan!


Der Resonator hat folgende Toleranz siehe Anhang.

von Stephan Hochberger (Gast)


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.

von Michael (Gast)


Angehängte Dateien:

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.

von Michael (Gast)


Lesenswert?

Hallo....

von Armin Kniesel (Gast)


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.

von Michael (Gast)


Lesenswert?

Hallo Armin!

Geht das auch mit dem Overflow Interrupt?

von Jens123 (Gast)


Angehängte Dateien:

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

von Profi (Gast)


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

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
Noch kein Account? Hier anmelden.