Forum: Mikrocontroller und Digitale Elektronik genauer TIMER


von HDW (Gast)


Angehängte Dateien:

Lesenswert?

Hallo

Ich möchte für eine Uhr ein relativ genaues 1Hz-Signal erzeugen 
PIC16f84).
Ausprobiert habe ich folgendes:

1. TRM0-Überlauf; mit polling am Überlaufbit
2. TMR0-Überlauf per Interupt
3. keramikschwinger gegen Quarz ausgetauscht
4. "zero-error" von http://www.ezy.net.au/~fastvid/one_sec.htm (beide 
versionen: mit echtem Interupt und mit "falschem" Interupt.

Alle Signale waren im vergleich zu meiner Windows-Uhr extrem ungenau.
Auf eine halbe Stunde kamen folgende Ungenauigkeiten:

1. hab ich vergessen. jedenfalls zuviel
2. 4s auf 20 min!!
3. Keramikschwinger und Methode 2: in 30 min 4 Sekunden schneller als 
PC-Uhr
Quarz und Methode 2: in 30 min 4 Sekunden zu langsam
4. Pro Minute 0,5 bis 1s Fehler!

Irgendeie verstehe ich das nicht.
Methode 1 ist verständlich. Beim Pollen wird nicht jeder Überlauf des 
TMR0 erkannt.
Bei Methode 2 dürfte meiner Meinung nach nicht eine solch große 
Abweichung auftreten. Der Interupt wird auomatisch beim Überlauf des 
TMR0 ausgeführt. Fehlerquelle wäre da nur, dass der Befehl, der zum 
Zeitpunkt des Interupts ausgeführt wird, den Interupt etwas(!) 
verzögert. Da handelt es sich ja dann nur um Mikrosekunden. Dass kann ja 
eigentlich nicht zu so einer großen Abweichung führen.

Ich hatte mir überlegt, ob es vielleicht am Oszillator liegt. Aber als 
ich dem Keramikschwinger gegen den sehr viel genaueren Quarz 
austauschte, lief die Uhr zwar nicht mehr zu schnell, dafür aber viel zu 
langsam.

Dass auch Methode 4 nicht genauer ist, wundert mich dann doch schon. Der 
Fehler soll durch Operationen im Quellcode ausgeglichen werden. Aber 
trotzdem habe ich extreme Abweichungen.

Wie erzeugt ihr denn genaue Zeiten?

Kennt jemand einen Link zu einem genaueren Timer bzw. Uhr, der brauchbar 
ist?

Wo könnten z.B. in Methode 2 beim Interupt diese groben Abweichungen zu 
erklären sein?


mfg   Wolfram Hildebrandt

von Sascha Weitkunat (Gast)


Lesenswert?

Gönn deinem Quarz mal einen Ziehkondensator, so kannst du die 
Feineinstellung der Frequenz optimieren und deine 4s ganz bestimmt 
kompensieren..

von HDW (Gast)


Lesenswert?

Äh.. Was heißt das bitte?

von crazy horse (Gast)


Lesenswert?

übliche MC-Quarze sind bei weitem nicht so genau, wie oft angenommen 
wird. Sie sind zwar relativ stabil gegen Frequenzänderung, absolut sind 
sie jedoch doch ein ganzes Stück neben der Sollfrequenz. Ein weiteres 
Problem: jeder Quarz hat eine Reihen- und eine Parallelresonanz, die 
liegen etwas auseinander. Wenn die Frequenz in Reihenresonanz angegeben 
wird, der Osz. aber in Parallelresonanz läuft, hast du schon mal einen 
systematischen Fehler.
Ob ein Timerüberlauf direkt oder ein paar Takte später erkannt wird, hat 
keine Auswirkungen, da sich dieser Fehler nicht summiert.
Abhilfe:
-genaue Quarze verwenden (sieht man direkt am Preis, statt 49Cent kosten 
die dann 8Euro,
-Einsatz einer echten RTC (z.B. von Dallas), hat auch den Vorteil, daß 
die bei Stromausfall weiterläuft
-Softwarekalibrierung
-Einsatz eines ext. Oszillators mit 32,768KHz (Uhrenquarz), evtl. mit 
Teiler, so daß du jede Sekunde einen ex. Interrupt bekommst.

von Peter D. (peda)


Lesenswert?

Es stimmt, MC-Quarze sind nicht absolut genau. Sie müssen ja auch nur 
genügend genau sein, damit eine RS-232 oder Ethernetverbindung usw. 
synchron bleiben.

Sie sind aber stabiler und weniger temperaturabhängig, als Uhrenquarze. 
Das liegt einfach an dem anderen Frequenzbereich (mehrere MHz).

Max 1 Sekunde pro Tag sollte man also erreichen können.

Wenn ich das jetzt richtig verstanden habe, ist beim PIC ein Timer nicht 
so einfach neu zu laden. Deshalb sollte man ihn ohne Vorteiler 
durchlaufen lassen und die nötigen Korrekturen bei den nachfolgenden 
Teiler-Bytes im SRAM machen.


Das Prinzip der Softwarekorrektur habe ich hier für den 8051 
beschrieben:

http://www.specs.de/users/danni/appl/soft/clock/timebase.htm


Aber auch normale Quarzuhren müssen abgeglichen werden. Höchstens ganz 
billige Werbegeschenkuhren werden nicht abgeglichen und haben dann auch 
große Abweichungen.

4s in 30min sind aber auch ohne Abgleich viel zu viel und deuten auf 
einen Softwarefehler hin.


Peter

von HDW (Gast)


Lesenswert?

Software-Fehler?

Im Anhang ist der Quellcode in dem mittels Überlauf des TMR0 alle 4ms 
ein Interupt ausgelöst wird. Dies wird dann 250 durchlaufen.
Wo könnte denn da der Fehler in der Genauigkeit liegen?

Wie war das doch gleich mit dem Zieh-Kondensator?
Kann ich damit meinen Quarz anpassen?



mfg   Wolfram Hildebrandt

von Onno (Gast)


Lesenswert?

Nur eine blöde Idee dazu:
Versuchs doch mal mit der atomgenauen Zeit :)
Siehe z.B. hier:

Two-Transistor Atomic Frequency Standard
http://www.techlib.com/electronics/atomic.html

Das kann man mit Anpassungen sicher auch leicht an einen Mikrocontroller 
anschließen. Ich plane das schon. Nur mußt Du bei Verwendung mit
uC darauf achten, daß der analoge 50Hz-Teil gut gegen die Einstreuungen 
des uC abgeschirmt ist.

von HDW (Gast)


Lesenswert?

Lustig!

Wenn ich aber diese Signale aus dem Netz auffangen soll, muss ich aber 
wohl in der Nähe zu so einem solchen sein. Dann kann ich ja direkt die 
50Hz aus dem 230V Netz nutzen und ein Kabel dran legen, wie viele (alte) 
Wecker es tun.


Aber noch mal zu meinem Problem: Es muss doch einen Weg geben, wie eine 
brauchbare Uhr mit dem PIC 16F84 hinzubekommen ist. Wenn es nicht am 
Oszillaor liegt, zumindest nicht in dem Maße, wo ist denn dann der 
Fehler. Der *.asm File ist ganz oben in diesen Beitrag.
Was ich mir evtl. vorstellen könnte, ist, dass die 
Interuptserviceroutine zu lang ist, und nicht alle Takte erkannt 
werden??

von crazy horse (Gast)


Lesenswert?

das Problem ist einfach, daß hier nicht mehr viele Leute sind, die was 
mit PICs machen, schon gar nicht in Assembler. Der Befehlssatz ist 
einfach zum Ko...

von HDW (Gast)


Lesenswert?

Ein paar, die Ahnung von PICs haben, sind doch noch im Forum. Auf die 
hoffe ich.

von Peter D. (peda)


Lesenswert?

Ich kenn mich mit dem PIC nicht aus, deshalb kann ich Dir nur sagen, wie 
es mit dem 8051 oder dem AVR geht.


Aber vielleicht hast Du einen Simulator, dann kannst Du Dir doch 
anzeigen lassen, wieviel Quarztaktzyklen 1 Sekunde, 1 Minute usw. 
dauert.
Und dann siehst Du, ob es ein Softwarefehler ist.


Peter

von Peter D. (peda)


Lesenswert?

Üblich sind für Quarze max +/-100ppm Abweichung von der Nennfrequenz, 
z.B. mein 12MHz Quarz hatte 12.000768MHz.
Das wären dann 6s je Tag.


Peter

von HDW (Gast)


Lesenswert?

Hm.
Ich bin mir nicht sicher, ob das im PMLAb geht. Ich glaube eher nicht.

Prinzipiell habe ich nichts gegen 8051er oder AVRs.
Wie wäre denn da das 1Hz Signal zu generieren? Wie genau wäre das dann?

von Peter D. (peda)


Lesenswert?

Z.B. beim 8051 wie in meinem obigen Link.


Peter

von HDW (Gast)


Lesenswert?

Zu dem Quarz: die Quarze bei Conrad haben eine Toleranz von 30ppm. Aber 
die 4s Differenz pro 30min können ja dann wohl nicht am Quarz liegen, 
wenn einer mit 100pm bei 12Mhz nur 6s pro Tag abweicht.

Auf jeden Fall wohl Software-Fehler.

von HDW (Gast)


Lesenswert?

Hallo

Nochmal die Software betreffend:

Der einzige große Fehler, den ich mir vorstellen könnte, wäre, dass die 
Interuptserviceroutine zu lang ist und nicht unter 4ms (Interuptzeit) 
zuende ist.
Bei 1us pro befehl hätte ich dann aber 4000 Befehle, Sprungbefehle 
ausgenommen. Das ist doch ziemlich viel.

Im der Interuptroutine rufe ich die Unterprogramme INCREASE, OUT und 
WECKVERGLEICHSEC auf. In INCREASE rufe ich alle Nase lang OUT auf. 
Vielleicht zu oft?

von HDW (Gast)


Lesenswert?

Die Interuptroutine habe ich jetzt verkürzt.
Die sollte nun auf jeden Fall in dem Fenster von 4ms ablaufen.

Die Uhr läuft jetzt testweise ca. 30 min und wieder 4s Abweichung.

von HDW (Gast)


Lesenswert?

Ich habe die Uhr jetzt passend gemacht.
Der Fehler von "9s pro Stunde zu langsam" wird nach jeder Stunde wieder 
zu den Sekunden addiert.
Das ist zwar nicht besonderes elegant, ich weiß aber momentan keine 
andere Lösung.


mfg   Wolfram Hildebrandt

von Peter D. (peda)


Lesenswert?

Wenn ich das richtig verstanden habe, wird beim PIC bei jedem Schreiben 
auf den Timer der Vorteiler zurückgesetzt.

Du must also unweigerlich Takte verlieren, d.h. zu langsam sein.

Abhilfe:

Entweder keinen Vorteiler oder den Timer durchlaufen lassen.


Bei Deinem Takt von 1MHz:

1MHz  32  256 = 122,07

Du läßt also das Teilerbyte im SRAM durch 122 teilen.
Der restliche Fehler ist dann:

1s - 1/(1MHz  32  256 / 122) = 576µs

Wenn Du dann einmal je Sekunde einen anderen Teilerwert (126) nimmst, 
ist Dein Fehler nur noch:

1s - 1/(1MHz  32  256 / ((59 * 122 + 126) / 60)) = 30µs

Das sind dann 2,5s/Tag.


Peter

von Peter D. (peda)


Lesenswert?

Sorry, ein Dreckfuhler hat sich eingeschlichen, es muß natürlich heißen:


"Wenn Du dann einmal je Minute einen anderen Teilerwert (126) 
nimmst,..."


Peter

von HDW (Gast)


Lesenswert?

Der Vorteiler bleibt schon gleich.
Den habe ich immer auf 32 eingestellt, aber nur einmal am Anfang 
initalisiert.
Der Timer wird jedoch in jedem Interupt neu beschrieben.
Max. kann der TMR0 256 (8 Bit) aufnehmen. Davon brauche ich jedoch nur 
125 (dann sind 4ms vorbei). Also wird der Timer in jedem Interupt neu 
mit 130 geladen. Dieser Wert wird jedoch erst nach ca. 3 Zyklen (3us) in 
den TMR0 geladen.

Diese Sache mit dem Ausgleichen habe ich zufällig gestern in einem alten 
EAM-Magazin gesehen.

Aber wenn man die Fehlerquellen zusammenrechnet:

Interupt: 2-3 Zyklen (max.3us)
TMR0 laden: 3 Zyklen
kein weiteres Polling etc.
D.h. jede 4 ms großzügig 10us Fehler. 1s hat dann 2500us, also 2,5ms 
Fehler. Mal 60 = 150ms in der Minute = 9000ms in der Stunde. Das ist 
genau mein Fehler von 9s/Std.

Das überrascht mich jetzt doch selbst. Dieser kleine Fehler scheint wohl 
tatsächlich die Ursache zu sein.

von Uwe (Gast)


Lesenswert?

Hi!
Du hast doch alles was du brauchst!
Interupt: 2-3 Zyklen (max.3us) Wieso 2-3 Zyklen?? Entweder 2 oder 3, 
einen Wechsel der Zykluszeiten kenne ich nicht. Also genau nachschauen!
TMR0 laden: 3 Zyklen

Du brauchst 125 Zyklen. Übrigens Timerüberlauf ist von
255->0= 256 Takte! Also berechnet sich dein Timerwert aus:
0-125+2 (oder auch 3) +3 (Das versteht eigentlich jeder Assembler) Das 
sind dann 136 oder 137 als Timerladewert.

Das wäre doch ein Unding wenn das nicht hinzubekommen ist.

MFG Uwe

von crazy horse (Gast)


Lesenswert?

als erstes müßtes du mal in Erfahrung bringen, was der Vorteiler bei 
einem Neuladen des Zählregisters so treibt. Läuft der durch (nehme ich 
an, weiß es aber nicht) können die paar Takte nicht der Fehler sein.
Der Vorteiler gibt einen Takt an den Zähler, Zähler läuft über und löst 
einen Int aus. Wenn du mit Vorteiler 32 arbeitest, mußt du nur zusehen, 
daß auf jeden Fall innerhalb der nächsten 32 Takte das Zählregister 
wieder mit dem neuen Startwert geladen ist, dann verlierst du nicht 
einen einzigen Takt.
Also Sprung zur ISR, Flags retten, neuen Zählerwert schreiben - das 
sollte doch wohl in 32 Takten möglich sein, es sei denn, der Prozessor 
treibt sich gerade in einer anderen ISR herum, dann wirds knapp. 
Prioritäten verteilen (wenn möglich) bzw. den Rest im Polling laufen 
lassen.

von HDW (Gast)


Lesenswert?

Hm.
Das stimmt eigentlich. Der interne Takt beträgt 1Mhz. Plus Vorteiler von 
32 bedeutet alle 32us Takt an den Timer.
Der Timer solte eigentlich innerhalb weniger us geladen sein.
32 us sollten da tatsächlich vollkommen ausreichen.

Dann kommt der Fehler aber nicht mehr hin.
Dann habe ich nur den Befehl, der gerade noch zuende ausgeführt wird, 
wenn der Interupt auftritt. Also meistens (außer Sprungbefehl) 1us plus 
2us für den Sprung zur ISR.
Dann wären das aber nur ca. 3s/Std Fehler, ich habe aber 9s/Std.

Ich muss ja eigentlich nur in jedem Interupt zusätzlich 10us vertrödeln. 
Ich habe gerade 10 nop-Befehle in der ISR eingefügt. Also 10us 
zusätzlich.

Der PIC, den ich gerade hier habe, habe ich aber schon mal halb 
gegrillt. Der wird unverschämt heiß. Ich fahr mir aber gleich ein paar 
neue holen und teste das dann einfach mal mit 10us zusätzlich.


mfg   Wolfram Hildebrandt

von crazy horse (Gast)


Lesenswert?

ich fürchte, du hast es immer noch nicht verstanden. Wenn der Timer 
nachgeladen ist, ist es völlig wurscht, wie lange du danach 
weitertrödelst, der nächste Int kommt exakt 4ms nach dem vorherigen. Die 
"Trödelzeit" spielt keine Rolle, der nächste Int kommt zwar dann relativ 
eher nach Verlassen der ISR, aber trotzdem genau 4ms nach der 
vorherigen.
Bei einem Fehler von 0,25% scheidet eigentlich auch der Quarz als 
Fehlerquelle aus, soweit liegen die nicht daneben.
Hast du mal nachgeschaut, was der Vorteiler beim PIC macht? Wenn der mit 
zurückgesetzt wird, ist das der Fehler. Kommt auch größenordnungsmäßig 
hin. Nach Timerüberlauf, ISR angesprungen und Timer nachgeladen sind 
etwa 10 Takte vergangen, der Vorteiler steht also eigentlich schon 
wieder auf 10, der nächste Impuls für den Timer müßte also nach weiteren 
22 Takten kommen. Wird der Vorteiler mit zurückgesetzt, kommt er aber 
erst nach 32 Takten, der Fehler bei 4ms: 4010/4000: 0,25%!

von HDW (Gast)


Lesenswert?

Hallo

Dass das mit der Verzögerung im Interupt Mist ist, stimmt.
Was ich wie lange in der ISR mache, ist ja egal, solange es nicht über 
4ms dauert. Dumm gedacht.

Ich habe gerade mal in einem meiner PIC-Bücher nachgesehen. Der 
Vorteiler wird durchaus immer bei jedem Schreiben oder Löschen des Timer 
zurückgesetzt!

von crazy horse (Gast)


Lesenswert?

na also.
Was kannst du jetzt tun? Sauberste Lösung wäre ein Quarzwechsel und den 
Timer ohne Vorteiler und ohne Nachladen komplett durchlaufen lassen. 
Geeignet z.B. 2.048MHz (1.024 ginge auch, weiß aber nicht, ob es die 
überhaupt gibt) , alle 125µs würde der Timer-Int ausgelöst.
Ansonsten per Software korrigieren, exakt ausklamüsern, wieviele Takte 
der Vorteiler verliert. Gibt dann mehrere Wege, das zu korrigieren. Da 
die Int-response-time aber wahrscheinlich nicht exakt angebbar ist, 
kommt es aber auch dabei zu weiteren unbestimmbaren Taktverlusten.
Oder du lässt den Timer ohne Nachladen durchlaufen und rechnest mit 
256µs als Zeitbasis, einfach in der ISR eine long-Variable 
incrementieren und daraus im Hauptprogramm eine darstellbare Zeit 
berechnen. Nach 337500000 Ints beginnt ein neuer Tag. Relativ viel 
Rechnerei, aber exakt.

von Peter D. (peda)


Lesenswert?

Schreib ich etwa mit unsichtbarer Tinte ?

Das mit dem durchlaufenden Timer hab ich doch oben schon alles 
beschrieben (Beitrag 19 und 20).


Peter

von HDW (Gast)


Lesenswert?

@ crazy horse:

Wie kommst du denn auf 125us Interupt?

Quarz 2048000Hz: interner Takt im PIC: 20480000/4= 512000Hz.
1/512000= 0,0000019s = 1,9us. 1,9us * 256 (voller TMR0)=0,0004864. Also 
alle 486,4us ein Interupt. Oder Denkfehler bei mir?

von HDW (Gast)


Lesenswert?

Korrektur:
1/512000= 0,000001953125. * 256 = 0,0005s =0,5ms.

von crazy horse (Gast)


Lesenswert?

wußte nicht, daß der PIC den Quarztakt erstmal durch 4 teilt.
125µs*4=0,5ms, dann stimmts doch wieder.

von HDW (Gast)


Lesenswert?

ja, habe ich mir schon gedacht. dass der AVR nicht durch 4 teilt, war 
mir bekannt. beim nachrechnen kam ich aber nicht auf dein ergebnis, weil 
ich mit einem billigen 8stelligen Taschenrechner gerechent habe. deshalb 
kam bei mir immer nur ein ähnliches ergebnis heraus (sehr viele 
nachkommanstellen).

Also, ich nehme einen Qaurz mit 2,048Mhz. Vorteiler aus. TMR0 
durchlaufen lassen. Dann habe ich alle 0,5ms einen Interupt, d.h. ich 
muss 2000 Interupts abwarten, bis 1s vorbei ist. Also acht mal eine 
Schleife von 250.

von crazy horse (Gast)


Lesenswert?

Kannst auch einen 4.096Mhz-Qarz nehmen, evtl. leichter zu beschaffen.

von HDW (Gast)


Angehängte Dateien:

Lesenswert?

Mist.
Bei einem Quarz von 2,048Mhz habe ich nur 500us/1,9us = ca. 263 mögliche 
Befehle in der ISR. Da liege ich aber deutlich drüber. D.h ich kann mein 
Programm nicht in so einer kurzen Zeit ausführen.
Mit 4,096Mhz komme ich wohl auch nicht hin.


Ich versuche nochmal die Real Time Clock DS1302. Die kann man dann über 
I2C auslesen.
Ob mit man auch ich gemeint bin, wird sich zeigen. Der PIC 16F876 hat 
für I2C eine Hardwareunterstützung.
Ist denn der DS 1302 voll I2C kompatibel? (Sieht für mich zumindest so 
aus.)
Datenblatt im Anhang.

von Peter D. (peda)


Lesenswert?

O.K. ich gebe auf.

Ich habe doch schon alle nötigen Reloadwerte für 4MHz hingeschrieben.

Oder wird heutzutage das Rechnen mit gebrochenen Zahlen nicht mehr 
gelehrt ?


Peter

von crazy horse (Gast)


Lesenswert?

Mann oh mann, langsam wirds lästig.
Letzter Versuch. Gehen wir einfach mal von 4.096MHz/250µs Interrupt aus.
In der ISR machst du weiter nichts, als bis 4000 zu zählen. Bei 4000 
wird der Zähler wieder auf 0 gesetzt und ein Flag gesetzt, welches 
anzeigt: eine Sekunde ist um!
Im Hauptprogramm kannst du dann in aller Seelenruhe dein Uhrprogramm 
laufen lassen.

Sekundenbit gesetzt?
nein->weiter warten
ja->Bit zurücksetzen,Sekundenzähler erhöhen, evtl Minuten erhöhen, evtl 
Stunden erhöhen
Anzeige aktualisieren

von HDW (Gast)


Lesenswert?

Ja, das stimmt. Wenn ich ein Flag setze, wenn 250us * 4000 =1s vorbei 
sind, und dies dann außerhalb auswerte, habe ich keine Zeitprobleme in 
der ISR. Man möge mir meine Anfängerfehler bitte verzeihen.


Ich wollte eigentlich noch weiter gehen und Tage, Wochen und Monate 
zählen.
Aber der DS 1302 kann das ja alles. Das ist eigentlich sehr viel 
effektiver als alles selbst zu schreiben.
Nur die Auswertung per I2C habe ich noch nicht hinbekommen.
Aber das MSSP-Modul des 16f876 habe ich da noch nicht gekannt (das ist 
u.a. für I2C zuständig).
Hat schon mal jemand eine ähnliche Real Time Clock ausgewertet?

von geloescht (Gast)


Lesenswert?

Dieser Beitrag wurde auf Wunsch des Autors geloescht.

von Steffen (Gast)


Lesenswert?

Wenn Du den 16F876 verwenden willst, warum nutzt du dann nicht das 
CCP-Module? Dann gibt es nicht den Fehler mit den 3 oder 4 Zyklen bis 
zum Einsprung in die ISR und man kann leicht die Uhr auf den verwendeten 
Resonator bzw. Quarz abgleichen.

MfG
Steffen

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.