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
Gönn deinem Quarz mal einen Ziehkondensator, so kannst du die Feineinstellung der Frequenz optimieren und deine 4s ganz bestimmt kompensieren..
ü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.
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
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
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.
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??
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...
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
Ü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
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?
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.
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?
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.
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
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
Sorry, ein Dreckfuhler hat sich eingeschlichen, es muß natürlich heißen: "Wenn Du dann einmal je Minute einen anderen Teilerwert (126) nimmst,..." Peter
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.
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
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.
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
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%!
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!
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.
Schreib ich etwa mit unsichtbarer Tinte ? Das mit dem durchlaufenden Timer hab ich doch oben schon alles beschrieben (Beitrag 19 und 20). Peter
@ 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?
wußte nicht, daß der PIC den Quarztakt erstmal durch 4 teilt. 125µs*4=0,5ms, dann stimmts doch wieder.
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.
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.
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
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
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?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.