unbekannte Quarz Frequenz

Gast #399878
Lesenswert?

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

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

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

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

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

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
#399898
Lesenswert?

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

@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...
#399900
Lesenswert?

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

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

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

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

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

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

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

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

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