Hallo, ich habe hier ein Quarz in einer von mir zu analysierenden schaltung gefunden. er hängt an einem controller, und seine frequenz beträgt 22,1184Mhz. der controller macht eigentlich nur ein wenig multiplexing und polling, also nicht zeit spezifisches wie: serielle schnittstelle, oder uhrfunktionen... bin bei testüberlegungen mit unterschiedlichen teilern auf keine brauchbare frequenz gekommen.... maddin
Also was ist eigentlich dein Problem? Die Frequenz scheinst du ja wohl zu kennen.
22,1184 MHz ist ein Baudratenquarz. Dein "Problem" an sich kann ich allerdings auch nicht ganz nachvollziehen.
Hallo, entschuldigung, habe ´mich da wohl etwas unklar ausgedrückt!? ich suche natürlich denn sinn, oder die Funktion dieser Frequenz. maddin
Hi, haben hier ja gerade schon so eine diskussion gehabt http://www.mikrocontroller.net/forum/read-1-408554.html#new doch leider habe ich auf der angegebenen seite: http://www.hanneslux.de/avr/tipps/baudratenquarz.html diesen nicht gefunden. nun betont der autor die unvollständigkeit seiner liste, ich meine aber in dem thread letzte w gelsen zu haben, das man mit vielen Baudratenquarzen auf 1Hz kommt. Mit diesem hier scheinbar nicht. maddin
Hallo, wenn die Funktionen keine Erklärung liefern, gibt es vielleicht einfach keine. Dann bliebe noch: waren noch 5000 Stück von im Lager, kostete 3ct weniger als 20MHz, wer der erste Quarz, der dem Entwickler beim Prototyp-Bau in die Hände fiel oder oder oder... ;) Gruß aus Berlin Michael
Hmm Ok das klingt gut. naja, ich hatte gehofft die frequenz für eine uhrenfunktion nutzen zu können, aber bei dem teilungsfaktor :-) dann schmeiß ich ihn runter und bleibe bei meinen: 4,194304Mhz (2^22) da geht die uhr dann richtig :-) maddin
Du schreibst er macht multiplexing. Vielleicht wurde die Frequenz für einen speziellen Multiplextakt benötigt? bye Frank
@Frank, hmm, kann ich mir nicht vorstellen. also um eine dispplay zu multiplexen braucht es doch eigentlich keine so spezifische frequenz, oder!?da scheint mir die aussage von christoph doch logischer .-) @Christoph Kessler dank dir, so wie es scheint - mit dem teiler 12 geht es ja glatt auf. dann wirds wohl ein baudratenquarz sein. :-) dank euch, maddin
22,1184 ist wie 11,0592 eine typische Quarzfrequenz für 51er Controller, deren interner Systemtakt der Quarztakt durch 6 ist. Die resultierenden 3,6864MHz sind dann für genaue Baudraten gut, und für genaue 1s reicht ein 8Bit-Timer (Periode=225T) nach 2^14 Vorteilung.
Das Quarz läßt sich doch super teilen: 22118400 = 2^15 * 3^3 * 5^2 Und für Baudraten ist es auch prima: 22118400 115200 16 = 12 Peter
hmm bin auch gerade am würfeln... nutze einen pic für dieses problem. interne vorteilung von 4...dann ein einstellbarer prescaler: /1 /2 /4 /8 /16 .... /256 maddin
@Peter Dannegger die teilung durch 6 fehlte mir ... jetzt so langsam... :-) maddin
Zähl einfach mit einem counter der mit der Quarzfrequenz läuft bis 22118400 hoch, wenn du angekommen bist setzt du den counter zurück... und schon hast du deine 1Hz (mit Vorteiler wäre das ganze sinnvoller)
@Lupin der pic ist ein 8bitter und hat eine vorteilung von 4, zudem programmiere ich den in asm! da muss man sich die teilungen etwas geschickter zusammenfrickeln als in c. bin jetzt bei /4 prescaler auf /256 ergibt: 21,6Khz...
Ja und, wo ist das Problem? Mit den 21600 Hz treibst Du Deinen Timer, der meinetwegen durch 216 teilt, dann hast Du alle 10 ms einen Überlauf. Abgleichen kannst du auf 0.46% (1/216 = 4629 ppm) genau, das ist für eine Uhr zu wenig. Du kannst es aber auch anders machen, damit du die volle Abgleichbarkeit der Uhr hast. Nämlich so, wie die DDS es macht: Du addierst z.B. in eine 48-bit-Variable die real vergangene Zeit als 32.16-bit Fixedpoint-Zahl. Oder für höhere Auflösung eine 56-bit-Variable mit 32.24-fixed Point. Dann kannst Du in den oberen 32 Bit direkt die Zeit in Sekunden ablesen. Beispiel: wie oben Überlauf-Interrupt mit 10ms, Du musst also 0.01 als FixedPoint (655 = 0x28F bei 16 Bit, 4*256*216/22118400*2y24=167772 = 0x28F5C bei 24 Bit) auf die Nachkomma-Stellen addieren. Wenn Du das 100 mal machst, also eine Sekunde vergangen ist, gibt es einen Überlauf von den Nachkommabits in die Vorkommabits, die Sekunden werden also um eins hochgezählt. Der Vorteil ist, dass Du jetzt die Uhr durch Variieren des Summanden sehr genau justieren kannst (bei 100 Hz und 24 Bit auf 6ppm genau). Außerdem kannst Du durch geschicktes Skalieren jede gewünschte Zeitbasis mit beliebigem Teilfaktor erzeugen. Willst Du z.B. den Teiler statt mit 216 mit 220 betreiben, musst Du halt 4*256*220/22118400*2y24=170879 statt 167772 addieren. Hat der Quarz eine Abweichung, kannst Du ihn damit digital trimmen. Nehmen wir an, er geht um 100 Hz zu langsam: 4*256*220/22118300*2y24=170880. Wenn Du jetzt noch einen Temperatursensor hast, kannst Du den richtigen Summanden aus einer Kompensationstabelle auslesen. So hast du eine digital temperaturkompensierte Uhr. Very tricky, nicht wahr? So ähnlich funktioniert auch der Bresenham-Algorithmus.
>Du addierst z.B. in eine 48-bit-Variable die real vergangene Zeit als 32.16-bit Fixedpoint-Zahl. ich verstehe die aussage nicht, aber wenn es irgentwoh steht, dann kann ich mir das ja mal ansehen. auch wenn mein pic nur ein kleiner 8bitter ist, und ich mir die routinen eben selber basteln müsste, aber ginge denke ich. es ist mir nur noch nicht ganz klar, was du da auch wen addierst, werde aber mal nach der DDS (was auch immer das sein mag - google xyz keine aussage)mal hier im forum suchen... >Der Vorteil ist, dass Du jetzt die Uhr durch Variieren des Summanden sehr genau justieren kannst (bei 100 Hz und 24 Bit auf 6ppm genau). mit summanden kannst du nicht die 0.01 meinen, oder -das passt dann doch nicht - also macht keinen sinn...iuch verstehe schon den hintergrund, aber deine aussagen noch nicht ganz... ich stelle mir das so vor: ich habe eine variable in der leigt der wert 22.1184Mio /4 (da 4 fest) jetzt zähle ich einen timer mit 22.1184Mhz /4 hoch. ich vergleiche variable mit timer. sind sie gleich. zähle ich die uhr um 1sec hoch und beginne von neuem. für einen abgleich ändere ich die zahl in der variablen nach oben oder unten. >Temperaturkompensation: bei den meisten quarzen kann man doch froh sein, wenn man überhaupt ein einseitiges datenblatt findet - oder!? geschweige denn - man weiß überhaupt von welchem hersteller dieser quárz ist! naja, ansonsten müsste man sich sowas selbst aufstellen - was denke ich sehr aufwändig ist, oder? >Bresenham-Algorithmus ich kenne den bis heute nur als algorithmus um linien und kreise in eine rasterung x,y zu rechnen... vielen dank für diese ausführliche darstellung - ich würde es wirklich gern komplett nachvollziehen. maddin
Ich weiß, es ist ein wenig zum Um-die-Ecke-denken. Denk Dir nichts, ich hab's beim ersten Mal auch nicht gleich verstanden. Das mit den großen BitZahlen ist auch für einen 8-Bitter ein Klacks: dafür gibt es ja den ADC(ADD with Carry)-Befehl. Nehmen wir mal einen einfachen Fall mit "geraden" Zahlen: Deine Interruptquelle (z.B. Timer) läuft mit 256 Hz. Du möchtest einen 16-bit-Sekundenzähler haben. Dann kannst Du: 1. in der ISR eine 8-Bit-Variable hochzählen, wenn die einen Überlauf macht, addierst Du eins zu den Sekunden. 2. in der ISR eine 16.8-FixedPoint(=24-Bit)-Zahl um 0x0.01 incrementieren. Das ist genau das selbe! Der Übertrag passiert bei 1 explizit und bei 2 beim ADC-Befehl im Carry vom letzen ins vorletzt Byte. Wenn Du das mal verinnerlicht hast, ist schon ein großer Schritt getan. So, als Zwischenlektion die Funktionsweise von FixedPoint: Bit Wertigkeit 15 32768 14 16384 .... 7 128 6 64 5 32 4 16 3 8 2 4 1 2 0 1 Die Wertigkeit wird also immer um 2 geteilt. Warum nicht einfach ein Byte "dranhängen" und weitermachen? -1 1/2=0,5 -2 1/4 -3 1/8 -4 1/16 -5 1/32 -6 1/64 -7 1/128 -8 1/256=0,00390625 Wenn Du diese 16+8=24 Bits als zusammenhängende 24-Bit-Zahl siehst und damit rechnest, hast Du sozusagen um 256 skaliert. So, und nun zurück zum Interrupt: nehmen wir an, der hat jetzt nicht 256 Hz, sondern 128. Was machen wir, um das Bit 0 wieder im Sekundentakt zu erhöhen? Ganz einfach, wir addieren 2 (0x0.02) statt 1 auf die 24-Bit-Zahl. Was passiert, wenn wir 3 (0x0.03) addieren? Dann muss der Interrupt mit 85,3333Hz kommen. Und bei 4 mit 64Hz. Gut, was ist, wenn der Interrupt aber mit 100 Hz kommt? Dann brauchen wir mehr als 8 Nachkommabits (z.B. 16.24), denn 1/100 ist in Binär 0.000000101000111101011100..., also 0.028F5C.... Der Interrupt kann mit jeder beliebigen Frequenz kommen, sogar seltener als 1 Hz, dann musst Du entsprechend viel addieren (also mehr als 0x1.00). Temperaturkompensation: Ja, die Tabelle passt nur auf den einen Quarztyp. Ist im Quarzkochbuch schän beschrieben. Mann muss sie in einem "Quarzofen" z.B. mit einem Peltier-Element (bipolar angesteuert, d.h. heizen und kühlen), einem Temperatursensor (z.B. Dallas) und einem Frequenzzähler erstellen. Die Analogie zum Bresenham: Sekunde = Schritt in seltener Richtung Interrupt = Schritt in häufiger Richtung Interruptfrequenz = Steigung der Geraden
Man kann das auch mit gebrochenen Zahlen rechnen, z.B. hier: http://www.mikrocontroller.net/forum/read-4-405548.html#new Im Interrupt wird alle 256 Sekunden ein anderer Reloadwert genommen, kein Mensch merkt das. Aber er würde es merken, wenn nach Stunden oder Tagen mehrere Sekunden Fehler entstehen und dem wirkt die Korrektur entgegen. Besonders angenehm ist, daß der Compiler alle Werte ausrechnet, man muß nur die genaue Quarzfrequenz eintragen. Peter
@Profi, au man ist das eine geile idee. jetzt wars sofort klar. fixet point zahlen, und die wertigkeiten waren kein problem, trotzdem vielen dank. schreibe meine rechenroutinen immer alle selbst. an der stelle: >Gut, was ist, wenn der Interrupt aber mit 100 Hz kommt? Dann brauchen wir mehr als 8 Nachkommabits (z.B. 16.24), denn 1/100 ist in Binär 0.000000101000111101011100..., also 0.028F5C.... war der sinn und auch der unterscheid sofort klar.... also, dann würde ich immer auf den übertrag in die erste volle stelle achten, und wenn das bit gesetzt ist, dann 2sekunde weiterzählen.... anschließend nur die 1.xxxx auf 0.xxxx setzen und wie gewohnt weiter addieren. >Der Interrupt kann mit jeder beliebigen Frequenz kommen, sogar seltener als 1 Hz, dann musst Du entsprechend viel addieren (also mehr als 0x1.00). sagen wir mal er kommt mit 0.5 hz. dann müsste ich nun ja 2.00 addieren. dann würde mit meiner routine, die uhr alle 2 sekunden um 2sekunden erhöht werden, und ich müsste auf die 2 im interrupt reagieren, wenn ich einen feinabgleich machen wollte - oder sehe ich das falsch... >Du musst also 0.01 als FixedPoint 655 = 0x28F wie kommst du auf die 655 - habe bis eben gedacht die mathematik ist hinterm komma, die selbe wie vor dem komma aber.: 0.01 x 100 ist 1 dezimal gesehen 0x28F x 0x64 ist 0xfddc ich hätte jetzt etwas mit übertrag in eine nächste stelle erwartet - habe ich einen denkfehler...??? klar kommt man mit der methode: die nächstgrößere wertigkeit von umzurechnenden zahl abzuziehen irgentwann an das ergebniss, doch es muss doch auch einfacher gehen... >Der Vorteil ist, dass Du jetzt die Uhr durch Variieren des Summanden sehr genau justieren kannst (bei 100 Hz und 24 Bit auf 6ppm genau). wie kommst du bei 24 bis auf die 6ppmm entschuldige die vielen fragen, aber das ganze ist jetzt so reizvoll, das ich es gern genau wissen würde .-) @Peter das problem ist ja, das ich das ganze in pic asm mache- und ich muss mir die rechenroutinen da mal selber basteln. dein projekt habe ich natürlich auch schon gesehen, und einer meiner posts ging ja auch mit als allererstes in deinem thread ein - da ich momentan an etwas vergleichbarem gearbeitet habe - nur mit etwas anderen bauteilen - mehr stellen und einem pic. das ganze ist mehr ein umbau - und es sind noch zusätzlich ein kalender zur wochentagsbestimmung und ein menü integriert :-) maddin ps.: momentan ist es bei mir genau so. ich habe einen 8bit zähler von 0-255 und beim überlauf, zähle ich 1 sec weiter - eine sehr starre geschichte im gegensatz zu der fixed point lösung...
@Maddin, "das problem ist ja, das ich das ganze in pic asm mache- und ich muss mir die rechenroutinen da mal selber basteln." mußt Du nicht. Der Trick ist, daß alles Konstanten sind, die schon zur Compilezeit ausgerechnet werden. Wenn der PIC-Assembler keine 23Bit Konstanten ausrechnen kann, kann mans also auch in den Taschenrechner eintippen und die Ergebnisse direkt laden. Peter
@Profi, habs: 0x1000000 / 0x64 = 0x28f5c2...natürlich geht das immer so weiter...und ist ein maß für die genauigkeit.... ist klar (ist sogar periodisch ab der 5ten stelle) ist doch so wie ich mir das vorgestellt habe.... @Peter interessant. ist es diese stelle im code: if( --sec_timer == 0 ){ one_second = 1; sec_timer = INTTIME; if( --corrector == 0 ){ // correction n / 256 sec_timer = (XTAL - 255UL 8 INTTIME + 4) / 8; } } vielleicht könntest du mir den hintergedanke etwas näher bringen... Maddin
Schönen Abend, zu DDS schreibe ich gerade einen kleinen Wiki-Artikel. Das freut mich, dass es Klick gemacht hat. Damit es Doppel-Klickt, noch ein paar Ausführungen: "also, dann würde ich immer auf den übertrag in die erste volle stelle achten, und wenn das bit gesetzt ist, dann 2sekunde weiterzählen.... anschließend nur die 1.xxxx auf 0.xxxx setzen und wie gewohnt weiter addieren." Es kommt darauf an, was Du mit den Sekunden anstellen willst. Ob Du sie als 16-32 Bit-Zahl willst, oder ob 8 Bit (0..59) ausreichen. Zuerst mal noch der Hinweis, dass Du garnicht explizit auf den Übertrag achten musst. Du siehst z.B. die 16.24-FixedPoint-Zahl als *eine 40-Bit-Zahl* und addierst den Summanden mit add summebyte0,summandbyte0 adc summebyte1,summandbyte1 adc summebyte2,summandbyte2 adc summebyte3,summandbyte3 adc summebyte4,summandbyte4 Der Übertrag findet automatisch im adc von Byte2 auf Byte3 übers Carry-Flag statt. Wenn Du die Sekunden als 16-Bit willst, betrachtest Du einfach nur summebyte3 und summebyte4 als 16-Bit-Zahl. "sagen wir mal er kommt mit 0.5 hz. dann müsste ich nun ja 2.00 addieren." Exakt. "dann würde mit meiner routine, die uhr alle 2 sekunden um 2sekunden erhöht werden, und ich müsste auf die 2 im interrupt reagieren, wenn ich einen feinabgleich machen wollte - oder sehe ich das falsch..." Verstehe ich jetzt nicht ganz. Den Feinabgleich machst Du, indem Du eben nicht exakt 2.000000 addierst, sondern 2.000001 oder 1.ffffff. Ja das stimmt, die Uhr würde alle 2 Sekunden um 2 Sekunden weiterschalten - oder bei einer Korrektur mal 3 oder 1 Sekunde. "wie kommst du auf die 655 - habe bis eben gedacht die mathematik ist hinterm komma, die selbe wie vor dem komma aber.:" 655 ist es bei x.16 , weil (2^16) * 0,01=655,35 "0.01 x 100 ist 1 dezimal gesehen" Ja. "0x28F x 0x64 ist 0xfddc ich hätte jetzt etwas mit übertrag in eine nächste stelle erwartet - habe ich einen denkfehler...???" Dass es jetzt noch nicht zum Übertrag kommt, liegt daran, dass wir das ,35 ständig unterschlagen haben. Deshalb wird das mit mehr Nachkommabits genauer. "klar kommt man mit der methode: die nächstgrößere wertigkeit von umzurechnenden zahl abzuziehen irgentwann an das ergebniss, doch es muss doch auch einfacher gehen..." ??? Könntest Du mir das nochmal erklären? "wie kommst du bei 24 bis auf die 6ppmm" 100(Hz) / (2^24) = 0,0000059604644775390625 "entschuldige die vielen fragen, aber das ganze ist jetzt so reizvoll, das ich es gern genau wissen würde .-)" Diese Einstellung gefällt mir! Da gibt's nichts zu entschuldigen. @Peter: Das ist natürlich die wesentlich einfachere Methode, ab und zu mal einen anderen Timerwert zu verwenden. Wobei ich zugeben muss, dass ich die entsprechenden Zeilen beim Überfliegen nicht gleich verstanden habe. Ich schaue sie mir bei Gelegenheit nochmal an.
Ich habe sehr gute Erfahrungen mit wechselnden Reload-Werten gemacht, mit etwas Geduld und viel Probiererei kann man durch geschickte Wahl der Reload-Werte die Quarz-Abweichungen nahezu vollständig ausgleichen. Komme so bei einem aktuellen Uhr-Projekt auf eine Abweichung von ca. 0,2ppm ohne jetzt noch weiter verbessern zu wollen. Abweichung ist ermittelt unter normalen Temperaturbedingungen im Wohnraum.
Warum eigentlich wechselnde Reload-Werte? Ich mach das immer per Addition (Ist-Wert + Reload-Wert) - mit nem AVR und >256er Timer-Vorteiler geht das normal gut. Mit PICs hab ich da keine Erfahrung (mehr).
@Johannes, die Addition ist nur nötig, wenn man den Timer laden will und er ungebremst läuft. In meinem Code läuft der Timer aber konstant 1024 Zyklen und das Reload erfolgt in einen Softwareteiler für 1s. Dieser Teiler zählt bis 0 runter und wird dann neu geladen. Zusätzlich zählt ein Byte runter und ist somit alle 256 Sekunden 0, dann wird ein anderer Wert geladen, der dem Fehler * 256 entspricht. Der Fehler ist also ein Bruch mit dem Nenner 256 und kann je nach Quarzfrequenz 0...255 sein. Ist er 0, dann optimiert der AVR-GCC die Korrektur komplett weg. Die ominöse 8 in der Berechnung des Korrekturwertes kommt von der Interruptrate (1024) und dem Korrekturintervall (256), also 1024 / 256 = 8. Die 255 in der Formel kommt daher, da ja 255 mal der Reloadwert geladen wird und das 256. mal aber der Korrekturwert. Peter
@Peter Du hast Recht, die letztliche Macht hat die Software. Aber mir geht es eigentlich um die Software, die überhaupt erstmal sagt, welchen Takt die Systemuntereinheiten bekommen. Johannes
Morgen!
@Profi
vielen Dank für die lange und ausführliche Antwort. dann würde mir bei
der implemntierung dieser sache eigentlich nur noch eine kleinigkeit im
wege stehen.
ich will natürlich dem nutzer dieser uhr die möglichkeit geben sie
selbst etwas zu trimmen. jetzt müsste ich ein geeignetes raster - also
eine geeigneten delta summanden finden - so das man mit den tasten +/-
einen gúten abgleich machen kann.
ich stelle mir das so vor, das ich auf den eigentlichen summanden dann
den wert von delta ppm addiere oder subtrahiere. bei jedem tastendruck
verringere - vergrößere ich den summanden um delta ppm.
>>>??? Könntest Du mir das nochmal erklären?
ich meinte die allzeit bekannte methode um dezimalzahlen nach binär
sozusagen zufuß um zu rechnen. bsp.: 0.73
wertigkeit 2^-1 0.5 passt in 0.73 rest 0.23 bit = 1
wertigkeit 2^-2 0.25 passt nicht in 0.23 rest 0.23 bit = 0
wertigkeit 2^-3 0.125 passt in 0.23 rest 0.105 bit = 1
wertigkeit 2^-4 0.0625 passt in 0.105 rest 0.0425 bit = 1
aus den ersten 4 bit 1011 kann man hex 'b' machen
usw.... musste es erst per hand versuchen, da die zahlen nicht zu
stimmen schienen
@Oliver
könntest du mir verraten wie du eine abweichung von 0.2ppm so genau
bestimmen konntest.
ich würde die uhr ein jahr laufen lassen und gucken wieviele sekunden
sie nach bzw vor geht. und daraus dann die abweichung berechnen.
dann benötige ich ein weiteres jahr um zu sehen ob sich die abweichung
wiederholt.
dann gleiche ich sie ab!? mit dem passenden korrekturfaktor...
da bin ich ja ewig bei - wie bekomme ich das in weniger zeit hin!?
maddin
Habe das erzeugte Sekundensignal auf externen Port gelegt und mich erstmal mit einem Logic-Analyzer rangetastet, da hat man schon gute Anhaltswerte, ohne immer sehr lange Messzeiten in Kauf nehmen zu müssen. Dann mal eine Woche laufenlassen, Korrektur wieder verändern. Aber um die endgültige Ungenauigkeit zu bestimmen, habe ich sie dann schon 1 Monat laufen lassen und am Schluss die Abweichung zum DCF Signal gemessen.
...das wäre natürlich auch was.... ein dcf modul einen monat an die uhr stöpseln, und eine routine schreiben, die die fehlerkorrektur automatisch macht... nach einem monat kann das dcf modul abgezogen werden, und die uhr ist weitgehend genau :-) ja klar, jetzt kommt wieder: aber dann kannst du das modul auch gleich dran lassen - die kosten doch nur 10... stimmt alles! aber wenn man mehrere uhren eigentlich ohne dcf modul plant - ist es eine gute lösung :-) maddin
Hallo, auch hier möchte ich mich nochmal für die vielen hinweise bedanken, im Anhang findet ihr ein kleines bildchen des aktuellen standes der Kalender/Uhr. Maddin
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.